Skip to content

Commit 39215e4

Browse files
committed
fix(worker): add rate limiter error handling and invalid purpose test
1 parent 55b70c7 commit 39215e4

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/worker/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,8 +704,18 @@ export default {
704704
const { sessionId, setCookie } = await ensureSession(request, env);
705705

706706
// Step 4: Rate limiting using session ID as key
707-
const { success } = await env.PROXY_RATE_LIMITER.limit({ key: sessionId });
708-
if (!success) {
707+
let rateLimited = false;
708+
try {
709+
const { success } = await env.PROXY_RATE_LIMITER.limit({ key: sessionId });
710+
rateLimited = !success;
711+
} catch (err) {
712+
log("error", "rate_limiter_failed", {
713+
error: err instanceof Error ? err.message : "unknown",
714+
}, request);
715+
// Fail open — rate limiter misconfiguration should not block all proxy requests.
716+
// Turnstile and session binding still protect the seal endpoint.
717+
}
718+
if (rateLimited) {
709719
log("warn", "proxy_rate_limited", { pathname: url.pathname }, request);
710720
const rateLimitResponse = errorResponse("rate_limited", 429);
711721
const headers = new Headers(rateLimitResponse.headers);

tests/worker/seal.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,19 @@ describe("Worker /api/proxy/seal endpoint", () => {
227227
expect(json["error"]).toBe("invalid_request");
228228
});
229229

230+
it("request with invalid purpose (not in VALID_PURPOSES) returns 400", async () => {
231+
globalThis.fetch = vi.fn().mockResolvedValue(
232+
new Response(JSON.stringify({ success: true }), { status: 200 })
233+
);
234+
235+
const req = makeSealRequest({ body: { token: "ghp_test", purpose: "github-pat" } });
236+
const res = await worker.fetch(req, makeEnv());
237+
238+
expect(res.status).toBe(400);
239+
const json = await res.json() as Record<string, unknown>;
240+
expect(json["error"]).toBe("invalid_request");
241+
});
242+
230243
it("request with missing token returns 400 with invalid_request", async () => {
231244
globalThis.fetch = vi.fn().mockResolvedValue(
232245
new Response(JSON.stringify({ success: true }), { status: 200 })

0 commit comments

Comments
 (0)