Skip to content

fix(orb): degrade rate-limit installation-identity resolution on a DB error instead of escaping uncaught#9227

Merged
JSONbored merged 1 commit into
mainfrom
fix/rate-limit-installation-identity-db-error
Jul 27, 2026
Merged

fix(orb): degrade rate-limit installation-identity resolution on a DB error instead of escaping uncaught#9227
JSONbored merged 1 commit into
mainfrom
fix/rate-limit-installation-identity-db-error

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

The global rate-limit middleware (app.use("*", ...)enforceRateLimitrateLimitIdentityinstallationRateLimitIdentity) runs before every route handler, including /v1/orb/token, /v1/orb/relay/register, and /v1/orb/relay/pull. For those three paths it called validateOrbRelayEnrollment(c.env, token) unguarded.

If the DB throws inside that function (a real, if rare, failure mode), the rejection propagated uncaught through the middleware — which has no try/catch around await enforceRateLimit(...) — producing a bare framework 500 upstream of the route handler. This silently defeated the route-level #4995 fix, whose .catch(dbBrokerError) only guards the handler's own, LATER call to the same function.

Verified live by instrumenting the existing #4995 regression tests in test/integration/orb-relay.test.ts — both currently pass on main, but only because their assertions never inspected the actual failure mode. The real response was a bare 500 with the throw originating in installationRateLimitIdentity, not in the route handler:

Error: db unavailable
    at Object.first (test/integration/orb-relay.test.ts:150:58)
    at validateOrbRelayEnrollment (src/orb/relay.ts:224:6)
    at installationRateLimitIdentity (src/auth/rate-limit.ts:240:24)
...
DEBUG STATUS 500 BODY Internal Server Error

Fix: .catch(() => null) around the call, degrading to IP-keyed rate limiting for that one request — exactly the fallback this function's own doc comment already promises ("falling back to IP-keying ... when [identity is] not resolvable -- a malformed payload, an unenrolled secret"), matching the sibling peekWebhookInstallationId branch's existing best-effort pattern. A DB error is just another "not resolvable" case.

Closes #9225

Validation

  • New regression test in test/unit/auth.test.ts (co-located with the existing Move GitHub-webhook rate-limit buckets from IP-keyed to installation-keyed #4891/installation-keying suite): forces the orb_enrollments lookup to reject, asserts all three affected paths resolve to IP-keying rather than rejecting.
  • npx vitest run test/unit/auth.test.ts test/integration/orb-relay.test.ts133/133 pass, including both of orb-relay.test.ts's own pre-existing #4995 regression tests, which now exercise the code path their names actually describe.
  • npm run typecheck — clean.

Safety

  • No secrets, wallets, hotkeys, trust scores, or reward values.
  • No change to any non-error resolution path — a valid/invalid/absent token still resolves identity exactly as before.
  • No change to peekWebhookInstallationId or the /v1/orb/relay single-tenant branch (out of scope, unaffected).

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 27, 2026
@JSONbored
JSONbored merged commit 8c1e839 into main Jul 27, 2026
3 of 4 checks passed
@JSONbored
JSONbored deleted the fix/rate-limit-installation-identity-db-error branch July 27, 2026 08:09
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
22219 2 22217 21
View the top 2 failed test(s) by shortest run time
test/integration/orb-onboarding.test.ts > Central Orb installation registry routes (/v1/internal/orb/installations) > tolerates a list query that omits results (rows.results ?? [])
Stack Traces | 0.0238s run time
SyntaxError: Unexpected token 'I', "Internal S"... is not valid JSON
 ❯ test/integration/orb-onboarding.test.ts:57:14
test/integration/orb-ingest.test.ts > Orb instance registry routes (/v1/internal/orb/instances) > tolerates a list query that omits results (rows.results ?? [])
Stack Traces | 0.0293s run time
SyntaxError: Unexpected token 'I', "Internal S"... is not valid JSON
 ❯ test/integration/orb-ingest.test.ts:427:14

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

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.

orb(rate-limit): a DB error resolving installation identity escapes as a bare 500, upstream of the route's own #4995 fix

1 participant