Skip to content

Auth credential hygiene: Basic/Digest password redaction, replay guard over every credential header #71

Description

@Wahbeh-Mohammad

Part of the audit remediation umbrella #67. Milestone 2. Severity: MEDIUM (security). Requirements: AUTH-8, AUTH-28, XCUT-16.

Current SDK behavior

Passwords in plain fields. BasicCredential and DigestCredential
(packages/core/src/auth/auth-step.ts:36-41,48-58) are structural interfaces with a public
password: string. ApiKeyCredential, NameKeyCredential and BearerToken in
credential.ts keep the secret in a #private field and override toString and
nodejs.util.inspect.custom. util.inspect(credentials) on an AuthCredentialSet prints
password: 'hunter2' beside ApiKeyCredential{key=***}. JSON.stringify serializes both
passwords. docs/sdk-documentation/auth.md:40-46 shows the raw-password shape directly above
the claim that a credential cannot leak into a log line by accident.

Replay guard checks two header names. After a 401, the auth step calls
guardReplayScheme (auth-step.ts:549-567) on the replacement request. The guard tests only
Authorization and Proxy-Authorization (:554-556). ApiKeyCredentialConfig.headerName
(:81) lets the step stamp any header. A challengeHook that returns a replacement on
http:// with X-Api-Key: SECRET is dispatched in clear text. No PlaintextCredentialError
is thrown.

Expected behavior

The SDK redacts every credential type in every string or diagnostic representation. The
Basic and Digest credentials do not expose the password as a plain property. The SDK refuses
to send a replay over plain HTTP when the replacement request carries any header the step
treats as a credential carrier.

Notes and leads

  • Passwords: add BasicCredential / DigestCredential classes (or createBasicCredential()
    factories) with #password, toString, and the inspect override, matching credential.ts.
    Accept them in AuthCredentialSet. Update auth.md. This is a public-shape change; it is
    free before the first version bump (docs/first-release.md). Minor changeset for
    @dexpace/core.
  • Replay guard: simplest correct rule is "if the original request was guarded, run
    requireHttps on the replacement, regardless of headers". Alternative: build the set of
    credential-carrying names from the step's configuration and check each.
  • AUTH-8 names bearer, API-key and name-key types only. Record the wider reading in the Phase
    5c ledger section.
  • Tests: util.inspect and JSON.stringify on a full AuthCredentialSet contain no
    password; a replay with an API-key header on http:// throws PlaintextCredentialError.
    Add both to packages/core/src/auth/ and the API-key case to
    tests/conformance/xcut/security-by-default.conformance.test.ts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:authAuthentication and credentials: AUTH-*area:coreCore HTTP, IO, body, context, encoding: HTTP-* IO-* BODY-* CTX-* UTF-*area:resilienceRetry, recovery, redirects: RETRY-* RECOV-* REDIR-*securitySecurity impact; see SECURITY.md for private reportstype:bugDefect in shipped behavior

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions