Skip to content

Commit 52a5662

Browse files
1 parent acb06f3 commit 52a5662

3 files changed

Lines changed: 17 additions & 5 deletions

File tree

advisories/github-reviewed/2026/03/GHSA-3rh2-v3gr-35p9/GHSA-3rh2-v3gr-35p9.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-3rh2-v3gr-35p9",
4-
"modified": "2026-03-31T21:36:46Z",
4+
"modified": "2026-04-08T11:55:44Z",
55
"published": "2026-03-27T22:26:05Z",
66
"aliases": [
77
"CVE-2026-34204"
88
],
99
"summary": "MinIO is Vulnerable to SSE Metadata Injection via Replication Headers",
1010
"details": "## Impact\n\n_What kind of vulnerability is it? Who is impacted?_\n\nA flaw in `extractMetadataFromMime()` allows any authenticated user with `s3:PutObject` permission to inject internal server-side encryption metadata into objects by sending crafted `X-Minio-Replication-*` headers on a normal PutObject request. The server unconditionally maps these headers to `X-Minio-Internal-*` encryption metadata without verifying that the request is a legitimate replication request. Objects written this way carry bogus encryption keys and become **permanently unreadable** through the S3 API.\n\nAny authenticated user or service with `s3:PutObject` permission on any bucket can make objects permanently unreadable by injecting fake SSE encryption metadata. The attacker sends a standard PutObject request with `X-Minio-Replication-Server-Side-Encryption-*` headers but **without** the `X-Minio-Source-Replication-Request` header that marks legitimate replication traffic. The server maps these headers to internal encryption metadata (`X-Minio-Internal-Server-Side-Encryption-Sealed-Key`, etc.), causing all subsequent GetObject and HeadObject calls to treat the object as encrypted with keys that do not exist.\n\nThis is a targeted denial-of-service vulnerability. An attacker can selectively corrupt individual objects or entire buckets. The `ReplicateObjectAction` IAM permission is never checked because the request is a normal PutObject, not a replication request.\n\n**Affected component:** `cmd/handler-utils.go`, function `extractMetadataFromMime()`.\n\n## Affected Versions\n\nAll MinIO releases through the final release of the minio/minio open-source project.\n\nThe vulnerability was introduced in commit `468a9fae83e965ecefa1c1fdc2fc57b84ece95b0` (\"Enable replication of SSE-C objects\", [PR #19107](https://github.com/minio/minio/pull/19107), 2024-03-28). The first affected release is `RELEASE.2024-03-30T09-41-56Z`.\n\n## Patches\n\n**Fixed in**: MinIO AIStor RELEASE.2026-03-26T21-24-40Z\n\n### Binary Downloads\n\n| Platform | Architecture | Download |\n| -------- | ------------ | -------- |\n| Linux | amd64 | [minio](https://dl.min.io/aistor/minio/release/linux-amd64/minio) |\n| Linux | arm64 | [minio](https://dl.min.io/aistor/minio/release/linux-arm64/minio) |\n| macOS | arm64 | [minio](https://dl.min.io/aistor/minio/release/darwin-arm64/minio) |\n| macOS | amd64 | [minio](https://dl.min.io/aistor/minio/release/darwin-amd64/minio) |\n| Windows | amd64 | [minio.exe](https://dl.min.io/aistor/minio/release/windows-amd64/minio.exe) |\n\n### FIPS Binaries\n\n| Platform | Architecture | Download |\n| -------- | ------------ | -------- |\n| Linux | amd64 | [minio.fips](https://dl.min.io/aistor/minio/release/linux-amd64/minio.fips) |\n| Linux | arm64 | [minio.fips](https://dl.min.io/aistor/minio/release/linux-arm64/minio.fips) |\n\n### Package Downloads\n\n| Format | Architecture | Download |\n| ------ | ------------ | -------- |\n| DEB | amd64 | [minio_20260326212440.0.0_amd64.deb](https://dl.min.io/aistor/minio/release/linux-amd64/minio_20260326212440.0.0_amd64.deb) |\n| DEB | arm64 | [minio_20260326212440.0.0_arm64.deb](https://dl.min.io/aistor/minio/release/linux-arm64/minio_20260326212440.0.0_arm64.deb) |\n| RPM | amd64 | [minio-20260326212440.0.0-1.x86_64.rpm](https://dl.min.io/aistor/minio/release/linux-amd64/minio-20260326212440.0.0-1.x86_64.rpm) |\n| RPM | arm64 | [minio-20260326212440.0.0-1.aarch64.rpm](https://dl.min.io/aistor/minio/release/linux-arm64/minio-20260326212440.0.0-1.aarch64.rpm) |\n\n### Container Images\n\n```bash\n# Standard\ndocker pull quay.io/minio/aistor/minio:RELEASE.2026-03-26T21-24-40Z\npodman pull quay.io/minio/aistor/minio:RELEASE.2026-03-26T21-24-40Z\n\n# FIPS\ndocker pull quay.io/minio/aistor/minio:RELEASE.2026-03-26T21-24-40Z.fips\npodman pull quay.io/minio/aistor/minio:RELEASE.2026-03-26T21-24-40Z.fips\n```\n\n### Homebrew (macOS)\n\n```bash\nbrew install minio/aistor/minio\n```\n\n## Workarounds\n\n[Users of the open-source `minio/minio` project should upgrade to MinIO AIStor `RELEASE.2026-03-26T21-24-40Z` or later.](https://docs.min.io/enterprise/aistor-object-store/upgrade-aistor-server/community-edition/)\n\nIf upgrading is not immediately possible:\n\n- **Restrict replication headers at a reverse proxy / load balancer.** Drop or reject any request containing `X-Minio-Replication-Server-Side-Encryption-*` headers that does not also carry `X-Minio-Source-Replication-Request`. This blocks the injection path without modifying the server.\n\n- **Audit IAM policies.** Limit `s3:PutObject` grants to trusted principals. While this reduces the attack surface, it does not eliminate the vulnerability since any authorized user can exploit it.\n\n## References\n\n- Introducing commit: [`468a9fae8`](https://github.com/minio/minio/commit/468a9fae83e965ecefa1c1fdc2fc57b84ece95b0) ([PR #19107](https://github.com/minio/minio/pull/19107))\n- [MinIO AIStor](https://min.io/aistor)",
1111
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H"
15+
},
1216
{
1317
"type": "CVSS_V4",
1418
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N"

advisories/github-reviewed/2026/03/GHSA-qr2g-p6q7-w82m/GHSA-qr2g-p6q7-w82m.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-qr2g-p6q7-w82m",
4-
"modified": "2026-03-07T02:37:47Z",
4+
"modified": "2026-04-08T11:55:22Z",
55
"published": "2026-03-07T02:37:47Z",
66
"aliases": [],
77
"summary": "x402 SDK Security Advisory",
@@ -71,6 +71,10 @@
7171
"type": "WEB",
7272
"url": "https://github.com/coinbase/x402/security/advisories/GHSA-qr2g-p6q7-w82m"
7373
},
74+
{
75+
"type": "WEB",
76+
"url": "https://github.com/x402-foundation/x402/security/advisories/GHSA-qr2g-p6q7-w82m"
77+
},
7478
{
7579
"type": "PACKAGE",
7680
"url": "https://github.com/coinbase/x402"

advisories/github-reviewed/2026/04/GHSA-rp9m-7r4c-75qg/GHSA-rp9m-7r4c-75qg.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-rp9m-7r4c-75qg",
4-
"modified": "2026-04-06T23:41:46Z",
4+
"modified": "2026-04-08T11:54:56Z",
55
"published": "2026-04-03T04:07:09Z",
66
"aliases": [
77
"CVE-2026-35039"
88
],
99
"summary": "fast-jwt: Cache Confusion via cacheKeyBuilder Collisions Can Return Claims From a Different Token (Identity/Authorization Mixup)",
10-
"details": "## Impact\n\nSetting up a custom cacheKeyBuilder method which does not properly create unique keys for different tokens can lead to cache collisions. This could cause tokens to be mis-identified during the verification process leading to:\n\n- Valid tokens returning claims from different valid tokens\n- Users being mis-identified as other users based on the wrong token\n\nThis could result in:\n- User impersonation - UserB receives UserA's identity and permissions\n- Privilege escalation - Low-privilege users inherit admin-level access\n- Cross-tenant data access - Users gain access to other tenants' resources\n- Authorization bypass - Security decisions made on wrong user identity\n\n## Affected Configurations\n\nThis vulnerability ONLY affects applications that BOTH:\n\n1. Enable caching using the cache option\n2. Use custom cacheKeyBuilder functions that can produce collisions\n\nVULNERABLE examples:\n```\n// Collision-prone: same audience = same cache key\ncacheKeyBuilder: (token) => {\n const { aud } = parseToken(token)\n return `aud=${aud}`\n}\n\n// Collision-prone: grouping by user type\ncacheKeyBuilder: (token) => {\n const { aud } = parseToken(token)\n return aud.includes('admin') ? 'admin-users' : 'regular-users'\n}\n\n// Collision-prone: tenant + service grouping\ncacheKeyBuilder: (token) => {\n const { iss, aud } = parseToken(token)\n return `${iss}-${aud}`\n}\n```\n\nSAFE examples:\n```\n// Default hash-based (recommended)\ncreateVerifier({ cache: true }) // Uses secure default\n\n// Include unique user identifier\ncacheKeyBuilder: (token) => {\n const { sub, aud, iat } = parseToken(token)\n return `${sub}-${aud}-${iat}`\n}\n\n// No caching (always safe)\ncreateVerifier({ cache: false })\n```\n### Not Affected\n\n- Applications using **default caching**\n- Applications with **caching disabled**\n \n## Assessment Guide\n\nTo determine if a consumer application is affected:\n\n1. Check if caching is enabled: Look for cache: true or cache: <number> in verifier configuration\n2. Check for custom cache key builders: Look for cacheKeyBuilder function in configuration\n3. Analyze collision potential: Review if the application's cacheKeyBuilder can produce identical keys for different users/tokens\n4. If no custom cacheKeyBuilder: The project is NOT affected (default is safe)\n\n## Mitigations\n\nWhile fast-jwt will look to include a fix for this in the next version, immediate mitigations include:\n\n- Ensure uniqueness of keys produced in cacheKeyBuilder\n- Remove custom cacheKeyBuilder method\n- Disable caching",
10+
"details": "_NOTE_: While the library exposes a mechanism which could introduce the vulnerability, this issue is created by developer-supplied code and not by the library itself. We will add a warning and some education for users around the possible issues however since the defaults work we will not be updating the library beyond that for this advisory.\n\n## Impact\n\nSetting up a custom cacheKeyBuilder method which does not properly create unique keys for different tokens can lead to cache collisions. This could cause tokens to be mis-identified during the verification process leading to:\n\n- Valid tokens returning claims from different valid tokens\n- Users being mis-identified as other users based on the wrong token\n\nThis could result in:\n- User impersonation - UserB receives UserA's identity and permissions\n- Privilege escalation - Low-privilege users inherit admin-level access\n- Cross-tenant data access - Users gain access to other tenants' resources\n- Authorization bypass - Security decisions made on wrong user identity\n\n## Affected Configurations\n\nThis vulnerability ONLY affects applications that BOTH:\n\n1. Enable caching using the cache option\n2. Use custom cacheKeyBuilder functions that can produce collisions\n\nVULNERABLE examples:\n```\n// Collision-prone: same audience = same cache key\ncacheKeyBuilder: (token) => {\n const { aud } = parseToken(token)\n return `aud=${aud}`\n}\n\n// Collision-prone: grouping by user type\ncacheKeyBuilder: (token) => {\n const { aud } = parseToken(token)\n return aud.includes('admin') ? 'admin-users' : 'regular-users'\n}\n\n// Collision-prone: tenant + service grouping\ncacheKeyBuilder: (token) => {\n const { iss, aud } = parseToken(token)\n return `${iss}-${aud}`\n}\n```\n\nSAFE examples:\n```\n// Default hash-based (recommended)\ncreateVerifier({ cache: true }) // Uses secure default\n\n// Include unique user identifier\ncacheKeyBuilder: (token) => {\n const { sub, aud, iat } = parseToken(token)\n return `${sub}-${aud}-${iat}`\n}\n\n// No caching (always safe)\ncreateVerifier({ cache: false })\n```\n### Not Affected\n\n- Applications using **default caching**\n- Applications with **caching disabled**\n \n## Assessment Guide\n\nTo determine if you're affected:\n\n1. Check if caching is enabled: Look for cache: true or cache: <number> in verifier configuration\n2. Check for custom cache key builders: Look for cacheKeyBuilder function in configuration\n3. Analyze collision potential: Review if your cacheKeyBuilder can produce identical keys for different users/tokens\n4. If no custom cacheKeyBuilder: You are NOT affected (default is safe)\n\n## Mitigations\n\nMitigations include:\n\n- Ensure uniqueness of keys produced in cacheKeyBuilder\n- Remove custom cacheKeyBuilder method\n- Disable caching\n\n---\n\nfast-jwt allows enabling a verification cache through the cache option.\nThe cache key is derived from the token via cacheKeyBuilder.\n\nWhen a custom cacheKeyBuilder produces collisions between different tokens, the verifier may return the cached payload of a previous token instead of validating and returning the payload of the current token.\n\nThis results in cross-token payload reuse and identity confusion.\n\nTwo distinct valid JWTs can be verified successfully but mapped to the same cached entry, causing the verifier to return claims belonging to a different token.\n\nThis affects authentication and authorization decisions when applications trust the returned payload.\n\nAffected component\n\nsrc/verifier.js\n\nRelevant logic:\n\ncache enabled via createCache\n\ncache population via cacheSet\n\nlookup based on cacheKeyBuilder(token)\n\ncached payload returned without re-verification\n\nImpact\n\nIdentity / authorization confusion via cache collision.\n\nIf two tokens generate the same cache key:\n\ntoken A is verified → payload stored in cache\n\ntoken B is verified → cache hit occurs\n\nverifier returns payload from token A instead of B\n\nObserved effect:\n\nsubject mismatch\n\nclaim mismatch\n\nauthorization decision performed on wrong identity\n\nPotential real-world consequences:\n\nuser impersonation (logical)\n\nprivilege confusion\n\nincorrect RBAC evaluation\n\ngateway / middleware auth inconsistencies\n\nThis is especially dangerous when:\n\ncache is enabled (recommended for performance)\n\ncustom cacheKeyBuilder is used\n\nidentity claims (sub / aud / iss) drive authorization\n\nRoot cause\n\nThe verifier assumes the cache key uniquely identifies the token and its claims.\n\nHowever:\n\ncacheKeyBuilder is user-controlled\n\ncollisions are not detected\n\ncache entries store decoded payload\n\ncached payload is returned without binding validation\n\nThis creates a trust boundary break between:\n\ntoken → cache key → cached payload\n\nProof of concept\n\nEnvironment:\n\nfast-jwt: 6.1.0\n\nNode.js: v24.13.1\n\nPoC:\n\nconst { createSigner, createVerifier } = require('fast-jwt')\n\nconst sign = createSigner({ key: 'secret' })\n\n// Two distinct tokens\nconst t1 = sign({ sub: 'userA', aud: 'admin' })\nconst t2 = sign({ sub: 'userB', aud: 'admin' })\n\n// Deliberately unsafe cache key builder (collision)\nconst verify = createVerifier({\n key: 'secret',\n cache: true,\n cacheKeyBuilder: () => 'static-key'\n})\n\nconsole.log('verify t1')\nconst p1 = verify(t1)\nconsole.log('t1 PASS sub=', p1.sub)\n\nconsole.log('verify t2')\nconst p2 = verify(t2)\nconsole.log('t2 PASS sub=', p2.sub)\n\nconsole.log('verify t2 again')\nconst p3 = verify(t2)\nconsole.log('t2-again PASS sub=', p3.sub)\n\nconsole.log('verify t1 again')\nconst p4 = verify(t1)\nconsole.log('t1-again PASS sub=', p4.sub)\n\nObserved output:\n\nverify t1\nt1 PASS sub= userA\n\nverify t2\nt2 PASS sub= userA\n\nverify t2 again\nt2-again PASS sub= userA\n\nverify t1 again\nt1-again PASS sub= userA\n\nThe verifier returns payload from userA when verifying userB.\n\nExpected behavior\n\nCache must not allow returning claims from a different token.\n\nVerification must remain bound to the actual token being validated.\n\nEven if cache collisions occur, the verifier should:\n\nrevalidate signature\n\nre-decode payload\n\nor invalidate cache entry\n\nWhy this is not “just misuse”\n\nThis is not merely a user mistake.\n\nReasons:\n\nfast-jwt explicitly exposes cacheKeyBuilder as an extension point.\n\nThe documentation suggests performance tuning via custom key builders.\n\nNo safeguards exist against collisions.\n\nNo verification binding is performed between:\n\ncached payload\n\noriginal token\n\nThe verifier trusts cache output as authoritative identity.\n\nThis creates a security-sensitive invariant:\n\n\"cache key uniqueness\"\n\nwhich is neither enforced nor validated.\n\nSecurity-critical libraries must assume extension hooks can be misused and implement defensive checks, especially when identity decisions are derived from cached values.\n\nSecurity classification\n\nlogical authorization flaw\n\ncache confusion vulnerability\n\nidentity boundary break\n\nClosest CWE:\n\nCWE-440 — Expected Behavior Violation\n\nSuggested fix (minimal and safe)\n\nBind cache entries to token integrity.\n\nOption A — safest:\n\nStore token hash along with payload and verify match before returning cache.\n\nConceptual patch:\n\nconst tokenHash = hashToken(token)\n\ncache.set(key, { tokenHash, payload })\n\n...\n\nconst entry = cache.get(key)\n\nif (entry && entry.tokenHash === hashToken(token)) {\n return entry.payload\n}\n\nOption B — simpler:\n\nDisable cache usage when custom cacheKeyBuilder is provided.\n\nOption C — defensive:\n\nAlways re-validate signature when cache hit occurs.\n\nNotes\n\nDefault cacheKeyBuilder is safe (hash-based).\n\nIssue appears when custom builders are used — a documented and supported feature.\n\nImpact increases in:\n\nAPI gateways\n\nauth middleware\n\nRBAC layers relying on payload.sub / payload.aud\n\nThis vulnerability is independent from:\n\nRegExp statefulness issue\n\nReDoS claim validation issue\n\nIt is a separate flaw in cache design and trust model.\n\nPoC did on my computer:\n'use strict'\n\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst { createSigner, createVerifier } = require('./src')\n\nfunction nowSec() {\n return Math.floor(Date.now() / 1000)\n}\n\nconst sign = createSigner({ key: 'secret' })\nconst t1 = sign({ sub: 'userA', aud: 'admin', iat: nowSec() })\nconst t2 = sign({ sub: 'userB', aud: 'admin', iat: nowSec() })\n\nfunction badKeyBuilder() {\n return 'aud=admin'\n}\n\nconst verify = createVerifier({\n key: 'secret',\n cache: true,\n cacheTTL: 60000,\n cacheKeyBuilder: badKeyBuilder\n})\n\nfunction run(tok) {\n try {\n const out = verify(tok)\n return { ok: true, sub: out.sub, aud: out.aud }\n } catch (e) {\n return { ok: false, code: e.code || String(e), message: e.message }\n }\n}\n\nconst results = []\nresults.push({ step: 'verify(t1)', token: 't1', result: run(t1) })\nresults.push({ step: 'verify(t2)', token: 't2', result: run(t2) })\nresults.push({ step: 'verify(t2) again', token: 't2', result: run(t2) })\nresults.push({ step: 'verify(t1) again', token: 't1', result: run(t1) })\n\nconst evidence = {\n title: 'fast-jwt cache confusion when cacheKeyBuilder collisions occur',\n environment: {\n node: process.version,\n fastJwt: require('./package.json').version\n },\n config: {\n cache: true,\n cacheTTL: 60000,\n cacheKeyBuilder: \"returns constant key 'aud=admin' (realistic collision pattern)\"\n },\n tokens: {\n t1: { claims: { sub: 'userA', aud: 'admin' }, jwt: t1 },\n t2: { claims: { sub: 'userB', aud: 'admin' }, jwt: t2 }\n },\n observed: results\n}\n\nconst outPath = path.join(process.cwd(), 'evidence-cache-keybuilder-confusion.json')\nfs.writeFileSync(outPath, JSON.stringify(evidence, null, 2))\nconsole.log('Wrote evidence to:', outPath)\n\nfor (const r of results) {\n console.log(r.step, '=>', r.result.ok ? `PASS sub=${r.result.sub}` : `FAIL ${r.result.code}`)\n}\n\nOutput:\nPS C:\\Users\\Franciny Rojas\\Desktop\\crypto-research\\fast-jwt> node poc_cache_keybuilder_confusion_evidence.js\nWrote evidence to: C:\\Users\\Franciny Rojas\\Desktop\\crypto-research\\fast-jwt\\evidence-cache-keybuilder-confusion.json\nverify(t1) => PASS sub=userA\nverify(t2) => PASS sub=userA\nverify(t2) again => PASS sub=userA\nverify(t1) again => PASS sub=userA\nPS C:\\Users\\Franciny Rojas\\Desktop\\crypto-research\\fast-jwt>",
1111
"severity": [
1212
{
1313
"type": "CVSS_V3",
@@ -28,7 +28,7 @@
2828
"introduced": "0.0.1"
2929
},
3030
{
31-
"fixed": "6.1.0"
31+
"fixed": "6.2.0"
3232
}
3333
]
3434
}
@@ -44,6 +44,10 @@
4444
"type": "ADVISORY",
4545
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35039"
4646
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/nearform/fast-jwt/commit/de121056c6415b58770c60640881eaec67ac4ceb"
50+
},
4751
{
4852
"type": "PACKAGE",
4953
"url": "https://github.com/nearform/fast-jwt"

0 commit comments

Comments
 (0)