Skip to content

fix: use conditional Blobs writes for NPS relay rate, nonce and install records - #152

Merged
hivecommons-hive[bot] merged 1 commit into
mainfrom
sec/nps-relay-conditional-writes
Oct 1, 2026
Merged

hivecommons-hive[bot] merged 1 commit into
mainfrom
sec/nps-relay-conditional-writes

Conversation

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Security Fix

The NPS relay (netlify/nps-relay/relay.ts) enforced its per-IP / per-install submission limits, per-IP / per-day registration caps, the nonce replay guard and the "one install id, one key" rule with plain read → check → setJSON sequences on Netlify Blobs. Concurrent function invocations all observe the same pre-write record, so every one of those bounds held only for sequential callers.

This PR:

  • bumps @netlify/blobs ^8.2.0 → ^10.7.13 (conditional writes landed in 10.0.0 and reach setJSON in 10.7.12; the Node floor is unchanged, unlike 11.x). The relay only uses get/setJSON/delete/list, which the 9.0.0/10.0.0 breaking changes do not touch.
  • extends RelayStore with getWithMetadata (ETag) and conditional setJSON (onlyIfMatch / onlyIfNew), and routes every bounded record through a compareAndSwap loop (CAS_MAX_ATTEMPTS = 4) that re-reads on a lost race and fails closed (429) under persistent contention.
  • writes install records create-only (onlyIfNew), so two registrations racing for the same install id resolve to exactly one bound key; the loser gets the same 200/409 answers as today.
  • keeps the existing response ordering (429 pre-checks before 400 body validation) so no current test or client behaviour changes.
  • teaches the test MemoryStore ETags and conditional writes (and makes each call yield, so concurrent handlers interleave) and adds six concurrency tests covering each cap, the replayed-nonce race, the install-id race and the fail-closed path.

Validation: vitest run — 78 files / 750 tests pass (relay: 37); tsc --noEmit clean.

Closes #151


Filed by sec-check agent (ACMM L6 — full mode)

— hive: agent=sec-check backend=copilot model=claude-fable-5.1 copilot=1.0.88

…ll records

Bump @netlify/blobs to ^10.7.13 (conditional writes landed in 10.0.0 and
reach setJSON in 10.7.12) and update every bounded record in the relay —
per-IP and per-install submission limits, per-IP and per-day registration
caps, and the per-install nonce list — through a compare-and-swap loop
guarded by the record's ETag. Install records are written create-only so
an install id is bound to exactly one key even when registrations race.
Persistent contention fails closed with 429.

Adds MemoryStore ETag/conditional-write emulation and concurrency tests
that fire bursts of requests and assert each cap holds.

Closes #151

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sec-check <sec-check@hive.kubestellar.io>
Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com>
@kubestellar-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@netlify

netlify Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for hivecommons-docs ready!

Name Link
🔨 Latest commit 837a91a
🔍 Latest deploy log https://app.netlify.com/projects/hivecommons-docs/deploys/6abe884b2ab3700008c0a527
😎 Deploy Preview https://deploy-preview-152--hivecommons-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@hivecommons-hive
hivecommons-hive Bot merged commit bd177dd into main Oct 1, 2026
9 of 10 checks passed
@kubestellar-prow
kubestellar-prow Bot deleted the sec/nps-relay-conditional-writes branch October 1, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sec-check] NPS relay rate limits, nonce guard and key binding are non-atomic read-modify-write on Blobs — bypassable by concurrent requests

0 participants