07

Inject Headers Without Leaking Secrets

Keep public configuration, credential references, secret values, and final wire headers in separate states. • Lab status: conceptual reconstruction. Receipts are expected simulated outputs, not deployed-system measurements.

System map · Day 07

Whole-system design

Five stable layers. Today's work is expanded and linked; the rest stays in context.

Entry and policy

Covered — Client entry · Browser and callback

Onboarding and control

Covered — Connector control plane

Authorization services

Covered — Authorization server

Compute and execution

Ahead — Refresh coordinator compute

Connector runtime compute

Design target · not proved

Merges static, profile, and credential-derived headers immediately before the network call.

External resource server

Design target · not proved

Receives the final REST or MCP request with the expected authorization placement.

Storage and evidence

Covered — Specification draft store · Sanitized discovery cacheAhead — Ordered migration log

Connector configuration store

Source-backed today

Supplies public static headers and precedence rules without containing reusable secret values.

Secret and token vault

Design target · not proved

Resolves the selected credential only inside the execution boundary and returns no secret to the model.

Evidence plane

Source-backed today

Keeps a redacted wire receipt and proves the secret canary is absent from inputs and logs.

Traversed today

secret resolution · Secret and token vaultConnector runtime computeexecute · Connector runtime computeExternal resource serverobserve · Connector runtime computeEvidence plane

Overview

Why one header map is an unsafe abstraction

Day 02 produced a reviewed operation draft, while Days 04 and 05 produced credential references. If caller headers, static connector headers, and secret material merge into one ordinary object, a caller can override authority or a debug log can expose it. Today you will build final REST and MCP wire headers with explicit precedence, collision denial, and end-to-end redaction.

OpenAPI security schemes describe how an API expects credentials, but their presence does not authorize secret exposure; see the OpenAPI 3.1.2 Security Scheme Object. MCP transport authorization follows the MCP 2025-11-25 authorization profile.

Separate configuration from secret material

The config store may contain public static values and secret references, never secret values. The vault resolves a reference only inside the runtime immediately before dispatch. Header names are normalized before collision checks.

connectorId: calendar-lab
publicHeaders:
  Accept: application/json
secretHeaders:
  X-Calendar-Key: vault://calendar-lab/static/api-key
authorization:
  source: vault://calendar-lab/grants/grant-d04
callerHeaderAllowlist:
  - X-Request-Id

{
  "resolvedFor": "dispatch-d07",
  "references": ["static/api-key", "grants/grant-d04"],
  "valuesReturnedToModel": false,
  "valuesWrittenToLogs": false
}

Apply one deterministic precedence contract

Runtime-owned transport headers such as Host and Content-Length are never caller-controlled. Authorization and secret-backed headers outrank public configuration. Caller headers are admitted only from the allowlist. Any normalized name collision across protected sources fails closed rather than relying on object insertion order.

const precedence = [
  "runtime-reserved",
  "authorization",
  "secret-backed-static",
  "public-static",
  "allowlisted-caller",
] as const;

const protectedNames = new Set(["authorization", "host", "content-length", "x-calendar-key"]);

POST /mcp HTTP/1.1
Host: calendar.example
Accept: application/json
Authorization: Bearer <resolved-in-runtime>
X-Calendar-Key: <resolved-in-runtime>
X-Request-Id: scg-d07
Content-Type: application/json

The same injection pipeline serves REST and MCP; only the body protocol differs. A caller-supplied Authorization or case-variant x-calendar-key is denied before vault resolution. Recovery removes the forbidden caller header and retries with a new dispatch ID. A public operation with only Accept remains the unaffected control.

Verify redaction at every sink

Redaction occurs before model-visible previews, structured logs, errors, traces, and evidence persistence. A canary secret placed in the disposable vault record must appear at the test upstream and nowhere else.

{
  "receipt": "SCG-R07",
  "wireHeaders": {
    "accept": "application/json",
    "authorization": "[REDACTED]",
    "x-calendar-key": "[REDACTED]",
    "x-request-id": "scg-d07"
  },
  "canaryOccurrencesOutsideUpstream": 0
}

Cleanup destroys the canary vault version and request fixture, then scans all captured outputs again. Failure to prove zero out-of-sink occurrences blocks completion.

Score one final-value decision

Given one header name, every candidate source, and the precedence contract, choose the final value/source or deny collision. The unknown is only that resolution. Caller Authorization is denied; allowlisted X-Request-Id is accepted when no protected source owns it.

The misconception is “last write wins is precedence.” Contrast normalized protected-name collision with a permitted caller header. Decline invented secrets, ad hoc exceptions, or logging a raw wire map.

Carry the injection contract forward

SCG-R07 contains normalized precedence, source references, final redacted wire map, collision denial, canary scan, positive control, and cleanup. Day 08 consumes the access credential reference and redaction contract while coordinating refresh across concurrent runtimes.