Time Of Check Time Of Use in Chi
How Time Of Check Time Of Use Manifests in Chi
Time Of Check Time Of Use (TOCTOU) vulnerabilities in Chi APIs arise when a resource is validated in one state but used in a different state by the time the operation executes. This race condition creates windows where authorization checks pass but the underlying resource has changed, enabling unauthorized access.
Chi's concurrent request handling model makes it particularly susceptible to TOCTOU when developers don't account for the asynchronous nature of HTTP request processing. The issue commonly appears in authorization workflows where resource state changes between validation and usage.
// Vulnerable Chi pattern - TOCTOU race condition
func deleteArticle(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
// Check 1: Verify ownership (state A)
article, err := getArticleByID(id)
if err != nil || article.OwnerID != getCurrentUserID(r) {
http.Error(w, "Unauthorized", 403)
return
}
// State can change here - another request could transfer ownership
// Use 2: Delete the article (state B)
err = deleteArticleByID(id)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
w.WriteHeader(204)
}In this Chi pattern, the authorization check and deletion operation are separate database calls. Between these calls, another request could transfer article ownership, creating a TOCTOU window where the delete operation executes on a resource the user no longer owns.
Chi's middleware-based architecture can compound TOCTOU issues when multiple middleware layers perform separate checks. Each layer introduces potential state changes:
// Multiple checks create larger TOCTOU windows
func updateArticle(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
// Middleware 1: Authentication
// Middleware 2: Rate limiting
// Middleware 3: Authorization check
// Between these checks, state can change
// Final operation
article, err := getArticleByID(id)
if err != nil {
http.Error(w, "Not found", 404)
return
}
// Process update
// ...
}Chi's URL parameter extraction and route matching also create TOCTOU scenarios when parameters are used to construct database queries without proper validation at the point of use.
Chi-Specific Detection
Detecting TOCTOU in Chi applications requires analyzing both the code structure and runtime behavior. middleBrick's black-box scanning approach is particularly effective for Chi APIs because it can identify TOCTOU patterns without requiring source code access.
middleBrick scans Chi APIs for TOCTOU by testing concurrent access patterns and monitoring resource state changes between validation and operation execution. The scanner identifies Chi-specific patterns like:
# Scan a Chi API endpoint for TOCTOU vulnerabilities
middlebrick scan https://api.example.com/articles/123
The scanner tests Chi's route handlers by making concurrent requests that attempt to trigger state changes between validation and usage. For example, it might:
- Read a resource, then attempt to modify it while another request validates access
- Trigger race conditions in Chi's middleware chain
- Test parameter extraction and validation timing
middleBrick's OpenAPI analysis also helps detect TOCTOU by examining Chi's route definitions and parameter handling patterns. The scanner resolves $ref references to understand how parameters flow through Chi's request processing pipeline.
Manual detection in Chi code involves looking for patterns where:
- Database operations are split across multiple calls
- Authorization checks happen separately from resource operations
- State validation occurs before the actual operation
- Middleware chains perform sequential checks without atomic operations
middleBrick's CI/CD integration allows teams to automatically scan Chi APIs before deployment, catching TOCTOU vulnerabilities early in the development lifecycle.
Chi-Specific Remediation
Remediating TOCTOU in Chi requires atomic operations that validate and execute in a single database transaction. Chi's middleware architecture supports atomic patterns through proper transaction management and single-query operations.
The most effective approach is using database transactions that combine validation and operation:
// Atomic operation - no TOCTOU window
func deleteArticleAtomic(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
userID := getCurrentUserID(r)
// Single transaction - validation and deletion atomic
err := db.Transaction(func(tx *sql.Tx) error {
// Combined check and delete
result, err := tx.Exec(`
DELETE FROM articles
WHERE id = $1 AND owner_id = $2
`, id, userID)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil || rowsAffected == 0 {
return errors.New("unauthorized or not found")
}
return nil
})
if err != nil {
http.Error(w, "Unauthorized or not found", 403)
return
}
w.WriteHeader(204)
}This pattern eliminates the TOCTOU window by making the authorization check and deletion a single atomic database operation. The database ensures the resource state doesn't change between validation and execution.
For Chi middleware that performs multiple checks, consolidate validation into a single operation:
// Consolidated validation - no TOCTOU between checks
func updateArticleSecure(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
userID := getCurrentUserID(r)
// Single query validates ownership and retrieves data
article, err := getArticleForUpdateByID(id, userID)
if err != nil {
http.Error(w, "Unauthorized or not found", 403)
return
}
// Process update with retrieved data
// ...
}Chi's context system can help prevent TOCTOU by passing validated state through the request lifecycle:
// Context-based validation - maintains state
func validateAndProcess(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
// Validate once, store in context
article, err := validateArticleAccess(r.Context(), id)
if err != nil {
http.Error(w, "Unauthorized", 403)
return
}
// Use validated article from context
r = r.WithContext(ContextWithArticle(r.Context(), article))
// Process with guaranteed valid state
processArticle(w, r.WithContext(r.Context()))
}middleBrick's scanning helps verify these remediation patterns by testing that concurrent requests cannot bypass the atomic operations.