HIGH zip slipchijwt tokens

Zip Slip in Chi with Jwt Tokens

Zip Slip in Chi with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Zip Slip is a path traversal vulnerability that occurs when an application constructs file paths using attacker-controlled input without proper validation. In the Chi web framework for Go, this risk can intersect with JWT token handling when tokens are extracted from requests and used to derive file paths or influence file-system operations. For example, if a handler reads a filename or directory segment from a JWT claim (such as a "file" or "role" field) and directly joins it to a base path using filepath.Join, a malicious token containing sequences like ../../etc/passwd can traverse outside the intended directory. Chi does not automatically sanitize inputs derived from JWTs, so developers must explicitly validate and sanitize any token-derived values used in file operations. Attackers may exploit this by crafting a token with a path traversal payload, obtaining a valid JWT (for instance, via a weaker signing algorithm or token leakage), and then using that token in an API call to trigger unauthorized file reads or writes. Since JWTs are often treated as trusted identity assertions, developers may inadvertently trust claims embedded in the token, increasing the likelihood of insecure path construction. The vulnerability is not in Chi or JWT libraries themselves, but in the way token data is used to build filesystem paths without strict allowlisting or canonicalization. middleBrick can detect such insecure patterns during a scan by correlating OpenAPI specifications with runtime behavior, highlighting endpoints where token-derived inputs influence file-system interactions. This is particularly important when tokens carry dynamic values used to locate resources, as missing validation can lead to unauthorized data access or manipulation.

Jwt Tokens-Specific Remediation in Chi — concrete code fixes

To secure JWT token usage in Chi and prevent Zip Slip and related issues, apply strict validation and avoid direct use of token claims in filesystem paths. When a JWT contains values that must map to files or directories, use an allowlist approach and canonicalize paths before use. Below are concrete code examples demonstrating secure patterns in Chi handlers.

1. Safe Path Construction with Token-Driven Resource Lookup

Assume a JWT contains a resource_id claim that should map to a file within a controlled directory. Do not directly join claims to paths. Instead, map the claim to a predefined set of safe locations or use a database lookup.

// Safe approach: map token claim to a known file in a secure base directory
package main

import (
	"archive/zip"
	"fmt"
	"io"
	"net/http"
	"path/filepath"
	"strings"

	"github.com/go-chi/chi/v5"
	"github.com/golang-jwt/jwt/v5"
)

var baseDir = "/safe/resources/"

func resourceHandler(w http.ResponseWriter, r *http.Request) {
	tokenString := chi.URLParam(r, "token") // Example: token passed in URL for illustration; prefer Authorization header
	parsedToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		// Provide key validation logic here
		return []byte("your-secret"), nil
	})
	if err != nil || !parsedToken.Valid {
		http.Error(w, "invalid token", http.StatusUnauthorized)
		return
	}

	claims, ok := parsedToken.Claims.(jwt.MapClaims)
	if !ok {
		http.Error(w, "invalid claims", http.StatusBadRequest)
		return
	}

	resourceID, ok := claims["resource_id"].(string)
	if !ok || resourceID == "" {
		http.Error(w, "missing resource_id", http.StatusBadRequest)
		return
	}

	// Allowlist check: only permit known resource IDs
	allowed := map[string]bool{"report.pdf": true, "data.csv": true}
	if !allowed[resourceID] {
		http.Error(w, "resource not allowed", http.StatusForbidden)
		return
	}

	// Canonicalize and join safely
	requestedPath := filepath.Clean("/" + resourceID)
	fullPath := filepath.Join(baseDir, requestedPath)
	if !strings.HasPrefix(fullPath, filepath.Clean(baseDir)) {
		http.Error(w, "path traversal attempt", http.StatusForbidden)
		return
	}

	// Open and serve file securely
	file, err := openFileSafely(fullPath)
	if err != nil {
		http.Error(w, "file not found", http.StatusNotFound)
		return
	}
	defer file.Close()
	io.Copy(w, file)
}

func openFileSafely(path string) (*os.File, error) {
	return os.Open(path)
}

In this example, the JWT’s resource_id is checked against an allowlist before being used to build a filesystem path. filepath.Clean and a prefix check ensure that even if the token contains traversal sequences, the final path remains within the allowed base directory.

2. Securing JWT Parsing and Claim Usage in Chi Middleware

Use Chi middleware to validate JWTs early and attach only safe, validated data to the request context. Avoid placing raw token claims into context fields that might later be used for file operations.

// Middleware to validate JWT and extract only safe claims
package main

import (
	"context"
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/golang-jwt/jwt/v5"
)

type safeClaims struct {
	UserID string
	Scopes []string
}

func jwtValidator(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tokenString := r.Header.Get("Authorization")
		if tokenString == "" {
			http.Error(w, "missing token", http.StatusUnauthorized)
			return
		}

		claims := &safeClaims{}
		token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
			return []byte("your-secret"), nil
		})
		if err != nil || !token.Valid {
			http.Error(w, "invalid token", http.StatusUnauthorized)
			return
		}

		ctx := context.WithValue(r.Context(), "claims", claims)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

// Usage in router
func main() {
	r := chi.NewRouter()
	r.Use(jwtValidator)

	r.Get("/files/{name}", func(w http.ResponseWriter, r *http.Request) {
		claims, _ := r.Context().Value("claims").(*safeClaims)
		// Use claims.UserID or claims.Scopes for authorization, not for path building
		// ... safe logic here
	})
	http.ListenAndServe(":8080", r)
}

By limiting the claims stored in context to a validated struct, you reduce the risk of inadvertently using untrusted data in filesystem operations. This pattern aligns with secure handling of JWTs and helps mitigate Zip Slip when token data influences resource resolution.

3. Input Validation and Canonicalization for File Operations

Even when JWTs are not directly used in paths, any user-influenced input—including values derived from tokens—must be validated. Use allowlists, avoid dynamic path segments, and canonicalize paths before use.

// Validate and sanitize any path-like input derived from tokens
func getValidatedPath(input string) (string, error) {
	cleaned := filepath.Clean(input)
	if strings.Contains(cleaned, "..") || strings.HasPrefix(cleaned, "/") {
		return "", fmt.Errorf("invalid path")
	}
	full := filepath.Join("/safe/base", cleaned)
	if !strings.HasPrefix(full, "/safe/base") {
		return "", fmt.Errorf("path traversal detected")
	}
	return full, nil
}

These practices help ensure that JWT-derived data does not lead to insecure file access, reducing the attack surface for Zip Slip and similar vulnerabilities.

Frequently Asked Questions

Can a valid JWT still lead to Zip Slip if claims are used in file paths?
Yes. Even a properly signed JWT can introduce Zip Slip if claims containing path traversal sequences are used to build filesystem paths without strict validation, allowlisting, and canonicalization.
Does middleBrick test for Zip Slip in JWT-driven file operations during scans?
middleBrick scans unauthenticated attack surfaces and can identify risky patterns where token-derived inputs may influence file-system interactions, correlating OpenAPI specs with runtime behavior to highlight such findings.