Skip to content

[compliance] Compliance Gap: Authentication Returns HTTP 401 for All Auth Failures (MUST Require HTTP 400 for Malformed Headers) #3057

@github-actions

Description

@github-actions

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.apiKey is 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:

  1. Generate a random API key on startup if not provided
  2. 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 mode

Gap: 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-180
  • internal/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 ⚠️ Warn only (not reject)
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) ⚠️ Prefixed with backendID___
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 ⚠️ Not implemented (SHOULD)
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

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 | none

Generated by Daily Compliance Checker ·

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions