HIGH zip slipfiberdynamodb

Zip Slip in Fiber with Dynamodb

Zip Slip in Fiber with Dynamodb — how this specific combination creates or exposes the vulnerability

Zip Slip is a path traversal vulnerability that occurs when an application constructs file paths from user-supplied input without proper validation. In a Go Fiber application that interacts with Amazon DynamoDB, the risk emerges at the intersection of HTTP request handling, file system operations, and data modeling choices in DynamoDB.

Consider a scenario where a Fiber handler accepts a filename or key from a client and uses it to read or write objects in DynamoDB, then later performs filesystem operations based on that key. If the input is not strictly validated, an attacker can provide a specially crafted value such as ../../../etc/passwd. When the application uses standard path joining (for example, filepath.Join(uploadDir, userInput)) without cleaning or restricting path segments, the resulting path escapes the intended directory. This allows reading or overwriting arbitrary files on the host, which can lead to information disclosure or code execution depending on the runtime context.

DynamoDB itself does not execute paths, but it can store metadata or keys that later influence file system behavior. For example, an item might contain an attachmentKey attribute that the application uses to build local file paths. If the application trusts this stored value and uses it directly in path operations without sanitization, the DynamoDB entry becomes a vector for persisted malicious payloads. Additionally, if the application uses DynamoDB conditional writes or streams to trigger downstream processing (e.g., invoking local scripts or parsers), crafted input stored in DynamoDB can be executed in a vulnerable context when the processing logic builds file paths unsafely.

The combination is particularly dangerous because Fiber’s performance and simplicity can encourage developers to skip rigorous input validation, assuming that DynamoDB acts as a safe, structured store. However, DynamoDB only enforces constraints you define; if your data model does not restrict path-like attributes, and your application code performs unsafe path concatenation, the vulnerability exists at the application layer, not the database layer. Attackers exploit this by sending malicious HTTP requests that leverage the Fiber route handling, ultimately manipulating local filesystem paths through unchecked values originating from or influenced by DynamoDB-stored data.

Dynamodb-Specific Remediation in Fiber — concrete code fixes

To remediate Zip Slip in a Fiber application that uses DynamoDB, you must validate and sanitize any path derived from user input or from data stored in DynamoDB before using it in filesystem operations. Below are concrete code examples for a Fiber handler that safely manages file keys while interacting with DynamoDB.

First, define a strict allowlist for filenames and use path.Clean and filepath.Rel to ensure paths remain within the intended directory. Combine this with parameterized DynamoDB operations to avoid injection of malicious metadata.

// main.go
package main

import (
    "fmt"
    "net/http"
    "path/filepath"
    "strings"

    "github.com/gofiber/fiber/v2"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
    app := fiber.New()

    // Load AWS config (assumes proper environment or IAM configuration)
    cfg, err := config.LoadDefaultConfig(app.Context())
    if err != nil {
        panic(fmt.Errorf("unable to load SDK config: %w", err))
    }
    client := dynamodb.NewFromConfig(cfg)

    app.Post("/upload", func(c *fiber.Ctx) error {
        // Expect JSON: { "key": "user123/report.txt" }
        type RequestBody struct {
            Key string `json:"key"`
        }
        var body RequestBody
        if err := c.BodyParser(&body); err != nil {
            return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
        }

        // Validate key: allow only alphanumeric, underscores, hyphens, and a single dot for extension
        if !isValidKey(body.Key) {
            return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid key format"})
        }

        // Ensure the key is relative and does not escape the base directory
        base := "uploads"
        cleanKey := filepath.Clean("/" + body.Key)
        if rel, err := filepath.Rel(base, cleanKey); err != err || strings.HasPrefix(rel, "..") {
            return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "path traversal detected"})
        }

        // Store metadata in DynamoDB using the validated key as a partition key
        _, dErr := client.PutItem(c.Context(), &dynamodb.PutItemInput{
            TableName: aws.String("Attachments"),
            Item: map[string]types.AttributeValue{
                "Key": &types.AttributeValueMemberS{Value: body.Key},
                "Owner": &types.AttributeValueMemberS{Value: c.IP()}, // example attribute
            },
        })
        if dErr != nil {
            return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "failed to store metadata"})
        }

        // Safe filesystem write using the cleaned relative path
        finalPath := filepath.Join(base, rel)
        if err := c.SaveFile(c.FormFile("file"), finalPath); err != nil {
            return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "unable to save file"})
        }

        return c.JSON(fiber.Map{"message": "uploaded"})
    })

    app.Listen(":3000")
}

func isValidKey(key string) bool {
    // Allow letters, digits, underscore, hyphen, dot, and slashes for directory-like keys
    // but ensure no null bytes or shell metacharacters
    for _, r := range key {
        if !(r == '/' || r == '.' || r == '-' || r == '_' || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || (r >= 'A' && r <= 'Z')) {
            return false
        }
    }
    return key != "" && !strings.Contains(key, "..")
}

This approach ensures that any key used with DynamoDB is validated before being stored or used in filesystem paths, effectively mitigating Zip Slip in the Fiber + DynamoDB context.

Frequently Asked Questions

Can DynamoDB stored values alone cause Zip Slip, or does the vulnerability require malicious filesystem code?
DynamoDB stored values do not cause Zip Slip by themselves; the vulnerability requires that your application later uses those values in unsafe filesystem path operations. If you validate and sanitize any path derived from DynamoDB data before using it in file joins, the risk is eliminated.
Does enabling DynamoDB encryption at rest protect against Zip Slip?
No. Encryption at rest protects data confidentiality on disk but does not affect path traversal logic. Zip Slip is about unsafe path resolution in your application code; you must still validate and clean paths independently of DynamoDB encryption settings.