Add external API abuse controls#16
Open
metajinglun wants to merge 4 commits into
Open
Conversation
Constraint: Emergency controls must be env-and-restart only with no runtime admin surface. Rejected: Runtime mutation endpoint | Adds a new mutating attack surface for a public API. Confidence: high Scope-risk: moderate Directive: Keep trusted-key traffic preserved unless product explicitly chooses a trusted-traffic kill switch. Tested: bun test; bun run build; git diff --check Not-tested: LSP diagnostics unavailable because TypeScript LSP is not installed.
Constraint: Additional-token recipients may be program-derived addresses. Rejected: Dropping tokenAccountAddress on derivation failure | Hides a valid off-curve recipient path. Confidence: high Scope-risk: narrow Directive: Keep additional-token ATA derivation aligned with other off-curve vault derivations. Tested: bun test; bun run build; git diff --check
|
Package Protection
Repository GuardExact dependency versions
Package minimum age
Sensitive wallet / program changes
Overall status: pass Transitive supply-chain threats are covered by the Socket scanner (via |
- rateLimit: check both per-IP and global ceilings before charging either, so a request rejected by one limit never consumes the other's quota (check-then- charge via describeBucket; adds a regression test). - clientContext: parse exemptCidrs once at app creation via a factory instead of re-parsing on every request. - clientContext: iterate all trusted keys without early-exit so the constant-time comparison doesn't leak the matching key's position. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cloudflare handles normal per-IP edge throttling, so this keeps the app layer focused on trusted identity, aggregate anonymous pressure, and emergency backend protection. Constraint: Public API controls should avoid extra operational bypasses or duplicate modes unless they materially protect downstream systems. Rejected: Origin allowlist, CIDR bypass, and lockdown mode | They duplicated edge policy or behaved the same as restricted while adding public surface area. Confidence: high Scope-risk: narrow Directive: Keep future app-layer controls focused on behavior Cloudflare cannot express safely: trusted identity, aggregate anonymous ceilings, and endpoint restriction. Tested: git diff --check; bun test tests/restriction.test.ts tests/rateLimit.test.ts tests/config.test.ts; bun run build; bun test; restricted-mode HTTP smoke Not-tested: LSP diagnostics unavailable because TypeScript LSP is not installed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Verification
git diff --checkbun test tests/restriction.test.ts tests/rateLimit.test.ts tests/config.test.tsbun run buildbun test/api/tickers-> 503SERVICE_RESTRICTED, trusted/api/tickers-> 200,/health-> 200Notes
GLOBAL_RATE_LIMIT_MAXremains off by default and can be enabled when aggregate anonymous origin pressure matters.Greptile Summary
This PR adds an abuse-control layer to the external API: anonymous and global rate limits (env-driven), a request-context middleware that validates API keys with timing-safe comparison, an emergency restriction mode that sheds anonymous traffic while preserving trusted and health access, and Prometheus metrics for restriction events. It also fixes
getAssociatedTokenAddressto passallowOwnerOffCurve=truefor PDA recipients in the launchpad service.src/middleware/rateLimit.tswith a check-then-charge design that prevents per-IP quota from being consumed by global-ceiling rejections; rate-limit headers (X-RateLimit-*,Retry-After) are now included on all responses.src/middleware/restriction.ts) gates onRESTRICTION_MODEandRESTRICTION_DISABLED_PATHS, always exempting/health,/api/health, and/metrics; controls are env + restart only with no runtime admin endpoint.allowOwnerOffCurve=trueargument togetAssociatedTokenAddressand covers the regression with a new test.Confidence Score: 5/5
Safe to merge; the new middleware layer is well-structured, tested, and the single finding is a minor path-matching edge case in an internal guard.
All three middleware pieces (client context, rate limiting, restriction) are logically correct and covered by tests. The rate limiter correctly implements check-before-charge to avoid phantom quota consumption. The timing-safe key comparison iterates all keys without early exit. The launchpad fix is small, targeted, and regression-tested. The only gap is that alwaysAllowedPaths uses prefix matching where exact matching was intended, but no current route collides with those prefixes, so it has no impact today.
src/middleware/restriction.ts — the alwaysAllowedPaths exact-vs-prefix matching issue is worth fixing before new routes are added near /health or /metrics.
Important Files Changed
alwaysAllowedPathsuses prefix matching instead of exact matching, which could silently exempt unintended paths.allowOwnerOffCurve=truetogetAssociatedTokenAddressso PDA recipients no longer throw during token account derivation.timingSafeEqual, ensuring constant-time string comparison regardless of string length differences.Reviews (3): Last reviewed commit: "Trim duplicate edge controls from API sa..." | Re-trigger Greptile