CVE-2026-118763
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
sigstore-js provides JavaScript libraries for interacting with Sigstore services. Prior to 0.7.2, packages/oci/src/registry.ts contains a RegistryClient.signIn() method that stores registry Authorization and Docker configuration headers as defaults on a shared HTTP client, while RegistryClient.uploadBlob() sends a fresh PUT to an absolute blob-upload Location supplied by the registry without checking that its origin or scheme matches the registry. A malicious or compromised registry can therefore direct a user pushing an artifact through attachArtifactToImage() to an attacker-controlled host and receive the registry bearer token, Basic credentials, or custom authentication headers. Redirect-time header stripping does not prevent the leak because the cross-host PUT is a new explicit request rather than a followed redirect. This is a residual of CVE-2026-59891, whose fix changed credential selection in credentials.ts but did not constrain where credentials are sent from registry.ts. Version 0.7.2 fixes the issue by separating registry credentials from client-wide defaults and sending them only to the registry origin.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.4
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
sigstore-js provides JavaScript libraries for interacting with Sigstore services. Prior to 0.7.2, packages/oci/src/registry.ts contains a RegistryClient.signIn() method that stores registry Authorization and Docker configuration headers as defaults on a shared HTTP client, while RegistryClient.uploadBlob() sends a fresh PUT to an absolute blob-upload Location supplied by the registry without checking that its origin or scheme matches the registry. A malicious or compromised registry can therefore direct a user pushing an artifact through attachArtifactToImage() to an attacker-controlled host and receive the registry bearer token, Basic credentials, or custom authentication headers. Redirect-time header stripping does not prevent the leak because the cross-host PUT is a new explicit request rather than a followed redirect. This is a residual of CVE-2026-59891, whose fix changed credential selection in credentials.ts but did not constrain where credentials are sent from registry.ts. Version 0.7.2 fixes the issue by separating registry credentials from client-wide defaults and sending them only to the registry origin.
- Record
CVE-2026-118763- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Weakness
- CWE-522
- Updated
- 2026-11-02
EUVDEUVD-2026-113272
7.4
sigstore-js provides JavaScript libraries for interacting with Sigstore services. Prior to 0.7.2, packages/oci/src/registry.ts contains a RegistryClient.signIn() method that stores registry Authorization and Docker configuration headers as defaults on a shared HTTP client, while RegistryClient.uploadBlob() sends a fresh PUT to an absolute blob-upload Location supplied by the registry without checking that its origin or scheme matches the registry. A malicious or compromised registry can therefore direct a user pushing an artifact through attachArtifactToImage() to an attacker-controlled host and receive the registry bearer token, Basic credentials, or custom authentication headers. Redirect-time header stripping does not prevent the leak because the cross-host PUT is a new explicit request rather than a followed redirect. This is a residual of CVE-2026-59891, whose fix changed credential selection in credentials.ts but did not constrain where credentials are sent from registry.ts. Version 0.7.2 fixes the issue by separating registry credentials from client-wide defaults and sending them only to the registry origin.
- Record
EUVD-2026-113272- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-j63v-mwhm-56jx
7.4
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
Summary
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
Affected versions and vulnerable location
- Confirmed on sigstore-js at
3a83271(current HEAD). - File:
packages/oci/src/registry.ts.signIn()installs the credential as a DEFAULT header on the shared client:this.#fetch = this.#fetch.defaults({ headers: { [HEADER_AUTHORIZATION]: 'Basic ' + basicAuth } })(:126-128) or... 'Bearer ' + token(:145-147), pluscreds.headersfrom the Docker config (:104).uploadBlob()reads theLocationresponse header (:184), buildsuploadLocation = new URL(location.startsWith('/') ? this.#baseURL + location : location)(:190-192), and PUTs the blob to it through the same client:await this.#fetch(uploadLocation.href, { method: 'PUT', body: blob, headers: { [HEADER_CONTENT_TYPE]: ... } })(:198).
- There is no check that
uploadLocation's host (or scheme) equals the registry host before the PUT is sent.
Root cause
Because signIn() sets Authorization via .defaults(), it is attached to every request the client issues, including requests to a host the client read out of a server response. When a POST to .../blobs/uploads/ returns an absolute Location pointing to a different host, uploadBlob() PUTs the blob there with the registry Authorization header still attached. If the challenge scheme was basic, that header carries the raw registry username:password; if bearer, it carries the access token; creds.headers custom auth headers ride along too.
The library's HTTP layer (make-fetch-happen / minipass-fetch) strips Authorization on cross-host redirects it follows internally, which protects the HEAD ... { redirect: 'follow' } at :167. It does not help here, because the PUT to the upload Location is a fresh, explicit this.#fetch() call, not a followed redirect, so the default header is applied unconditionally.
This is a residual of GHSA-pf56-329r-95rw / CVE-2026-59891 (credential confusion in @sigstore/oci). The fix for that advisory (commit 85c5838) changed only credentials.ts, replacing a key.includes(registry) substring match with an exact host match when SELECTING which Docker credential to load. It never touched registry.ts, which controls WHERE the loaded credential is sent. The cross-host send remains.
Attacker model
A user pushing a signed artifact/attestation to an OCI registry via attachArtifactToImage(). The credential leaks to any host the registry names in the blob-upload Location. This is reachable when the registry is malicious or compromised, or when a registry that legitimately redirects blob uploads to third-party storage is impersonated. The OCI distribution spec permits absolute upload Location values (registries commonly redirect blob storage to a separate host), so a compliant-but-hostile registry can steer the PUT to an attacker host and capture the credential. This is the same "attacker-controlled registry" threat model accepted for GHSA-pf56.
Reachability trace
index.ts:43 attachArtifactToImage() -> new OCIImage(...).addArtifact() -> image.ts:67 this.#client.signIn(credentials) (installs the default Authorization header) -> image.ts:76/79 this.#client.uploadBlob(...) -> registry.ts:198 PUT to the response-supplied Location with the default Authorization header attached. Same RegistryClient instance throughout, so the default persists.
Reproduction
Source-verified. No live push against a hostile registry was executed in this pass. Confirmed:
rg -n "defaults\(|HEADER_AUTHORIZATION|Location|new URL\(|this.#fetch\(uploadLocation" packages/oci/src/registry.ts
git log --oneline -3 -- packages/oci/src/credentials.ts packages/oci/src/registry.ts
signIn() sets Authorization via .defaults(); uploadBlob() PUTs to uploadLocation.href (which may be an absolute cross-host URL) with no host check; the GHSA-pf56 fix commit is the latest…
- Record
GHSA-j63v-mwhm-56jx- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Weakness
- CWE-522
- Updated
- 2026-11-02
NVD
7.4
sigstore-js provides JavaScript libraries for interacting with Sigstore services. Prior to 0.7.2, packages/oci/src/registry.ts contains a RegistryClient.signIn() method that stores registry Authorization and Docker configuration headers as defaults on a shared HTTP client, while RegistryClient.uploadBlob() sends a fresh PUT to an absolute blob-upload Location supplied by the registry without checking that its origin or scheme matches the registry. A malicious or compromised registry can therefore direct a user pushing an artifact through attachArtifactToImage() to an attacker-controlled host and receive the registry bearer token, Basic credentials, or custom authentication headers. Redirect-time header stripping does not prevent the leak because the cross-host PUT is a new explicit request rather than a followed redirect. This is a residual of CVE-2026-59891, whose fix changed credential selection in credentials.ts but did not constrain where credentials are sent from registry.ts. Version 0.7.2 fixes the issue by separating registry credentials from client-wide defaults and sending them only to the registry origin.
- Record
CVE-2026-118763- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Weakness
- CWE-522
- Updated
- 2026-11-02
OSV
7.4
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
sigstore-js provides JavaScript libraries for interacting with Sigstore services. Prior to 0.7.2, packages/oci/src/registry.ts contains a RegistryClient.signIn() method that stores registry Authorization and Docker configuration headers as defaults on a shared HTTP client, while RegistryClient.uploadBlob() sends a fresh PUT to an absolute blob-upload Location supplied by the registry without checking that its origin or scheme matches the registry. A malicious or compromised registry can therefore direct a user pushing an artifact through attachArtifactToImage() to an attacker-controlled host and receive the registry bearer token, Basic credentials, or custom authentication headers. Redirect-time header stripping does not prevent the leak because the cross-host PUT is a new explicit request rather than a followed redirect. This is a residual of CVE-2026-59891, whose fix changed credential selection in credentials.ts but did not constrain where credentials are sent from registry.ts. Version 0.7.2 fixes the issue by separating registry credentials from client-wide defaults and sending them only to the registry origin.
- Record
CVE-2026-118763- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Weakness
- CWE-522
- Updated
- 2026-11-02
OSVGHSA-j63v-mwhm-56jx
7.4
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
Summary
@sigstore/oci sends the registry Authorization header to a cross-host blob-upload Location
Affected versions and vulnerable location
- Confirmed on sigstore-js at
3a83271(current HEAD). - File:
packages/oci/src/registry.ts.signIn()installs the credential as a DEFAULT header on the shared client:this.#fetch = this.#fetch.defaults({ headers: { [HEADER_AUTHORIZATION]: 'Basic ' + basicAuth } })(:126-128) or... 'Bearer ' + token(:145-147), pluscreds.headersfrom the Docker config (:104).uploadBlob()reads theLocationresponse header (:184), buildsuploadLocation = new URL(location.startsWith('/') ? this.#baseURL + location : location)(:190-192), and PUTs the blob to it through the same client:await this.#fetch(uploadLocation.href, { method: 'PUT', body: blob, headers: { [HEADER_CONTENT_TYPE]: ... } })(:198).
- There is no check that
uploadLocation's host (or scheme) equals the registry host before the PUT is sent.
Root cause
Because signIn() sets Authorization via .defaults(), it is attached to every request the client issues, including requests to a host the client read out of a server response. When a POST to .../blobs/uploads/ returns an absolute Location pointing to a different host, uploadBlob() PUTs the blob there with the registry Authorization header still attached. If the challenge scheme was basic, that header carries the raw registry username:password; if bearer, it carries the access token; creds.headers custom auth headers ride along too.
The library's HTTP layer (make-fetch-happen / minipass-fetch) strips Authorization on cross-host redirects it follows internally, which protects the HEAD ... { redirect: 'follow' } at :167. It does not help here, because the PUT to the upload Location is a fresh, explicit this.#fetch() call, not a followed redirect, so the default header is applied unconditionally.
This is a residual of GHSA-pf56-329r-95rw / CVE-2026-59891 (credential confusion in @sigstore/oci). The fix for that advisory (commit 85c5838) changed only credentials.ts, replacing a key.includes(registry) substring match with an exact host match when SELECTING which Docker credential to load. It never touched registry.ts, which controls WHERE the loaded credential is sent. The cross-host send remains.
Attacker model
A user pushing a signed artifact/attestation to an OCI registry via attachArtifactToImage(). The credential leaks to any host the registry names in the blob-upload Location. This is reachable when the registry is malicious or compromised, or when a registry that legitimately redirects blob uploads to third-party storage is impersonated. The OCI distribution spec permits absolute upload Location values (registries commonly redirect blob storage to a separate host), so a compliant-but-hostile registry can steer the PUT to an attacker host and capture the credential. This is the same "attacker-controlled registry" threat model accepted for GHSA-pf56.
Reachability trace
index.ts:43 attachArtifactToImage() -> new OCIImage(...).addArtifact() -> image.ts:67 this.#client.signIn(credentials) (installs the default Authorization header) -> image.ts:76/79 this.#client.uploadBlob(...) -> registry.ts:198 PUT to the response-supplied Location with the default Authorization header attached. Same RegistryClient instance throughout, so the default persists.
Reproduction
Source-verified. No live push against a hostile registry was executed in this pass. Confirmed:
rg -n "defaults\(|HEADER_AUTHORIZATION|Location|new URL\(|this.#fetch\(uploadLocation" packages/oci/src/registry.ts
git log --oneline -3 -- packages/oci/src/credentials.ts packages/oci/src/registry.ts
signIn() sets Authorization via .defaults(); uploadBlob() PUTs to uploadLocation.href (which may be an absolute cross-host URL) with no host check; the GHSA-pf56 fix commit is the latest…
- Record
GHSA-j63v-mwhm-56jx- CVSS 3.1
- 7.4 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N - Weakness
- CWE-522
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@sigstore/ocinpm |
through 0.7.1 | 0.7.2 |
@sigstore/ocinpm |
before 0.7.2 | 0.7.2 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-118763 is a high vulnerability (CVSS 7.4) in Sigstore Sigstore-js, published October 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.30%, the 22nd percentile. Fixed in @sigstore/oci 0.7.2.
References
github.com/sigstore/sigstore-js/security/advisories/GHSA-j63v-mwhm-56jx
github.com/sigstore/sigstore-js/pull/1762
github.com/sigstore/sigstore-js/commit/b855f46cfe81f26481c6d3f4b333dfd00f2fd1b1
github.com/sigstore/sigstore-js/commit/e4ca65c3ab3c675456ab9b0bd04217ceccad3558
github.com/sigstore/sigstore-js/releases/tag/@sigstore/[email protected]
nvd.nist.gov/vuln/detail/CVE-2026-118763
github.com/advisories/GHSA-j63v-mwhm-56jx
github.com/CVEProject/cvelistV5/tree/main/cves/2026/118xxx/CVE-2026-118763.json
github.com/sigstore/sigstore-js
Left out here: the rest of 2 source descriptions. The JSON record has them.