Skip to content

docs(security): document the bounded decompression path (LAB-2504) - #117

Open
27Bslash6 wants to merge 2 commits into
mainfrom
lab-2504-document-decompression-bound
Open

docs(security): document the bounded decompression path (LAB-2504)#117
27Bslash6 wants to merge 2 commits into
mainfrom
lab-2504-document-decompression-bound

Conversation

@27Bslash6

Copy link
Copy Markdown
Contributor

Docs-only. Part of the LAB-2504 cross-SDK decompression-bomb audit. Depends on cachekit-core#75 — the inline link targets an anchor that PR adds, so merge core first.

Why

SECURITY.md covered reporting and scope but said nothing about the read pipeline, so a reader had no way to tell whether this SDK decompresses anything itself.

Audit outcome for this repo: no bypass, but a misleading ceiling

It does not decompress anything itself. Both bindings — cachekit-core-ts (NAPI, src/lib.rs:118) and cachekit-core-wasm (Workers, src/lib.rs:98) — are one-line pass-throughs to cachekit-core's retrieveextract(), which bounds output at min(512 MiB, 1000 × compressed_len) before decompressing. No SDK-side LZ4, no pre-extract allocation.

The audit did surface a real mismatch, which this PR documents and LAB-2732 tracks for a code fix: serializer.maxDecodedSize defaults to 10 MiB but is only applied inside serializer.decode, i.e. after unpack returns. Core may have materialized up to 512 MiB by then, so the two ceilings differ by ~51×, and cache-core.ts:574 currently claims the blast radius is bounded by maxDecodedSize. Turning that knob down to harden a Workers deployment changes nothing about what unpack may allocate.

What this PR corrects about its own first draft

The panel found the Workers callout said "bound payload size at the caller" without naming a lever, while the only knob the section mentions is precisely the one that does not work — so a reader would reasonably reach for maxDecodedSize and stay exposed. It now names the two levers that exist: check the fetched value's byte length before handing it to the cache, or cap value size at the backend.

Scope

No code. The maxDecodedSize mismatch is LAB-2732; core's constants are LAB-2505.

Closes LAB-2504 for this repo.

SECURITY.md covered reporting and scope but said nothing about the read
pipeline, so a reader had no way to tell whether this SDK decompresses
anything itself. It does not: both bindings (NAPI and the Workers wasm build)
are thin wrappers over cachekit-core's extract(), which bounds output at
min(512 MiB, 1000 x compressed_len) before decompressing, does not trust the
envelope's declared original_size, and does not rely on the unkeyed xxHash3-64
checksum for anything but corruption detection.

Calls out that maxDecodedSize is checked on already-decompressed bytes, so it
is downstream of that bound rather than a substitute for it.

Flags the Workers case specifically: 512 MiB is a server-class ceiling and an
isolate has roughly 128 MiB, so on that build a payload well inside core's
limits can still exhaust it. Sizing belongs to LAB-2505; this records the
constraint so nobody reads the ceiling as tuned for Workers.
Expert-panel findings on the previous commit.

'maxDecodedSize is checked on the already-decompressed bytes' was true but
buried the consequence: the default is 10 MiB and core will materialize up to
512 MiB before it is ever consulted, so the two ceilings differ by ~51x and
turning maxDecodedSize down to harden a Workers deployment does nothing to what
unpack may allocate. cache-core.ts:574 currently claims the blast radius IS
bounded by maxDecodedSize, which is wrong by that same factor; filed as
LAB-2732 and cross-referenced here.

The Workers callout also said 'bound payload size at the caller' without naming
a lever, while the only knob the section mentions is the one that does not
work -- so a reader would reasonably reach for maxDecodedSize and stay exposed.
Now names the two levers that exist: check the fetched byte length before
handing it to the cache, or cap value size at the backend.
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 43 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 96 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 1970d866-d3bb-4a43-806a-5e7f3532cdb8

📥 Commits

Reviewing files that changed from the base of the PR and between 19ad90c and c8aebfb.

📒 Files selected for processing (1)
  • SECURITY.md

Comment @coderabbitai help to get the list of available commands.

@kodus-27b

kodus-27b Bot commented Sep 2, 2026

Copy link
Copy Markdown

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant