HIGH information disclosurechi

Information Disclosure in Chi

How Information Disclosure Manifests in Chi

Information disclosure vulnerabilities in Chi APIs typically emerge through several distinct attack vectors. The most common pattern involves error messages that reveal stack traces, database schemas, or internal system paths. When Chi handlers encounter exceptions, default error responses often include verbose technical details that attackers can leverage for reconnaissance.

Consider this vulnerable Chi endpoint:

router.Get("/api/users/{id}", func(c *chi.Context) error {
    userID := c.Param("id")
    user, err := db.GetUser(userID)
    if err != nil {
        return err // Leaks database error details
    }
    return c.JSON(http.StatusOK, user)
})

When db.GetUser fails, the raw database error propagates to the client, potentially exposing table names, query structures, or even credentials if connection strings are mishandled. This is particularly problematic in Chi applications where middleware stacks might not catch and sanitize errors before they reach the response.

Another Chi-specific disclosure pattern occurs with improper use of context values. Developers often store sensitive debugging information in context for logging, but if that context flows through to responses:

router.Post("/api/login", func(c *chi.Context) error {
    creds := c.BodyJSON()
    
    // Debug info stored in context
    c.Set("authDebug", map[string]interface{}{
        "attempt": creds,
        "ip": c.RemoteIP(),
        "headers": c.Request().Header,
    })
    
    // Later middleware might accidentally expose this
    return c.JSON(http.StatusOK, map[string]string{"status": "success"})
})

Chi's context package makes it easy to accidentally expose sensitive debugging data if middleware or handlers serialize context values without proper filtering.

Directory traversal vulnerabilities also manifest uniquely in Chi applications. The router's path parameter handling can be exploited when combined with file operations:

router.Get("/static/{file}", func(c *chi.Context) error {
    filename := c.Param("file")
    content, err := os.ReadFile("/var/www/static/" + filename)
    if err != nil {
        return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()})
    }
    return c.String(http.StatusOK, content)
})

An attacker can request /static/../../etc/passwd to traverse directories and access sensitive files, with error messages potentially revealing whether files exist.

Chi-Specific Detection

Detecting information disclosure vulnerabilities in Chi applications requires both static analysis and runtime scanning. For static detection, look for patterns where errors are returned directly without sanitization:

// Vulnerable pattern - returns raw error
return err

// Also vulnerable - includes error in JSON response
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})

Dynamic scanning with middleBrick specifically targets these Chi patterns. The scanner sends malformed requests to trigger error conditions, then analyzes responses for sensitive content like:

  • Stack traces containing file paths and line numbers
  • Database error messages with schema details
  • Environment variables or configuration data
  • Internal IP addresses and server information
  • Git repository paths or source code snippets

middleBrick's black-box scanning approach is particularly effective for Chi applications because it tests the actual running API without requiring source code access. The scanner can detect if your Chi error handling middleware is improperly configured or missing entirely.

For Chi applications using middleware chains, middleBrick analyzes whether error handling propagates through the entire stack. Many Chi applications use custom error middleware that looks like:

router.Use(middleware.DefaultLogger)
router.Use(middleware.Recoverer) // Critical for preventing info disclosure

middleBrick verifies that Recoverer middleware is properly installed and configured, as missing error handling is a common cause of information disclosure in Chi applications.

The scanner also tests Chi's context handling by attempting to access endpoints that might expose stored context values. This includes testing for endpoints that might serialize request metadata, authentication attempts, or debugging information in responses.

Chi-Specific Remediation

Remediating information disclosure vulnerabilities in Chi applications requires a multi-layered approach. The foundation is proper error handling middleware. Chi provides middleware.Recoverer which catches panics and returns sanitized error responses:

import "github.com/go-chi/chi/middleware"

router := chi.NewRouter()
router.Use(middleware.Recoverer)
router.Use(middleware.DefaultLogger)

This middleware prevents stack traces from leaking while still providing useful error codes to clients. For production environments, you should enhance this with custom error handling:

type errorHandler struct{}

func (h *errorHandler) Handle(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) {
    log.Printf("Error: %v", err) // Log full error server-side
    
    // Return generic error to client
    w.WriteHeader(http.StatusInternalServerError)
    w.Write([]byte(`{"error": "Internal server error"}`))
}

router.Use(middleware.RecovererWithWriter(&errorHandler{}))

For database operations in Chi handlers, always sanitize error messages before returning them:

router.Get("/api/users/{id}", func(c *chi.Context) error {
    userID := c.Param("id")
    user, err := db.GetUser(userID)
    if err != nil {
        if errors.Is(err, sql.ErrNoRows) {
            return c.JSON(http.StatusNotFound, map[string]string{"error": "User not found"})
        }
        log.Printf("Database error: %v", err) // Log detailed error
        return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Database error"})
    }
    return c.JSON(http.StatusOK, user)
})

Chi's context package requires careful handling to prevent information disclosure. Always filter context values before including them in responses:

func safeContextResponse(c *chi.Context) map[string]interface{} {
    safe := make(map[string]interface{})
    
    // Only include explicitly safe values
    if val := c.Values["userID"]; val != nil {
        safe["userID"] = val
    }
    
    return safe
}

router.Get("/api/context", func(c *chi.Context) error {
    return c.JSON(http.StatusOK, safeContextResponse(c))
})

For file operations in Chi applications, implement strict path validation to prevent directory traversal:

func validateFilePath(requested string, baseDir string) (string, error) {
    targetPath := filepath.Join(baseDir, filepath.Clean(requested))
    if !strings.HasPrefix(targetPath, baseDir) {
        return "", errors.New("invalid path")
    }
    return targetPath, nil
}

router.Get("/static/{file}", func(c *chi.Context) error {
    file := c.Param("file")
    safePath, err := validateFilePath(file, "/var/www/static")
    if err != nil {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid file path"})
    }
    
    content, err := os.ReadFile(safePath)
    if err != nil {
        if os.IsNotExist(err) {
            return c.JSON(http.StatusNotFound, map[string]string{"error": "File not found"})
        }
        log.Printf("File read error: %v", err)
        return c.JSON(http.StatusInternalServerError, map[string]string{"error": "File read error"})
    }
    
    return c.String(http.StatusOK, content)
})

Finally, implement comprehensive logging that captures detailed error information server-side while ensuring client responses remain generic. This allows debugging without exposing sensitive data to attackers.

Frequently Asked Questions

How does middleBrick detect information disclosure vulnerabilities in Chi applications?
middleBrick performs black-box scanning by sending malformed requests to trigger error conditions, then analyzes responses for sensitive content like stack traces, database schemas, and internal system information. The scanner specifically tests Chi's error handling middleware configuration and context value serialization patterns that are unique to Chi applications.
What's the difference between middleware.Recoverer and custom error handling in Chi?
middleware.Recoverer catches panics and prevents stack traces from reaching clients, but custom error handlers give you more control over the response format and logging. For production Chi applications, use Recoverer with a custom writer that logs detailed errors server-side while returning generic error messages to clients.