GoogleContainerTools / GoogleContainerTools/jib

Unvalidated WWW-Authenticate realm allows registry credential exfiltration to attacker-controlled host (CWE-918 SSRF)

Open
#4,523 0 comments 0 reactions 0 assignees View on GitHub
priority: p3
Dominant language
Java
Stars
14.5k
Forks
1.5k
PR merge metrics
No merged PRs in 30d

Description

## Summary

`RegistryAuthenticator.fromAuthenticationMethod()` parses the `realm` value directly out of a registry's `WWW-Authenticate` response header with no validation of its host, then Jib sends the configured registry credentials (Basic auth or OAuth2 refresh token) to that URL:

```java
Pattern realmPattern = Pattern.compile("realm=\"(.*?)\"");
...
String realm = realmMatcher.group(1);
```
```java
URL getAuthenticationUrl(...) {
return isOAuth2Auth(credential) ? new URL(realm) : new URL(realm + "?" + ...);
}
```

Since `realm` is fully attacker-controlled, a malicious or compromised registry can point it at an attacker-controlled HTTPS endpoint and receive the developer's real registry credentials. This fires on Jib's default, most common usage (any registry pull/push with credentials configured) — no special configuration needed.

Note: Jib's `FailoverHttpClient` already strips `Authorization` for plain-HTTP targets, which blocks the trivial plain-HTTP variant — but a realistic attacker just uses HTTPS (free to obtain), bypassing that safeguard entirely. Confirmed with a PoC: a plain-HTTP attacker endpoint received nothing, an HTTPS one received the full Basic-auth credentials.

## Why this matters now — established CWE-918 pattern with 2026 precedent

This is the same root cause (CWE-918, SSRF via unvalidated URL from an upstream response) behind several 2026 CVEs in sibling tools:
- **CVE-2026-33540** — `distribution/distribution` (reference OCI registry impl), fixed by validating realm host matches the expected upstream host
- **CVE-2026-33990** — Google's own Docker Model Runner, identical pattern
- **CVE-2026-48978** (oras-go), **CVE-2026-12566** (BBOT), **CVE-2026-24845** (Malcontent)

## Proof of Concept

Two local mock HTTPS servers (self-signed certs, loopback only):
1. Mock registry → responds to any manifest request with `401` + `WWW-Authenticate: Bearer realm="https:///steal-creds",service="..."`
2. Mock attacker collector → logs the `Authorization` header of anything it receives

```java
Jib.from(RegistryImage.named("/fake/repo:latest")
.addCredential(victimUser, victimPassword))
.containerize(...)
```

Result: the attacker collector received `Authorization: Basic ` — the real configured credential, sent to an unrelated host.

## Why I'm opening an issue rather than a PR this time

Unlike the path-traversal fix (#4522), the correct remediation here is a real compatibility tradeoff, not a one-line guard: legitimate registries commonly use a *different host* for their token-issuing auth server than the registry itself (Docker Hub's `registry-1.docker.io` redirects to `auth.docker.io`). A blind "realm host must equal registry host" check — the fix `distribution/distribution` shipped for CVE-2026-33540 — risks breaking compatibility with real registries Jib supports today (this project's own issue history shows a lot of registry-specific auth handling — Azure ACR, OpenShift, Nexus, etc.).

Options worth your team's consideration, roughly in order of increasing compatibility risk:
1. Reject non-HTTPS realms outright at the point of use (currently only the `Authorization` header gets cleared for plain HTTP; the request still fires).
2. Compare `realm`'s registrable domain (eTLD+1) against the registry's, allowing same-organization cross-subdomain realms (covers Docker Hub) while blocking unrelated domains.
3. An opt-in strict/allowlist mode for users who know their registry's real auth topology in advance.

Happy to attempt a PR for whichever direction the maintainers think is right, or to help test compatibility against known registries if that's useful.

Contributor guide

Open the contributing guide

Research direction

Read RegistryAuthenticator.fromAuthenticationMethod() and getAuthenticationUrl(), then inspect FailoverHttpClient’s Authorization handling. Compare the proposed remediation options against existing registry-specific authentication behavior, including Docker Hub, Azure ACR, OpenShift, and Nexus. Done means an agreed validation policy prevents credentials reaching unrelated HTTPS realms while preserving supported registry compatibility.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, java
Domain
authentication, backend, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.