Skip to content

This release includes 2 security fixes for security teams reviewing exposed deployments.

Published 7d Caching
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 2 known CVEs

Topics

cache-manager cache memory-cache multi-layer-cache nodejs redis
+2 more
stampede-prevention typescript

Affected surfaces

auth breaking_upgrade

ReleasePort's take

Moderate signal
editorial:auto 7d

In v4.0.0 public CacheStack reads return undefined for misses and negative‑cache entries, while read‑through fetchers now cache null as a regular value; `getOrThrow()` returns stored nulls and throws only for undefined.

Why it matters: Cache behavior changes affect application logic that distinguishes between null and missing values; developers must update conditional checks to handle undefined misses and null results accordingly.

Summary

AI summary

Public cache reads now return undefined on misses, fetchers default to caching nulls, and write coordination applies finite limits rejecting saturation with CacheWriteSaturationError.

Changes in this release

Security High

Fixed implicit Express/Hono private URL caching to bypass sensitive query parameters unless a custom `keyResolver` is supplied.

Fixed implicit Express/Hono private URL caching to bypass sensitive query parameters unless a custom `keyResolver` is supplied.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

Namespace clearing now invalidates only the delimiter‑bound prefix, preventing sibling namespace eviction.

Namespace clearing now invalidates only the delimiter‑bound prefix, preventing sibling namespace eviction.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

DiskLayer protected reads now reject plaintext legacy payloads when encryption or signing keys are configured; opt‑in via `allowLegacyPlaintext`.

DiskLayer protected reads now reject plaintext legacy payloads when encryption or signing keys are configured; opt‑in via `allowLegacyPlaintext`.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

Generation cleanup now streams old‑generation keys in bounded batches and caps unique‑key discovery at 10,000 entries by default.

Generation cleanup now streams old‑generation keys in bounded batches and caps unique‑key discovery at 10,000 entries by default.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

OpenTelemetry instrumentation now exports `layercache.key_hash` by default; raw `layercache.key` requires `includeRawKeyAttributes: true`.

OpenTelemetry instrumentation now exports `layercache.key_hash` by default; raw `layercache.key` requires `includeRawKeyAttributes: true`.

Source: llm_adapter@2026-07-19

Confidence: high

Security High

CLI invalidation now requires `--force` for wildcard‑only patterns (`*`, `**`, `?*`).

CLI invalidation now requires `--force` for wildcard‑only patterns (`*`, `**`, `?*`).

Source: llm_adapter@2026-07-19

Confidence: high

Security High

Hardened snapshot commits by rejecting symlinked target parents before final rename.

Hardened snapshot commits by rejecting symlinked target parents before final rename.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security High

Hardened docs playground by keeping token‑bearing worker message sender outside user‑code global reach, in addition to sandboxed iframe, Blob Worker, and token checks.

Hardened docs playground by keeping token‑bearing worker message sender outside user‑code global reach, in addition to sandboxed iframe, Blob Worker, and token checks.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Medium

CLI Redis connection errors scrub Redis URLs from nested error messages before printing.

CLI Redis connection errors scrub Redis URLs from nested error messages before printing.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Medium

Prevented plain objects from forging native structured cache-key tags; rotated keys from j: to j2: to avoid reuse of ambiguous entries.

Prevented plain objects from forging native structured cache-key tags; rotated keys from j: to j2: to avoid reuse of ambiguous entries.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Medium

Prevented stale single and bulk writes from repopulating invalidated keys or deleting newer mset() values by sharing a per‑key ordering boundary.

Prevented stale single and bulk writes from repopulating invalidated keys or deleting newer mset() values by sharing a per‑key ordering boundary.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Medium

Replaced reusable per‑key epoch values with monotonic tokens to eliminate ABA windows for stale writes.

Replaced reusable per‑key epoch values with monotonic tokens to eliminate ABA windows for stale writes.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Low

RedisInvalidationBus emits a warning when constructed without signingSecret and a logger is provided.

RedisInvalidationBus emits a warning when constructed without signingSecret and a logger is provided.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Low

Bounded retained write‑ordering state with configurable global, active‑key, and per‑key limits; rejects saturation with CacheWriteSaturationError.

Bounded retained write‑ordering state with configurable global, active‑key, and per‑key limits; rejects saturation with CacheWriteSaturationError.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Security Low

Fixed per‑key fetch rate limiting so a ready key can preempt a later shared drain timer chosen by a throttled key.

Fixed per‑key fetch rate limiting so a ready key can preempt a later shared drain timer chosen by a throttled key.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Breaking High

Public CacheStack reads now return undefined for misses and negative-cache entries instead of null.

Public CacheStack reads now return undefined for misses and negative-cache entries instead of null.

Source: llm_adapter@2026-07-19

Confidence: high

Breaking High

Read-through fetchers now cache null as a regular value by default; `getOrThrow()` returns stored nulls while throwing only for undefined.

Read-through fetchers now cache null as a regular value by default; `getOrThrow()` returns stored nulls while throwing only for undefined.

Source: llm_adapter@2026-07-19

Confidence: high

Breaking High

Automatically derived structured `wrap()` keys now use the `j2:` schema; old `j:` entries become cold misses and expire naturally.

Automatically derived structured `wrap()` keys now use the `j2:` schema; old `j:` entries become cold misses and expire naturally.

Source: llm_adapter@2026-07-19

Confidence: high

Breaking Low

Write coordination applies finite default limits and can reject saturated work with CacheWriteSaturationError.

Write coordination applies finite default limits and can reject saturated work with CacheWriteSaturationError.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Feature Medium

