-
Notifications
You must be signed in to change notification settings - Fork 19
[compliance] Compliance Gap: Authentication Returns HTTP 401 for All Auth Failures (MUST Require HTTP 400 for Malformed Headers) #3057
Description
MCP Gateway Compliance Review — 2026-04-02
Daily compliance review of commit 1a09953 (refactor: remove redundant config default fallbacks in server and launcher).
Summary
Found 4 compliance gaps — 1 Critical MUST violation, 1 borderline MUST, and 2 SHOULD deviations.
Critical Issue (MUST Violation)
1. HTTP 400 Not Returned for Malformed Authorization Headers
Specification Section: 7.2 API Key Authentication
Deep Link: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#72-api-key-authentication
Requirement:
When
gateway.apiKeyis configured, the gateway MUST:
2. Reject requests with missing or invalid tokens (HTTP 401)
3. Reject requests with malformed Authorization headers (HTTP 400)
Current State:
internal/server/auth.go returns HTTP 401 for all auth failures — missing headers, invalid keys, and malformed headers alike. There is no distinct HTTP 400 path:
if authHeader == "" {
rejectRequest(w, r, http.StatusUnauthorized, ...) // 401
return
}
if authHeader != apiKey {
rejectRequest(w, r, http.StatusUnauthorized, ...) // 401 — should be 400 for malformed headers
return
}Gap:
The spec distinguishes between two cases that MUST return different status codes:
- Invalid but well-formed header → 401 Unauthorized
- Malformed header (e.g., null bytes, non-printable chars) → 400 Bad Request
Severity: Important (MUST violation per spec §7.2 item 3)
File References:
internal/server/auth.go:42-60
Suggested Fix:
Add a pre-check for malformed headers (e.g., non-printable characters, invalid encoding) before the API key comparison and return HTTP 400 for those cases:
if containsMalformedChars(authHeader) {
rejectRequest(w, r, http.StatusBadRequest, "bad_request", "malformed Authorization header", ...)
return
}Important Issue (Borderline MUST)
2. TOML Unknown Fields Warned But Not Rejected
Specification Section: 4.3.1 Unknown Features
Deep Link: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#431-unknown-features
Requirement:
The gateway MUST reject configurations containing unrecognized fields at the top level with an error message indicating the unrecognized field name, location, and a suggestion to check the specification version.
Current State:
internal/config/config_core.go:259-275 explicitly warns but continues loading:
// Design decision: We use warnings rather than hard errors to maintain
// backward compatibility and allow gradual config migration.
undecoded := md.Undecoded()
if len(undecoded) > 0 {
for _, key := range undecoded {
logger.LogWarn("config", "Unknown configuration key '%s' - check for typos...", key)
}
}Gap:
The JSON stdin format is fully compliant (schema uses additionalProperties: false to reject unknown fields). However, TOML format silently accepts unknown fields. The spec says MUST reject without qualification.
Note: This is a conscious design decision for backward compatibility. JSON stdin config is compliant.
Severity: Important (MUST violation for TOML format; JSON stdin is compliant)
File References:
internal/config/config_core.go:259-275
Suggested Fix:
Return an error when unknown TOML keys are found, rather than just warning:
if len(undecoded) > 0 {
return nil, fmt.Errorf("configuration contains unrecognized field(s): %v. Check the MCP Gateway Specification for supported fields.", undecoded)
}Minor Issues (SHOULD Violations)
3. No Random API Key Auto-Generation on Startup
Specification Section: 7.3 Optimal Temporary API Key
Deep Link: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#73-optimal-temporary-api-key
Requirement:
The gateway SHOULD support temporary API keys:
- Generate a random API key on startup if not provided
- Include key in stdout configuration output
Current State: No random API key generation in internal/cmd/root.go. If apiKey is empty, the gateway runs without authentication.
Severity: Minor (SHOULD violation)
File References:
internal/cmd/root.go:324-336
Suggested Fix: Generate a cryptographically random key at startup when none is configured, include it in the stdout configuration output.
4. Unified Mode Prefixes Tool Names with backendID___
Specification Section: 5.2.3 Tool Signature Preservation
Deep Link: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#523-tool-signature-preservation
Requirement:
The gateway SHOULD NOT modify: Tool names, Tool parameters, Tool return values, Method signatures
Current State: In unified mode (/mcp), tools from all backends are prefixed with backendID___ (e.g., github___search_code). In routed mode (/mcp/{server}), the prefix is correctly stripped.
// tool_registry.go:169
prefixedName := fmt.Sprintf("%s___%s", serverID, tool.Name)
// Stored as prefixedName and exposed to clients in unified modeGap: Clients using unified mode see modified tool names. Routed mode is compliant.
Note: This modification is architecturally necessary in unified mode to avoid name collisions across backends. Routed mode is fully compliant.
Severity: Minor (SHOULD NOT — architecturally necessary in unified mode)
File References:
internal/server/tool_registry.go:169-180internal/server/unified.go:606-628
Compliance Status
| Section | Description | Status |
|---|---|---|
| 3.2.1 | Containerization Requirement | ✅ Compliant |
| 4.1 | Configuration Format | ✅ Compliant |
| 4.2 | Variable Expression Rendering | ✅ Compliant |
| 4.3.1 | Unknown Fields — JSON stdin | ✅ Compliant |
| 4.3.1 | Unknown Fields — TOML | |
| 4.3.2 | Schema Validation | ✅ Compliant |
| 4.3.3 | Fail-Fast Requirements | ✅ Compliant |
| 4.1.4 | Custom Server Types | ✅ Compliant |
| 4.1.5 | Volume Mounts | ✅ Compliant |
| 4.1.3.1 | Payload Dir Path Validation | ✅ Compliant |
| 4.1.3.4 | Trusted Bots Configuration | ✅ Compliant |
| 5.1.1 | Endpoint Structure | ✅ Compliant |
| 5.1.3 | Close Endpoint | ✅ Compliant |
| 5.2.3 | Tool Name Preservation (routed) | ✅ Compliant |
| 5.2.3 | Tool Name Preservation (unified) | |
| 5.4 | Stdout Configuration Output | ✅ Compliant |
| 6 | Server Isolation | ✅ Compliant |
| 7.2 | Auth — HTTP 401 for invalid | ✅ Compliant |
| 7.2 | Auth — HTTP 400 for malformed | ❌ Returns 401 instead |
| 7.3 | Random API Key Generation | |
| 7.4 | Health Exemption from Auth | ✅ Compliant |
| 8 | Health Monitoring | ✅ Compliant |
| 9 | Error Handling | ✅ Compliant |
Remediation Tasks
Task 1: HTTP 400 for Malformed Authorization Headers
Description: Add detection of malformed Authorization header content before the API key comparison. Return HTTP 400 for headers containing invalid characters.
Files: internal/server/auth.go
Reference: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#72-api-key-authentication
Effort: Small (1–2 hours)
Task 2: Reject Unknown TOML Fields
Description: Treat unknown TOML configuration keys as fatal errors rather than warnings, to bring TOML parity with the JSON stdin schema enforcement.
Files: internal/config/config_core.go
Reference: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#431-unknown-features
Effort: Small (1–2 hours; may need careful backward compat consideration)
Task 3: Random API Key Auto-Generation
Description: When no apiKey is configured, generate a cryptographically random key at startup and include it in stdout config output.
Files: internal/cmd/root.go
Reference: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md#73-optimal-temporary-api-key
Effort: Small (1–2 hours)
References
- MCP Gateway Specification v1.9.0
- Commit reviewed:
1a09953— refactor: remove redundant config default fallbacks in server and launcher
Note
🔒 Integrity filter blocked 1 item
The following item were blocked because they don't meet the GitHub integrity level.
- get_file_contents
get_file_contents: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
To allow these resources, lower min-integrity in your GitHub frontmatter:
tools:
github:
min-integrity: approved # merged | approved | unapproved | noneGenerated by Daily Compliance Checker · ◷