Fix 8 high-severity audit findings across security, Go, API, and container domains
- Use typed context key for auth context to prevent collisions (auth.go) - Eliminate nested locking in CheckRateLimit to prevent potential deadlock (auth.go) - Add 1MB request body size limit middleware to prevent DoS (router.go) - Return proper gRPC status codes instead of nil errors on failures (handler.go) - Use key name instead of raw API key in admin URL paths to prevent secret leakage (keys.go, router.go, keystore_db.go, keystore_hybrid.go) - Enforce RBAC authorization in service Send/SendBatch for both REST and gRPC (service.go) - Pin runtime Docker image to alpine:3.21 for reproducible builds (Dockerfile) - Enable readOnlyRootFilesystem with /tmp emptyDir in k8s deployment (deployment.yaml) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+13
-5
@@ -115,24 +115,29 @@ func (s *APIKeyStore) ValidateKey(keyStr string) (*APIKey, error) {
|
||||
|
||||
// CheckRateLimit checks if a key has exceeded its rate limit
|
||||
func (s *APIKeyStore) CheckRateLimit(keyStr string) (bool, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
// Look up key and limiter under the store lock, then release it
|
||||
// before acquiring the per-key limiter lock to avoid nested locking.
|
||||
s.mu.RLock()
|
||||
key, exists := s.keys[keyStr]
|
||||
if !exists {
|
||||
s.mu.RUnlock()
|
||||
return false, fmt.Errorf("invalid API key")
|
||||
}
|
||||
|
||||
// Unlimited rate limit
|
||||
if key.RateLimit <= 0 {
|
||||
s.mu.RUnlock()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
limiter, exists := s.rateLimits[keyStr]
|
||||
if !exists {
|
||||
s.mu.RUnlock()
|
||||
return false, fmt.Errorf("rate limiter not found")
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
// Now lock only the per-key rate limiter
|
||||
limiter.mu.Lock()
|
||||
defer limiter.mu.Unlock()
|
||||
|
||||
@@ -206,13 +211,16 @@ func (s *APIKeyStore) ListKeys(clientID string) []*APIKey {
|
||||
return keys
|
||||
}
|
||||
|
||||
// authContextKey is an unexported type for context keys to avoid collisions.
|
||||
type authContextKey struct{}
|
||||
|
||||
// ContextWithAuth adds auth context to a request context
|
||||
func ContextWithAuth(ctx context.Context, auth *AuthContext) context.Context {
|
||||
return context.WithValue(ctx, "auth", auth)
|
||||
return context.WithValue(ctx, authContextKey{}, auth)
|
||||
}
|
||||
|
||||
// GetAuthContext retrieves auth context from a request context
|
||||
func GetAuthContext(ctx context.Context) (*AuthContext, bool) {
|
||||
auth, ok := ctx.Value("auth").(*AuthContext)
|
||||
auth, ok := ctx.Value(authContextKey{}).(*AuthContext)
|
||||
return auth, ok
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user