Updated Vite and related development‑only transitive dependencies to resolve the release audit finding.

Updated Vite and related development‑only transitive dependencies to resolve the release audit finding.

Source: llm_adapter@2026-07-19

Confidence: high

Refactor Low

Updated API, migration, serialization, resilience, integration, architecture‑decision, and security documentation for v4 miss/null semantics, finite cleanup/write limits, structured‑key rotation, HTTP credential handling, CLI guard, and playground isolation boundary.

Updated API, migration, serialization, resilience, integration, architecture‑decision, and security documentation for v4 miss/null semantics, finite cleanup/write limits, structured‑key rotation, HTTP credential handling, CLI guard, and playground isolation boundary.

Source: granite4.1:30b@2026-07-19-audit

Confidence: high

Full changelog

Breaking

  • Public CacheStack, namespace, wrap(), getOrSet(), and mget() reads now return undefined for misses and negative-cache entries instead of null, resolving issue #90.
  • Read-through fetchers now cache null as a regular value by default, and getOrThrow() returns stored nulls while throwing only for undefined. Set cacheNullValues: false when null represents absence.
  • Automatically derived structured wrap() keys use the j2: schema, so old j: entries become cold misses and expire naturally.
  • Write coordination and generation cleanup now apply finite default limits and can reject saturated work with CacheWriteSaturationError.

Security

  • Fixed implicit Express/Hono private URL caching so requests containing sensitive query parameters, including OAuth client_secret and client assertions, bypass implicit URL-only caching unless a custom keyResolver is supplied.
  • Fixed namespace clearing so CacheNamespace.clear() invalidates the delimiter-bound namespace prefix (for example tenant:), preventing sibling namespace eviction such as a clearing ab.
  • Fixed DiskLayer protected reads so plaintext legacy payloads are rejected when encryptionKey or signingKey is configured. Added allowLegacyPlaintext as an explicit migration-only opt-in.
  • Fixed generation cleanup to stream old-generation keys into bounded batches and cap its unique-key discovery set at 10,000 entries by default.
  • Changed OpenTelemetry instrumentation to export layercache.key_hash by default. Raw layercache.key attributes now require includeRawKeyAttributes: true.
  • Hardened snapshot commits by rejecting symlinked target parents immediately before the final rename.
  • Hardened CLI invalidation so every wildcard-only pattern such as *, **, and ?* requires --force, matching the default full-cache invalidation guard.
  • Hardened CLI Redis connection errors by scrubbing Redis URLs from nested error messages before printing them.
  • Added a Redis invalidation warning when RedisInvalidationBus is constructed without signingSecret and a logger is provided.
  • Hardened the docs playground by keeping the token-bearing worker message sender outside user-code global reach, in addition to sandboxed iframe, Blob Worker, and token checks.
  • Prevented plain objects from forging native structured cache-key tags and rotated structured argument keys from j: to j2: so previously ambiguous entries are not reused.
  • Prevented stale single and bulk writes from repopulating invalidated keys or deleting newer mset() values by sharing one per-key ordering boundary and checking fences after backend writes.
  • Bounded retained write-ordering state with configurable global, active-key, and per-key limits that reject saturation with CacheWriteSaturationError.
  • Replaced reusable per-key epoch values with monotonic tokens so maintenance pruning cannot create an ABA window for stale writes.
  • Fixed per-key fetch rate limiting so a ready key can preempt a later shared drain timer chosen by a throttled key.

Changed

  • Updated Vite and related development-only transitive dependencies to resolve the release audit finding.
  • Updated the README and benchmarking guide with a fresh reproducible 4.0.0 baseline covering direct, HTTP, payload, slow-Redis, queue-amplification, memory-pressure, invalidation, and distributed single-flight scenarios.
  • Corrected benchmark TTLs to use the documented millisecond units and updated Autocannon plus its Hyperid override so the HTTP benchmark runs on current Node.js with zero npm audit findings.
  • Updated API, migration, serialization, resilience, integration, architecture-decision, and security documentation for v4 miss/null semantics, finite cleanup/write limits, structured-key rotation, HTTP credential handling, CLI guard, and playground isolation boundary.

Tests

  • Added regression coverage for all security fixes and hardening changes, including shared drain-timer preemption, disposal of queued rate-limited work, epoch rollover, empty serialized writes, symlinked snapshot bases, and serializer undefined behavior. The unit suite reports 672 passing tests and 24 skipped tests; the real Redis integration suite adds 25 passing tests.
  • Added docs-web content assertions for the updated security-sensitive documentation.

Breaking Changes

  • Public `CacheStack`, namespace, `wrap()`, `getOrSet()`, and `mget()` now return `undefined` for misses and negative-cache entries instead of `null`.
  • Read‑through fetchers cache `null` as a regular value by default; set `cacheNullValues: false` to revert.
  • Automatically derived structured `wrap()` keys use the `j2:` schema, making old `j:` entries cold misses that expire naturally.
  • Write coordination and generation cleanup apply finite default limits and can reject saturated work with `CacheWriteSaturationError`.

Security Fixes

  • Fixed implicit Express/Hono private URL caching to bypass sensitive query parameters (e.g., OAuth `client_secret`) unless a custom `keyResolver` is supplied.
  • Fixed namespace clearing so `CacheNamespace.clear()` only invalidates the intended delimiter‑bound prefix, preventing sibling namespace eviction.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track flyingsquirrel0419/layercache

Get notified when new releases ship.

Sign up free

About flyingsquirrel0419/layercache

All releases →

Related context

Related tools

Beta — feedback welcome: [email protected]