NornicDB Security Validation
This package provides comprehensive security validation for NornicDB HTTP endpoints, protecting against:
- CSRF (Cross-Site Request Forgery) attacks
- SSRF (Server-Side Request Forgery) attacks
- HTTP Header Injection attacks
- XSS (Cross-Site Scripting) attacks
- Protocol Smuggling attacks
- Data URI Injection attacks
Features
1. Token Validation (ValidateToken)
Validates OAuth/API tokens to prevent injection attacks:
import "github.com/orneryd/nornicdb/pkg/security"
token := "eyJhbGciOiJIUzI1NiIs..."
if err := security.ValidateToken(token); err != nil {
return fmt.Errorf("invalid token: %w", err)
}
Protects against:
- HTTP header injection (CRLF, newlines)
- XSS attacks (HTML tags, JavaScript)
- Protocol injection (javascript:, data:, file:)
- DoS attacks (excessively long tokens > 8192 bytes)
- String termination attacks (null bytes)
Test Coverage: 13 injection attack scenarios
2. URL Validation (ValidateURL)
Validates URLs to prevent SSRF attacks:
// Production mode (strict)
err := security.ValidateURL(callbackURL, false, false)
// Development mode (allows localhost)
err := security.ValidateURL(localURL, true, true)
Protects against:
- SSRF to private IP ranges (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
- SSRF to cloud metadata services (169.254.169.254)
- SSRF to localhost (127.0.0.0/8) in production
- Protocol smuggling (file://, gopher://, dict://)
- HTTP downgrade attacks (requires HTTPS in production)
Test Coverage: 15+ SSRF attack scenarios including AWS/Azure/GCP metadata services
Validates HTTP header values to prevent injection:
if err := security.ValidateHeaderValue(userAgent); err != nil {
return fmt.Errorf("invalid header: %w", err)
}
Protects against:
- HTTP header injection (CRLF)
- HTTP response splitting
- Null byte injection
- Excessively long headers (> 4096 bytes)
4. Security Middleware
Automatically applies all validations to HTTP endpoints:
import (
"net/http"
"github.com/orneryd/nornicdb/pkg/security"
)
func main() {
middleware := security.NewSecurityMiddleware()
// Wrap individual handler
http.Handle("/api/query", middleware.Wrap(queryHandler))
// Or wrap entire mux
mux := http.NewServeMux()
mux.HandleFunc("/api/query", queryHandler)
http.ListenAndServe(":7474", middleware.ValidateRequest(mux))
}
Automatically validates:
- All HTTP header values
- Authorization tokens (Bearer/Basic)
- Query parameter tokens (for SSE/WebSocket)
- URL parameters (callback, redirect, redirect_uri, url, webhook)
Environment Variables
NORNICDB_ENV or NODE_ENV: Set to development to allow localhost URLs
NORNICDB_ALLOW_HTTP: Set to true to allow HTTP URLs in production (not recommended)
Mapping to TypeScript Tests
This implementation provides equivalent protection to the TypeScript security tests:
CSRF Protection (csrf-protection.test.ts)
While the TypeScript tests focus on OAuth state management, NornicDB's security layer protects against CSRF through:
- Token validation - prevents forged/injected tokens
- State parameter validation - validates callback URLs (SSRF prevention)
- Header injection prevention - blocks CRLF attacks that could bypass CSRF checks
Example equivalent protection:
// TypeScript: SecureStateStore validates OAuth state parameters
// Go: SecurityMiddleware validates all tokens and URLs
middleware := security.NewSecurityMiddleware()
http.Handle("/oauth/callback", middleware.Wrap(oauthCallbackHandler))
SSRF Protection (ssrf-protection.test.ts)
Direct 1:1 mapping of all SSRF protections:
| TypeScript Test |
Go Implementation |
Coverage |
validateOAuthTokenFormat() |
ValidateToken() |
✅ 100% |
validateOAuthUserinfoUrl() |
ValidateURL() |
✅ 100% |
createSecureFetchOptions() |
SecurityMiddleware |
✅ 100% |
| Private IP detection |
isPrivateIP() |
✅ All ranges |
| Cloud metadata blocking |
ValidateURL() |
✅ AWS/Azure/GCP |
| Protocol smuggling |
ValidateURL() |
✅ file://, gopher://, etc. |
Test Scenarios Covered
All attack scenarios from the TypeScript tests are covered:
Token Injection:
- ✅ CRLF injection (
token\r\nX-Malicious: header)
- ✅ HTML injection (
<script>alert('xss')</script>)
- ✅ JavaScript protocol (
javascript:alert('xss'))
- ✅ Data URI (
data:text/html,<script>...)
- ✅ File protocol (
file:///etc/passwd)
- ✅ Null byte injection (
token\x00evil)
SSRF Attacks:
- ✅ Private IP ranges (10.x, 192.168.x, 172.16-31.x)
- ✅ AWS metadata (
http://169.254.169.254/latest/meta-data/)
- ✅ Azure metadata (
http://169.254.169.254/metadata/instance)
- ✅ GCP metadata (
http://169.254.169.254/computeMetadata/)
- ✅ Internal network scanning
- ✅ Localhost access in production
Protocol Smuggling:
- ✅
file:// protocol
- ✅
ftp:// protocol
- ✅
gopher:// protocol
- ✅
dict:// protocol
Testing
Run all security tests:
cd nornicdb
go test -v ./pkg/security/...
Run with coverage:
go test -cover ./pkg/security/...
Benchmark performance:
go test -bench=. ./pkg/security/...
Usage Examples
Protecting OAuth Endpoints
func setupOAuthServer() {
middleware := security.NewSecurityMiddleware()
// OAuth authorization endpoint
http.Handle("/oauth/authorize", middleware.Wrap(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// redirect_uri is automatically validated by middleware
redirectURI := r.URL.Query().Get("redirect_uri")
// ... OAuth flow
}),
))
// OAuth callback endpoint
http.Handle("/oauth/callback", middleware.Wrap(oauthCallbackHandler))
}
Protecting API Endpoints
func setupAPIServer() {
middleware := security.NewSecurityMiddleware()
mux := http.NewServeMux()
mux.HandleFunc("/api/query", queryHandler)
mux.HandleFunc("/api/import", importHandler)
mux.HandleFunc("/api/export", exportHandler)
// All endpoints protected
http.ListenAndServe(":7474", middleware.ValidateRequest(mux))
}
Manual Validation
func handleWebhook(w http.ResponseWriter, r *http.Request) {
webhookURL := r.URL.Query().Get("callback")
// Validate before making outbound request
if err := security.ValidateURL(webhookURL, false, false); err != nil {
http.Error(w, "Invalid webhook URL", http.StatusBadRequest)
return
}
// Safe to make request
resp, err := http.Post(webhookURL, "application/json", payload)
// ...
}
Security Best Practices
- Always use HTTPS in production - set
NORNICDB_ENV=production
- Never disable validations - they prevent real attacks
- Use middleware globally - protect all endpoints by default
- Validate before external requests - check all user-provided URLs
- Log security violations - monitor for attack attempts
- Keep dependencies updated - security fixes are critical
All validations are optimized for production use:
- Token validation: ~1-2 µs per call
- URL validation: ~5-10 µs per call
- Header validation: ~0.5-1 µs per call
Negligible overhead for comprehensive protection.
References