Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
middleware_test.go5.42 kB
// Package security provides HTTP middleware tests. package security import ( "net/http" "net/http/httptest" "os" "testing" ) func TestSecurityMiddleware_HeaderValidation(t *testing.T) { middleware := NewSecurityMiddleware() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) }) wrappedHandler := middleware.ValidateRequest(handler) tests := []struct { name string headerName string headerValue string expectBlocked bool }{ {"valid header", "User-Agent", "Mozilla/5.0", false}, {"CRLF injection", "X-Custom", "value\r\nX-Injected: evil", true}, {"newline injection", "X-Custom", "value\nX-Injected: evil", true}, {"null byte", "X-Custom", "value\x00injected", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req := httptest.NewRequest("GET", "/test", nil) req.Header.Set(tt.headerName, tt.headerValue) rr := httptest.NewRecorder() wrappedHandler.ServeHTTP(rr, req) if tt.expectBlocked { if rr.Code == http.StatusOK { t.Errorf("Expected request to be blocked, but got status %d", rr.Code) } } else { if rr.Code != http.StatusOK { t.Errorf("Expected status 200, got %d: %s", rr.Code, rr.Body.String()) } } }) } } func TestSecurityMiddleware_TokenValidation(t *testing.T) { middleware := NewSecurityMiddleware() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) wrappedHandler := middleware.ValidateRequest(handler) tests := []struct { name string authHeader string expectBlocked bool }{ {"valid bearer token", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", false}, {"valid basic auth", "Basic dXNlcjpwYXNz", false}, {"injection in bearer", "Bearer token\r\nX-Evil: header", true}, {"XSS in token", "Bearer <script>alert('xss')</script>", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req := httptest.NewRequest("GET", "/test", nil) req.Header.Set("Authorization", tt.authHeader) rr := httptest.NewRecorder() wrappedHandler.ServeHTTP(rr, req) if tt.expectBlocked { if rr.Code == http.StatusOK { t.Errorf("Expected token to be blocked, but got status %d", rr.Code) } } else { if rr.Code != http.StatusOK { t.Errorf("Expected status 200, got %d: %s", rr.Code, rr.Body.String()) } } }) } } func TestSecurityMiddleware_URLValidation(t *testing.T) { // Set production environment oldEnv := os.Getenv("NORNICDB_ENV") os.Setenv("NORNICDB_ENV", "production") defer os.Setenv("NORNICDB_ENV", oldEnv) middleware := NewSecurityMiddleware() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) wrappedHandler := middleware.ValidateRequest(handler) tests := []struct { name string urlParam string expectBlocked bool }{ {"valid HTTPS callback", "https://example.com/callback", false}, {"SSRF to private IP", "https://192.168.1.1/callback", true}, {"SSRF to metadata service", "http://169.254.169.254/latest/meta-data/", true}, {"protocol smuggling", "file:///etc/passwd", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req := httptest.NewRequest("GET", "/test?callback="+tt.urlParam, nil) rr := httptest.NewRecorder() wrappedHandler.ServeHTTP(rr, req) if tt.expectBlocked { if rr.Code == http.StatusOK { t.Errorf("Expected SSRF to be blocked, but got status %d", rr.Code) } } else { if rr.Code != http.StatusOK { t.Errorf("Expected status 200, got %d: %s", rr.Code, rr.Body.String()) } } }) } } func TestSecurityMiddleware_DevelopmentMode(t *testing.T) { oldEnv := os.Getenv("NORNICDB_ENV") os.Setenv("NORNICDB_ENV", "development") defer os.Setenv("NORNICDB_ENV", oldEnv) middleware := NewSecurityMiddleware() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) wrappedHandler := middleware.ValidateRequest(handler) // Localhost should be allowed in development req := httptest.NewRequest("GET", "/test?callback=http://localhost:8080/callback", nil) rr := httptest.NewRecorder() wrappedHandler.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Errorf("Expected localhost to be allowed in development, got status %d: %s", rr.Code, rr.Body.String()) } } func TestSecurityMiddleware_AllowHTTP(t *testing.T) { oldEnv := os.Getenv("NORNICDB_ALLOW_HTTP") oldNodeEnv := os.Getenv("NORNICDB_ENV") os.Setenv("NORNICDB_ALLOW_HTTP", "true") os.Setenv("NORNICDB_ENV", "production") defer func() { os.Setenv("NORNICDB_ALLOW_HTTP", oldEnv) os.Setenv("NORNICDB_ENV", oldNodeEnv) }() middleware := NewSecurityMiddleware() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) wrappedHandler := middleware.ValidateRequest(handler) // HTTP should be allowed when NORNICDB_ALLOW_HTTP=true req := httptest.NewRequest("GET", "/test?callback=http://example.com/callback", nil) rr := httptest.NewRecorder() wrappedHandler.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Errorf("Expected HTTP to be allowed with NORNICDB_ALLOW_HTTP=true, got status %d: %s", rr.Code, rr.Body.String()) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server