Major additions: - Community Next.js app (port 18187) for browsing claims with API docs - stemedb-chaos crate: Fault injection, chaos testing, CRDT properties - Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents - Disputed claims handling: Manual review workflows and validation - Aphoria security scanner: New extractors (SQL injection, command injection, weak crypto, TLS version), policy-based ignores, UAT reports - Docker infrastructure: Dockerfile, docker-compose.yml for full stack - VulnBank demo: Intentionally vulnerable multi-language test corpus SDK & API enhancements: - Source registry handlers for tracking data provenance - Metrics endpoint - Skeptic filtering improvements Code quality: - Split 14 large files (>500 lines) into focused modules - All files now under 500-line limit per project guidelines Documentation: - Chaos testing guide, circuit breakers, observability docs - Phase 7 UAT documentation updates - Martin Kleppmann technical writer agent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
// VulnBank - HTTP Handlers with intentional vulnerabilities
|
|
//
|
|
// Vulnerabilities:
|
|
// - JWT algorithm confusion
|
|
// - CORS wildcard
|
|
// - TLS verification disabled
|
|
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
)
|
|
|
|
// BLOCK: Hardcoded JWT secret in source code
|
|
var jwtSecret = []byte("hardcoded_secret_key_12345")
|
|
|
|
// GetUserHandler returns user data with insecure CORS
|
|
func GetUserHandler(w http.ResponseWriter, r *http.Request) {
|
|
// BLOCK: Access-Control-Allow-Origin: * allows any origin
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
_ = json.NewEncoder(w).Encode(map[string]string{
|
|
"id": "12345",
|
|
"name": "Test User",
|
|
})
|
|
}
|
|
|
|
// VerifyTokenHandler validates JWT with algorithm confusion vulnerability
|
|
func VerifyTokenHandler(w http.ResponseWriter, r *http.Request) {
|
|
tokenString := r.Header.Get("Authorization")
|
|
if tokenString == "" {
|
|
http.Error(w, "Missing token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// BLOCK: jwt.Parse without algorithm validation - allows algorithm confusion attacks
|
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
// Vulnerable: accepts any algorithm the attacker specifies
|
|
return jwtSecret, nil
|
|
})
|
|
|
|
if err != nil || !token.Valid {
|
|
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
_ = json.NewEncoder(w).Encode(map[string]string{"status": "valid"})
|
|
}
|
|
|
|
// GetExternalDataHandler fetches external data with TLS verification disabled
|
|
func GetExternalDataHandler(w http.ResponseWriter, r *http.Request) {
|
|
url := r.URL.Query().Get("url")
|
|
if url == "" {
|
|
http.Error(w, "Missing url parameter", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// BLOCK: InsecureSkipVerify disables TLS certificate verification
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
client := &http.Client{Transport: tr}
|
|
|
|
resp, err := client.Get(url)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write(body)
|
|
}
|
|
|
|
// HashDataHandler demonstrates insecure JWT parsing
|
|
func HashDataHandler(w http.ResponseWriter, r *http.Request) {
|
|
// BLOCK: Using UnsafeAllowNoneSignatureType allows unsigned tokens
|
|
parser := jwt.NewParser(jwt.WithValidMethods([]string{"none", "HS256"}))
|
|
|
|
tokenString := r.Header.Get("Authorization")
|
|
token, _ := parser.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
|
|
return jwtSecret, nil
|
|
})
|
|
|
|
if token != nil && token.Valid {
|
|
w.WriteHeader(http.StatusOK)
|
|
} else {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
}
|
|
}
|