HIGH zip slipginapi keys

Zip Slip in Gin with Api Keys

Zip Slip in Gin with Api Keys — how this specific combination creates or exposes the vulnerability

Zip Slip is a path traversal vulnerability where an attacker-controlled archive leads to files being extracted outside the intended directory. When an API built with the Gin framework uses static file serving and also relies on API keys for access control, the combination can expose sensitive files if path validation is weak and authentication is misunderstood as authorization.

In Gin, a typical pattern is to use Static or StaticFile to serve assets, often behind a handler that checks for an API key in a header. If the API key gate is applied only to the route entry point and not enforced per-file, and if user input directly influences the file path without proper sanitization, an authenticated request (with a valid API key) can traverse directories. For example, a request like /download?file=../../../etc/passwd may pass the API key check and then allow reading files outside the public folder. This means the presence of API keys does not automatically prevent path traversal; it can create a false sense of security if validation is limited to authentication alone.

The vulnerability is realized when the server concatenates user input to a base directory without canonicalizing the path and ensuring it remains within the intended prefix. An attacker with a valid API key can exploit this to read arbitrary files (e.g., source code, configuration, or secrets) or, in more severe cases involving writable endpoints, write malicious content. Note that API keys in Gin are typically validated in middleware, but if the middleware does not reject requests with invalid or missing keys for all downstream handlers, or if path traversal is possible in static file handling, the attack surface remains.

middleBrick scans such endpoints (including those using API keys) and tests the unauthenticated attack surface; if your API exposes file-serving routes without strict path validation, a scan can identify related findings like Path Traversal. Remember, middleBrick detects and reports — it does not fix or block — so you must apply secure coding practices to remediate.

Api Keys-Specific Remediation in Gin — concrete code fixes

To fix Zip Slip in Gin when API keys are used, ensure strict path validation and keep authentication separate from authorization logic. Use filepath.Clean and verify that the resolved path remains within the allowed directory. Do not rely on API key middleware alone to prevent path traversal.

Example of an insecure handler that concatenates user input and is vulnerable to Zip Slip:

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
    "path/filepath"
    "strings"
)

func main() {
    r := gin.Default()
    r.GET("/download", func(c *gin.Context) {
        requestedFile := c.Query("file")
        // Insecure: no path cleaning or base restriction
        fullPath := filepath.Join("/var/www/public", requestedFile)
        c.File(fullPath) // Zip Slip possible
    })
    r.Run()
}

Remediation steps:

  • Canonicalize and restrict the file path using filepath.Clean and ensure it does not escape the base directory.
  • Validate the file extension and type if applicable.
  • Use http.Dir with Open and Readdir for more control, or use http.ServeFile with a computed safe path.
  • Keep API key validation in middleware but ensure it applies to all routes; do not assume a key permits access to all filesystem paths.

Secure example with path validation:

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
    "os"
    "path/filepath"
)

func safeFilePath(base, requested string) (string, error) {
    clean := filepath.Clean(requested)
    if strings.Contains(clean, ".."+string(os.PathSeparator)) {
        return "", os.ErrInvalid
    }
    full := filepath.Join(base, clean)
    if rel, err := filepath.Rel(base, full); err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
        return "", os.ErrInvalid
    }
    return full, nil
}

func main() {
    r := gin.Default()
    r.GET("/download", func(c *gin.Context) {
        requestedFile := c.Query("file")
        const baseDir = "/var/www/public"
        filePath, err := safeFilePath(baseDir, requestedFile)
        if err != nil {
            c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid file path"})
            return
        }
        // Ensure file exists and is within baseDir
        if _, err := os.Stat(filePath); os.IsNotExist(err) {
            c.AbortWithStatus(http.StatusNotFound)
            return
        }
        c.File(filePath)
    })
    r.Run()
}

Additionally, if you use API keys via middleware, ensure it rejects requests before they reach the file handler:

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func apiKeyMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("X-API-Key")
        if token != "YOUR_SECRET_KEY" {
            c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid api key"})
            return
        }
        c.Next()
    }
}

func main() {
    r := gin.Default()
    r.Use(apiKeyMiddleware())
    r.GET("/public", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "public endpoint"})
    })
    r.Run()
}

By combining secure path handling with consistent API key validation, you reduce the risk of Zip Slip and ensure that authenticated access does not inadvertently expose filesystem traversal.

Frequently Asked Questions

Does using API keys in Gin prevent Zip Slip vulnerabilities?
No. API keys provide authentication but do not prevent path traversal. You must validate and sanitize file paths independently.
How can I test my Gin API for Zip Slip and API key handling?
Use a scanner like middleBrick to test unauthenticated and authenticated scenarios; also perform manual path traversal tests with valid and invalid API keys to confirm behavior.