upstream-credential
Each caller's own credential reaches the upstream
The sections below are generated from the CLI (methodology 0.3-draft, CLI 0.3.0); the same text is printed by sealmark explain upstream-credential.
- pack
upstreamopt-in pack- weight
- criticalcandidate
- scope
- server (what the harness's upstream stub received from the server, and what the server printed or relayed)
- decided by
- upstream
- since
- 0.3-draft (methodology 0.3-draft)
- config keys
checks.upstream-credential.enabledchecks.upstream-credential.severityidentities.aidentities.bupstream.credential_headerupstream.kind
Probes
identity-aevery valid call (a `probes:` entry without `check`) as identity a ({bearer:a}); the stub records the credential header of each request the server makesidentity-bthe same calls as identity b ({bearer:b}); a request that carries identity a's token (a cached credential) or a credential that is neither identity's (a static one) failsanonymousthe same calls with every header that holds {bearer} dropped; a refusal is fine, a request that reaches the upstream with a credential header fails
Settings and thresholds
Every check also takes checks.upstream-credential.enabled and checks.upstream-credential.severity; they are described once in the configuration reference.
This check has no numeric threshold.
| Key | Default | Standard | Meaning |
|---|---|---|---|
identities.a | none | not locked | Token the harness sends as caller A wherever the server config says {bearer} or {bearer:a}. null mints one per run. Set it when the server validates tokens it did not issue. ${VAR} is read from the environment. Treated as a secret: redacted in config show and in reports (flag --identity-a). |
identities.b | none | not locked | Token the harness sends as caller B ({bearer:b}). null mints one per run. Must differ from identities.a. Treated as a secret (flag --identity-b). |
upstream.credential_header | authorization | not locked | Header the upstream-credential check reads the forwarded credential from (compared case-insensitively). |
upstream.kind | none | not locked | Kind of the harness-owned upstream stub the server's backend is pointed at through {upstream}. http starts a loopback stub that records every request the server forwards (flag --upstream). null starts none. The stub needs a server Sealmark starts, and the server must use {upstream} in command, args, env, url, headers or files. |
How the verdict is established
- Scoring. critical and scored: pass = 1 point, part = 0.5, fail = 0. A fail caps the pack's grade at D, whatever the other checks scored.
What to fix
Pass each caller's own credential to the backend, taken from the request that arrived: never a static token, an environment variable, or a value cached from the first caller. An anonymous request must reach the backend with no credential, or be refused. If the server validates tokens it did not issue, every call is refused and the check is inconclusive: set identities.a and identities.b to real tokens (from the environment, not the file).
False positives
A server that validates the tokens it receives refuses the minted ones, so nothing reaches the stub: the check is inconclusive, never a fail (set identities.a and identities.b to real tokens). A server that deliberately uses its own service credential for some tools fails on those tools.
False negatives
Only the harness's valid calls are observed; a tool the harness did not call can still use a shared credential. A request that carries no credential at all is reported but is not a fail.