HIGH time of check time of useecho goapi keys

Time Of Check Time Of Use in Echo Go with Api Keys

Time Of Check Time Of Use in Echo Go with Api Keys — how this specific combination creates or exposes the vulnerability

Time Of Check Time Of Use (TOCTOU) occurs when the state used in a security decision changes between the check and the use of that resource. In Echo Go, a common pattern is to validate an API key on each request and then use the associated permissions to decide whether to allow an operation. If the authorization check and the subsequent data access are not performed as a single, atomic operation, an attacker can exploit the window between check and use.

Consider an endpoint that first verifies an API key and then retrieves a user’s resource by ID. A typical vulnerable flow is:

  1. Extract the API key from the request header.
  2. Look up the key to determine the associated user ID and permissions.
  3. Check if the user has permission to access resource X.
  4. Use the user-supplied identifier to fetch or modify resource X.

An attacker can change the mapping between the API key and the underlying user or resource between steps 3 and 4. For example, if the key-to-user binding is stored in a cache or database that can be modified asynchronously (e.g., via an administrative API or a background process), the check may pass, but the use may operate on a different target. In Echo Go, this can happen when authorization is derived from request-scaped context values that can be influenced after the check, such as mutable URL parameters or headers that are re-evaluated later in middleware or handlers.

Another scenario specific to Echo Go involves route parameters and context handlers. If you perform a permission check in one middleware using a param like userID derived from the API key, and then a downstream handler uses a different param (e.g., resourceID) to construct a database query without re-verifying scope, you may inadvertently allow access to resources owned by other users. This is a BOLA/IDOR pattern often triggered by inconsistent validation between middleware and route handlers.

Real-world parallels include findings where scanners detect endpoints that expose sensitive data or allow unauthorized modifications due to missing binding between the API key context and the resource access logic. These are not theoretical: similar patterns have been observed in APIs enumerated in the OWASP API Top 10 under Broken Object Level Authorization (BOLA), often mapped to IDs such as CVE-like patterns involving IDOR when object references are not validated against the authenticated subject on each use.

To summarize, the combination of Echo Go’s flexible middleware chaining and the use of API keys for authentication can create TOCTOU when authorization decisions are not tightly coupled to the resource access logic. Without atomic checks, an attacker can manipulate the runtime state to escalate privileges or access other users’ data.

Api Keys-Specific Remediation in Echo Go — concrete code fixes

To prevent TOCTOU in Echo Go when using API keys, enforce that authorization and resource access occur within a single, non-interruptible flow and that the identity derived from the key is bound to every operation. Avoid relying on mutable or re-resolved identifiers between the check and the use phase.

Remediation pattern 1: Bind the key identity to the resource request in a single handler

Instead of resolving the user from the key in middleware and later using a separate parameter, embed the authoritative identifier into the request context and use it directly when accessing data. Here is a secure example:

// Secure Echo Go handler with API key binding
package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

type contextKey string

const userIDKey contextKey = "userID"

func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		apiKey := c.Request().Header.Get("X-API-Key")
		userID, ok := validateAPIKeyAndGetUserID(apiKey) // returns userID or empty
		if !ok || userID == "" {
			return echo.ErrUnauthorized
		}
		// Bind the userID to the context for this request only
		c.Set(userIDKey, userID)
		return next(c)
	}
}

func getResourceHandler(c echo.Context) error {
	// Retrieve the bound userID from context, not from request params
	userID, ok := c.Get(userIDKey).(string)
	if !ok {
		return echo.ErrUnauthorized
	}
	// Use the userID to scope the resource lookup, ensuring ownership check
	resourceID := c.Param("resource_id")
	resource, err := fetchResourceByOwner(userID, resourceID)
	if err != nil {
		return echo.ErrNotFound
	}
	return c.JSON(http.StatusOK, resource)
}

func validateAPIKeyAndGetUserID(apiKey string) (string, bool) {
	// Example: lookup key in a store and return associated userID
	// In practice, use a constant-time comparison and secure storage
	return "validated_user_id", true
}

func fetchResourceByOwner(userID, resourceID string) (interface{}, error) {
	// Ensure the query includes the userID scope to prevent IDOR
	// Example SQL: SELECT * FROM resources WHERE user_id = $1 AND id = $2
	return map[string]string{"id": resourceID, "owner": userID}, nil
}

This pattern ensures that the user identity used for authorization is fixed at the point of validation and cannot be altered by later parameter manipulation.

Remediation pattern 2: Use request-scoped context and avoid re-deriving identifiers

Do not re-derive or re-validate the API key or user identity in downstream handlers. Keep the context immutable for the request lifecycle:

// Avoid this: re-deriving or using params without re-binding
func insecureHandler(c echo.Context) error {
	// BAD: re-reading the key and re-resolving can lead to TOCTOU
	apiKey := c.Request().Header.Get("X-API-Key")
	userID, _ := validateAPIKeyAndGetUserID(apiKey)
	resourceID := c.Param("resource_id")
	// If validateAPIKeyAndGetUserID can return different values between calls,
	// the check and use are not atomic.
	return c.JSON(http.StatusOK, map[string]string{"resource": resourceID, "user": userID})
}

Instead, rely on the context set once by middleware and ensure all data access uses that bound identity.

These practices align with remediations for BOLA and IDOR by enforcing strict ownership checks tied to the authenticated subject on every request. middleBrick scans can help identify endpoints where authorization checks and resource operations are not consistently scoped, providing prioritized findings and remediation guidance mapped to frameworks such as OWASP API Top 10.

Frequently Asked Questions

How can I test if my Echo Go endpoint is vulnerable to TOCTOU with API keys?
Send two requests where the API key maps to one user but an alternate resource identifier targets another user’s object. If the endpoint returns or modifies the other user’s resource, it is likely vulnerable. Automated scanners like middleBrick can detect missing atomic checks between authorization and use.
Does using the middleBrick CLI help detect API key TOCTOU issues in Echo Go?
Yes. The CLI (install via npm as the middlebrick package) can scan your endpoints and surface findings related to Broken Object Level Authorization and TOCTOU patterns, including specific remediation guidance. You can run: middlebrick scan to get a JSON or text report.