Add rate limiting to auth endpoints (CRU-38) - #217
Merged
Conversation
Protect login (5 req/min) and setup (3 req/min) endpoints against brute-force attacks using @fastify/rate-limit with per-route config. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests verify login (5/min), setup (3/min) limits and that the status endpoint remains unrestricted. Each test group uses a fresh Fastify instance to isolate rate limit counters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
niiyeboah added a commit
that referenced
this pull request
Jun 10, 2026
Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's (possibly recycled) PID is never SIGTERM'd on the next paste. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selfcontained pushed a commit
that referenced
this pull request
Jun 12, 2026
Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's (possibly recycled) PID is never SIGTERM'd on the next paste. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
selfcontained added a commit
that referenced
this pull request
Jun 12, 2026
* Add drag-and-drop / paste file upload to the terminal Drop files onto the agent terminal → upload to the media store, insert `[File #N] <path>` (per-agent index, increments across drops). Drag-and-drop is always path-based (works on headless VMs). Image paste (Cmd/Ctrl+V) is hybrid: when the host can place the image on a clipboard the agent CLI can read (macOS pasteboard, or Linux+Xvfb), it injects natively (host clipboard + Ctrl+V → inline [Image #N]); otherwise it falls back to the path-based upload. Capability is reported by GET /api/v1/system/defaults (`clipboardImagePaste`); the agent env exports DISPLAY=$DISPATCH_COPY_DISPLAY so the CLI can read the Xvfb clipboard. Shiny status-gradient drop overlay + shared-ActivityBars uploading pill (role=status). Hardened the /api/v1/clipboard/image endpoint (stdin EPIPE guard). Incorporates frontend-ux / infra / architecture review fixes. Tests: command builder (DISPLAY), system defaults (capability), e2e (drag→media, paste native when capable, paste fallback when not). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Address arch + infra review on terminal file upload Architecture review: - Extract hostClipboardImageCapable() so /system/defaults and /clipboard/image share one predicate (no drift; Linux branch now gated on it instead of an open-ended else). - Fix misleading /clipboard/image header + 150ms comments: the paste hybrid DOES call this route; drop the "remove this route" guidance. - pasteImage: single owner for the uploadingFiles flag per phase (clear before delegating to the path-based fallback). - Source clipboardImagePaste via a shared useSystemDefaults React Query hook; migrate create-agent-dialog off its duplicate raw fetch. - Soften the [File #N] counter comment (per-mount, cosmetic label). Infra review: - Replace the 150ms heuristic with a deterministic readiness poll (xclip owns the selection + advertises the target) and reject on timeout so the client can fall back — closes the silent, previously non-recoverable paste-failure race. - Track and SIGTERM the previous resident xclip before spawning a new one; document the orphan-on-restart behavior. - Rate-limit (30/min) and size-cap (8MB) /clipboard/image. - macOS temp file now written into a private mkdtemp dir (no predictable /tmp clobber); cleaned via rm. - Document the shared-Xvfb / cross-agent clipboard limitation on the DISPLAY export. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Close PID-reuse TOCTOU in xclip reaper (review #217) Clear lastXclipPid in the proc 'exit' handler so a self-exited xclip's (possibly recycled) PID is never SIGTERM'd on the next paste. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Apply prettier formatting to system.ts (fix CI) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: add extensionForMime helper for clipboard paste naming Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add per-agent file sequence counter for terminal injection Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add inject mode to media upload — server-side clipboard + tmux injection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: unify client upload — both paste and drop use single uploadFiles callback Remove the dual uploadAndInsertFiles/pasteImage callbacks and their supporting refs (fileSeqRef, clipboardCapableRef, useSystemDefaults) from use-terminal.ts. Replace with a single uploadFiles callback that delegates delivery entirely to the server via the inject flag. The client no longer types paths into the terminal, tracks file numbering, or manages clipboard routing — the server handles all of it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove dead /clipboard/image endpoint and update E2E tests Clipboard-write logic moved to shared/lib/clipboard-write.ts (used by the media inject flow). The client no longer routes to a separate clipboard endpoint — all uploads go through the unified media endpoint. E2E tests updated to match: the two clipboard-endpoint tests are replaced by a single "pastes images via the media endpoint" test. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: file upload path injection should not auto-submit the prompt Use pasteText() (bracketed paste, no Enter) instead of sendCommand() for [File #N] injection. This matches the clipboard path behavior — both now paste without submitting, letting the user add context or review before sending. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: verify media entries created after drag-drop and paste uploads Each upload E2E test now checks the media list API to confirm the DB entry exists with correct name, source, and size — not just that the request was sent. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: replace artificial upload delay with console-log overlay detection Extract UploadingOverlay into its own component that logs on mount. The E2E test listens for that console message instead of injecting an 800ms route delay. Also wait for the upload response (not just the request) so the DB write has committed before asserting on media entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove unused clipboardImagePaste from system defaults The server-side inject flow calls hostClipboardImageCapable() directly — the client no longer needs the capability flag. Drop it from the API response, client type, and unit test. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Brad Harris <bmharris@gmail.com>
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 freeto 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
@fastify/rate-limit(v9, Fastify 4-compatible) withglobal: false— no default limits on any routePOST /api/v1/auth/loginto 5 requests/minute per IPPOST /api/v1/auth/setupto 3 requests/minute per IPTest plan
pnpm run check— TypeScript passespnpm run test— 96 unit tests passpnpm run test:e2e— 79 E2E tests pass (6 pre-existing skips)Closes CRU-38