security: a credential resolver returns a token without the cleartext-http check #714

Closed
opened 2026-10-04 18:57:13 +00:00 by hexajon · 1 comment
Owner

What happens

madtea resolves forge credentials through a fallback chain. One resolver, GetCredentialsWithSource (internal/config/config.go:545-549), has an environment-variable branch that returns the URL and token without running RequireSecureScheme - the guard that refuses to send a token over a non-loopback http:// connection. The host-keyed and other resolvers run the guard; this branch does not.

Not exploitable today

Every token-bearing request re-runs the guard where it attaches the token, in doAuthedRequest (internal/config/request.go:26-30), and all three current callers of the resolver are verified safe. So nothing leaks today. The gap is latent: a future caller of this resolver could use its result directly and skip the guard, sending a token over cleartext.

Decision

Add RequireSecureScheme in the resolver itself, so the guard cannot be skipped by a future caller. This matches ADR 0041 - the token-security check belongs at the point that carries the token, not at each caller. Non-breaking: an https or loopback setup is unaffected; only a non-loopback http env URL carrying a token is refused, which ADR 0041 already forbids everywhere else.

Scope

Severity low: latent, not currently reachable.

Acceptance criteria

  • The environment-variable branch of GetCredentialsWithSource runs RequireSecureScheme before it returns a token.
  • A test proves the resolver refuses a token for a non-loopback http URL.
## What happens madtea resolves forge credentials through a fallback chain. One resolver, `GetCredentialsWithSource` (`internal/config/config.go:545-549`), has an environment-variable branch that returns the URL and token without running `RequireSecureScheme` - the guard that refuses to send a token over a non-loopback `http://` connection. The host-keyed and other resolvers run the guard; this branch does not. ## Not exploitable today Every token-bearing request re-runs the guard where it attaches the token, in `doAuthedRequest` (`internal/config/request.go:26-30`), and all three current callers of the resolver are verified safe. So nothing leaks today. The gap is latent: a future caller of this resolver could use its result directly and skip the guard, sending a token over cleartext. ## Decision Add `RequireSecureScheme` in the resolver itself, so the guard cannot be skipped by a future caller. This matches ADR 0041 - the token-security check belongs at the point that carries the token, not at each caller. Non-breaking: an `https` or loopback setup is unaffected; only a non-loopback `http` env URL carrying a token is refused, which ADR 0041 already forbids everywhere else. ## Scope Severity low: latent, not currently reachable. ## Acceptance criteria - [ ] The environment-variable branch of `GetCredentialsWithSource` runs `RequireSecureScheme` before it returns a token. - [ ] A test proves the resolver refuses a token for a non-loopback `http` URL.
Author
Owner

Duplicate of #715 (same finding, filed clean).

Duplicate of #715 (same finding, filed clean).
hexajon 2026-10-05 12:31:14 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#714
No description provided.