Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Primary rating from Vendor (https://github.com/distribution/distribution).
CVSS VectorVendor: https://github.com/distribution/distribution
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Lifecycle Timeline
6DescriptionCVE.org
summary:
distribution can restore read access in repo a after an explicit delete when storage.cache.blobdescriptor: redis and storage.delete.enabled: true are both enabled. the delete path clears the shared digest descriptor but leaves stale repo-scoped membership behind, so a later Stat or Get from repo b repopulates the shared descriptor and makes the deleted blob readable from repo a again.
Severity
HIGH
justification: this is a repo-local authorization bypass after explicit delete, with concrete confidentiality impact and no requirement for write access after the delete event. CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (7.5). CWE-284.
affected version
- repository: https://github.com/distribution/distribution
- commit: ab67ffa0bda3712991194841d0fde727464feeb9
- affected versions: \<= 3.0.x, \<= 2.8.x when redis blob descriptor cache and delete are both enabled
- affected file:
- https://github.com/distribution/distribution/blob/ab67ffa0bda3712991194841d0fde727464feeb9/registry/storage/cache/redis/redis.go#L212-L226
- related callsites:
- https://github.com/distribution/distribution/blob/ab67ffa0bda3712991194841d0fde727464feeb9/registry/storage/cache/cachedblobdescriptorstore.go#L66-L76
- https://github.com/distribution/distribution/blob/ab67ffa0bda3712991194841d0fde727464feeb9/registry/storage/linkedblobstore.go#L218-L224
- https://github.com/distribution/distribution/blob/ab67ffa0bda3712991194841d0fde727464feeb9/registry/storage/linkedblobstore.go#L396-L403
details
the backend access model is repository-link based: once repo a deletes its blob link, later reads from repo a should continue returning ErrBlobUnknown even if the same digest remains linked in repo b.
the issue is the split invalidation path in the redis cache backend:
linkedBlobStore.DeletecallsblobAccessController.Clearduring repository delete handling.cachedBlobStatter.Clearforwards that invalidation into the cache layer.repositoryScopedRedisBlobDescriptorService.Clearchecks that the digest is a member ofrepo a, but then only callsupstream.Clear.upstream.Cleardeletes the shared digest descriptor and does not remove the digest from the repository membership set forrepo a.- when
repo blater stats or gets the same digest, the shared descriptor is recreated. repositoryScopedRedisBlobDescriptorService.Statforrepo aaccepts the stale membership and now trusts the repopulated shared descriptor, restoring access in the repository that already deleted its link.
this creates a revocation gap at the repository boundary. the blob is briefly inaccessible from repo a right after delete, which confirms the backend link was removed, and then becomes accessible again only because stale redis membership survived while a peer repository repopulated the shared descriptor.
attack scenario
- an operator runs distribution with
storage.cache.blobdescriptor: redisandstorage.delete.enabled: true. - the same digest exists in both
repo aandrepo b. - the operator deletes the blob from
repo aand expects repository-local access to be revoked. repo acorrectly returnsblob unknownimmediately after the delete.- an anonymous or unprivileged user requests the same digest from
repo b, which still legitimately owns it and repopulates the shared descriptor. - a later request for the digest from
repo asucceeds again because stale repo-a membership was never revoked from redis.
PoC
attachment: poc.zip
the attached PoC is a deterministic integration harness using miniredis and the pinned distribution source tree.
steps to reproduce
canonical:
unzip -q -o poc.zip -d poc
cd poc
make canonicalexpected output:
[CALLSITE_HIT]: repositoryScopedRedisBlobDescriptorService.Clear->upstream.Clear->repositoryScopedRedisBlobDescriptorService.Stat
[PROOF_MARKER]: repo_a_access_restored=true repo_a_delete_miss=true repo_b_peer_warm=true
[IMPACT_MARKER]: repo_a_post_delete_read=true confidentiality_boundary_broken=truecontrol:
unzip -q -o poc.zip -d poc
cd poc
make controlexpected control output:
[CALLSITE_HIT]: repositoryScopedRedisBlobDescriptorService.Clear->repositoryScopedRedisBlobDescriptorService.Stat
[NC_MARKER]: repo_a_access_restored=false repo_b_peer_warm=trueexpected vs actual
- expected: after
repo adeletes its blob link, later reads fromrepo ashould keep returningblob unknowneven ifrepo bstill references the same digest and warms cache state. - actual:
repo afirst returnsblob unknown, thenrepo brepopulates the shared descriptor, andrepo aserves the deleted digest again through stale repo-scoped redis membership.
impact
the confirmed impact is repository-local confidentiality failure after explicit delete. an operator can remove sensitive content from repo a, observe revocation working immediately after the delete, and still have the same content become readable from repo a again as soon as repo b refreshes the shared descriptor for that digest.
this is not a claim about global blob deletion. the bounded claim is that repository-local revocation fails, which breaks the expectation that deleting a blob link from one repository prevents further reads from that repository.
remediation
the safest fix is to make redis invalidation revoke repo-scoped state together with the backend link deletion. in practice that means removing the digest from the repository membership set, deleting the repo-scoped descriptor hash, and keeping that cleanup atomic enough that peer-repository warming cannot restore access in the repository that already deleted its link.
AnalysisAI
Distribution container registry versions ≤3.0.x and ≤2.8.x restore read access to explicitly deleted blobs when Redis blob descriptor caching and storage deletion are both enabled. After an administrator deletes a blob from repository A, the deletion briefly succeeds, but when repository B later accesses the same digest, it repopulates the shared Redis descriptor cache. Repository A then regains unauthorized read access to the deleted blob because stale repository-scoped membership metadata was never invalidated from Redis. This authorization bypass defeats repository-local content revocation with concrete confidentiality impact. CVSS 7.5 (HIGH) with network attack vector, low complexity, and no authentication required. EPSS exploitation probability is very low (0.03%, 9th percentile), suggesting limited real-world targeting despite public POC availability. Vendor-released patch confirms the issue and provides a fix in version 3.1.0.
Technical ContextAI
Distribution (formerly Docker Registry) is a stateless, highly scalable container registry implementation. The vulnerability lies in the Redis-backed blob descriptor cache layer (storage.cache.blobdescriptor: redis), which implements a two-tier state model: shared digest descriptors and repository-scoped membership sets. When storage.delete.enabled: true is configured, the delete code path (linkedBlobStore.Delete → blobAccessController.Clear → cachedBlobStatter.Clear → repositoryScopedRedisBlobDescriptorService.Clear) only invalidates the shared digest descriptor via upstream.Clear but fails to remove the digest from the repository-scoped membership set in Redis. Later, when a peer repository (repo B) legitimately accesses the same digest via Stat or Get, it repopulates the shared descriptor. The original repository (repo A) then trusts the stale membership metadata and re-authorizes access to content it had already deleted. This maps to CWE-284 (Improper Access Control) because the cache layer violates the repository-link-based access model's revocation invariant: once a repository deletes its blob link, it should never regain read access to that digest regardless of peer repository state. The affected code paths are in registry/storage/cache/redis/redis.go (L212-226), cachedblobdescriptorstore.go (L66-76), and linkedblobstore.go (L218-224, L396-403).
RemediationAI
Upgrade to Distribution 3.1.0 or later, which includes the vendor-released patch (commit 078b0783f239b4115d1a979e66f08832084e9d1d) that atomically removes digests from repository-scoped membership sets during blob deletion. Refer to GitHub Security Advisory GHSA-f2g3-hh2r-cwgc for upgrade guidance. If immediate upgrade is not feasible, implement these compensating controls with their trade-offs: (1) Disable storage.delete.enabled: true to prevent delete operations entirely-this eliminates the vulnerability but also removes the ability to reclaim storage, impacting compliance workflows that depend on permanent deletion. (2) Switch from storage.cache.blobdescriptor: redis to storage.cache.blobdescriptor: inmemory or disable blob descriptor caching entirely-this closes the attack vector but degrades registry performance, especially for Stat-heavy workloads, as every descriptor lookup hits backend storage. (3) Implement external cache invalidation: after deleting a blob from repository A, manually flush the corresponding Redis keys (both the shared descriptor hash and the repository membership set)-this requires custom scripting, introduces operational complexity, and risks race conditions if not executed atomically with the delete operation. None of these workarounds provide the same security guarantee as the patched code, which ensures repository-local revocation survives peer repository cache warming.
LiteSpeed User-End cPanel Plugin before 2.4.5 allows privilege escalation (possibly to root), as exploited in the wild i
UAF in Redis 8.2.1 via crafted Lua scripts by authenticated users. EPSS 12.4%. Patch available.
It was discovered, that redis, a persistent key-value database, due to a packaging issue, is prone to a (Debian-specific
Memory Corruption was discovered in the cmsgpack library in the Lua subsystem in Redis before 3.2.12, 4.x before 4.0.10,
Redis is an open source, in-memory database that persists on disk. Versions 8.2.1 and below allow an authenticated user
Redis before 2.8.21 and 3.x before 3.0.2 allows remote attackers to execute arbitrary Lua bytecode via the eval command.
A buffer overflow in Redis 3.2.x prior to 3.2.4 causes arbitrary code execution when a crafted command is sent. Rated cr
Code injection in OneUptime monitoring via custom JS monitor using vm module. PoC and patch available.
In applications using jfinal 4.9.08 and below, there is a deserialization vulnerability when using redis,may be vulnerab
An issue was found in Apache Airflow versions 1.10.10 and below. Rated critical severity (CVSS 9.8), this vulnerability
An Integer Overflow issue was discovered in the struct library in the Lua subsystem in Redis before 3.2.12, 4.x before 4
goanother Another Redis Desktop Manager =<1.6.1 is vulnerable to Cross Site Scripting (XSS) via src/components/Setting.v
Same weakness CWE-284 – Improper Access Control
View allSame technique Authentication Bypass
View allVendor StatusVendor
SUSE
Severity: High| Product | Status |
|---|---|
| SUSE Linux Enterprise High Performance Computing 15 SP7 | Fixed |
| SUSE Linux Enterprise Micro 5.5 | Fixed |
| SUSE Linux Enterprise Module for Containers 15 SP7 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP7 | Fixed |
| SUSE Linux Enterprise Server 15 SP7 | Fixed |
| SUSE Linux Enterprise Server 16.0 | Fixed |
| SUSE Linux Enterprise Server 16.1 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP7 | Fixed |
| SUSE Linux Enterprise Server for SAP applications 16.0 | Fixed |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Fixed |
| SUSE Linux Micro 6.0 | Fixed |
| SUSE Linux Micro 6.0 | Fixed |
| SUSE Linux Micro 6.1 | Fixed |
| SUSE Linux Micro 6.1 | Fixed |
| SUSE Linux Micro 6.2 | Fixed |
| SUSE Linux Micro 6.2 | Fixed |
| openSUSE Leap 15.6 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP4 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP4-LTSS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP5 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP5-LTSS | Fixed |
| SUSE Linux Enterprise Module for Containers 15 SP4 | Fixed |
| SUSE Linux Enterprise Module for Containers 15 SP5 | Fixed |
| SUSE Linux Enterprise Module for Containers 15 SP6 | Fixed |
| SUSE Linux Enterprise Server 15 SP4 | Fixed |
| SUSE Linux Enterprise Server 15 SP4-LTSS | Fixed |
| SUSE Linux Enterprise Server 15 SP5 | Fixed |
| SUSE Linux Enterprise Server 15 SP5-LTSS | Fixed |
| SUSE Linux Enterprise Server 15 SP6 | Fixed |
| SUSE Linux Enterprise Server 15 SP6-LTSS | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP6 | Fixed |
| SUSE Manager Proxy 4.3 | Fixed |
| SUSE Manager Retail Branch Server 4.3 | Fixed |
| SUSE Manager Server 4.3 | Fixed |
| SUSE Enterprise Storage 7.1 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP3 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP3-ESPOS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP3-LTSS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP4-ESPOS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP5-ESPOS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP6 | Fixed |
| SUSE Linux Enterprise Module for Containers 15 SP3 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP3 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP4 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Fixed |
| SUSE Linux Enterprise Server 15 SP3 | Fixed |
| SUSE Linux Enterprise Server 15 SP3-BCL | Fixed |
| SUSE Linux Enterprise Server 15 SP3-LTSS | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP3 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP4 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP5 | Fixed |
| SUSE Manager Proxy 4.2 | Fixed |
| SUSE Manager Retail Branch Server 4.2 | Fixed |
| SUSE Manager Server 4.2 | Fixed |
| openSUSE Leap 15.3 | Fixed |
| openSUSE Leap 15.4 | Fixed |
| openSUSE Leap 15.5 | Fixed |
| openSUSE Leap Micro 5.5 | Fixed |
| suse/helm | Fixed |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-19446
GHSA-f2g3-hh2r-cwgc