CVE-2026-61836 is a high-severity (CVSS 8.6) CWE-524 vulnerability in directus. A fix is available for directus — see the affected versions and patch details below.
Directus: Authorization-dependent response served from unsegmented cache key
Exploitation Status
No confirmed exploitation observed yet
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-61836.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-61836 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 390,807 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
directusnpmDescription
Summary
When response caching is enabled (CACHE_ENABLED=true), the cache-key derivation in api/src/utils/get-cache-key.ts includes only version, path, query, and accountability.user (plus a conditional ip). Authorization context beyond user (share, role, roles, admin, app, policies) is not part of the key.
For share tokens this is load-bearing. Directus's share-authentication flow (api/src/services/shares.ts:100-105) issues a JWT without an id claim, so api/src/utils/get-accountability-for-token.ts never assigns accountability.user, leaving it null (the default from create-default-accountability.ts). Every share token, and every anonymous request, therefore reduces to user: null in the cache-key input. Two different shares (or an anonymous request and a share token) requesting the same URL with the same query produce identical cache keys. The first request populates the bucket with a permission-filtered response; subsequent hits from unrelated shares or anonymous clients receive that payload without any permission re-evaluation.
This is the web-cache pattern "authorization-dependent response cached under an unsegmented key" (cache key collision / missing authorization context in cache key, CWE-524 and CWE-639). Two adjacent read populations collide:
- Share to share:
Share Apopulates the cache,Share BreadsShare A's scoped response. - Share to anonymous (and the reverse): any unauthenticated client hitting the same URL retrieves cached share-scoped data without presenting any token.
Affected
- Config required:
CACHE_ENABLED=true(any store: memory, redis, memcached) plus at least one activedirectus_sharesrow. This is not a default-on bug:CACHE_ENABLEDships asfalse. The cache is documented as a production performance setting, so operators who enable it are the ones affected.
Vulnerability class
- CWE-524: Use of Cache Containing Sensitive Information
- CWE-639: Authorization Bypass Through User-Controlled Key (the key here is the derived cache key, not the URL)
- OWASP API3:2023: Broken Object Property Level Authorization
Impact
- Cross-share confidentiality breach. Any share's filtered response can be served to a holder of a different share token, or to an anonymous request, that hits the same URL and query. Shares are advertised as a mechanism to distribute scoped, read-only access to specific items; this bug makes every cached share response readable by any other share-token holder who can reach the URL (the item-detail admin UI uses a predictable pattern).
- Anonymous request can read share data. Anonymous requests also compute
user=null. An anonymous client hitting/items/articles?fields=*after a share request has populated the cache receives the share's scoped payload with zero authentication. - Password-protected share, derivative effect. Password protection lives only at
shares.login(JWT issuance). Once any share has populated the cache for a URL, an anonymous or alternate-share request to that URL retrieves the cached payload without exchanging the share password. This is the same cache-key collision surfacing as a password-protection bypass symptom, not a distinct mechanism. - Persistence. The leak persists for the
CACHE_TTLwindow (commonly 5 to 30 minutes).CACHE_AUTO_PURGEclears on mutating writes to cached collections but does not purge per-user or per-share. WithCACHE_STORE=redis(common in production) the poisoned bucket survives server restarts. - No write impact. The bypass is read-only.
Scope of the leak depends on the share's permission surface. A share with no backing role (directus_shares.role = null, the default) collapses visibility to the primary key, so the cache leaks only PKs. A share backed by a role with broader field access (the intended production setup for distributing useful content) leaks the full content that role can see on the scoped item.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | directus | all versions | 12.0.0npm install directus@12.0.0 |
Affected Products
directusmonospaceDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for directus, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update directus to 12.0.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-61836 is resolved across your whole dependency graph.
Workarounds
Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.
Frequently Asked Questions
Is CVE-2026-61836 in your dependencies?
Find it across npm, including transitive dependencies.