Repository navigation
fix(security): device consent phishing guard and 2FA disable throttle - #693
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #693 +/- ##
==========================================
- Coverage 89.73% 89.70% -0.04%
==========================================
Files 1292 1292
Lines 131726 131787 +61
==========================================
+ Hits 118199 118213 +14
- Misses 13518 13565 +47
Partials 9 9
🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…roval Device-code phishing guard (spec 2026-10-27-01, RFC 8628 §5.4): - device_auth_requests stores requester_ip (trusted-proxy resolution, the rate limiter's rules, now shared as base.ExtractTrustedClientIP) and requester_user_agent (migration 031). - GET /auth/device/consent returns requestedAt, requesterIp, requesterUserAgent (short summary) and approverIp. - An approval enqueues device-token-created.html to the approver, naming the client, org, requester IP and the tokens page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The authorize card now shows when, from which IP and with which client the request was opened, the approver's own IP with a different-network hint, a destructive warning above Approve, labels the client name as self-reported, and requires an "I started this sign-in myself" tick when the code arrived pre-filled from the URL (spec 2026-10-27-01). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…one can mint and send by link, with no warning Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Disable2FA checked the TOTP code with no attempt counter, so a stolen session or PAT could guess its way to removing the second factor. It now shares the per-user login budget (5 attempts per 15 minutes) and answers 429 RATE_LIMITED once it is spent, even for a valid code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The disable dialog now shows the translated "too many attempts" message on a 429. disable2FA also stops treating its 401 INVALID_2FA_CODE as an expired session: the refresh-and-retry spent two attempts of the 2FA budget per click and could sign the user out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… with no attempt budget Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Oct 27, 2026
fclairamb
added a commit
that referenced
this pull request
Oct 29, 2026
…eport screenshots (#708) Fixes the findings of the daily security scans. Each spec is the tracker for its finding. ## Fixed by this PR - **Y1 (low)**: `specs/done/2026/10/2026-10-29-01-bug-report-upload-instance-budget.md`. Anonymous bug-report screenshots are capped at 100 MB per org, but the caller picks the org, so the instance-wide total is 100 MB times the number of orgs. Screenshots are also stored past the issue-dispatch cap and never deleted. The fix adds an instance-wide budget for anonymous screenshots, reserves the dispatch slot before storing, makes the quota atomic and adds a retention. ## Earlier scan specs (implemented, in `specs/done/2026/10/`) - **X1 (high)**: `2026-10-28-01-pat-cannot-mint-sessions-or-sign-in-factors.md`. A PAT could open sessions in its owner's other orgs and add sign-in factors. Fixed in #699. - **X2 (medium)**: `2026-10-28-02-status-subscribe-throttle-and-keep-confirmed.md`. Unthrottled subscribe confirm emails, and re-subscribing un-confirmed a subscriber. Fixed in #699. - **X3 (medium on SaaS)**: `2026-10-28-03-invite-lookup-without-org-scan.md`. Invite lookup scanned every org. Fixed in #699. - **X4 (low)**: `2026-10-28-04-snmp-community-secret-field.md`. The SNMP community was not a secret field. Fixed in #699. - **V1 (medium)**: `2026-10-27-01-device-consent-phishing-guard.md`. Device-flow consent phishing. Fixed in #693. - **W1 (low)**: `2026-10-27-02-disable-2fa-attempt-throttle.md`. `DELETE /auth/2fa` had no attempt budget. Fixed in #693. - **U1 (low)**: `2026-10-26-02-ai-repair-hold-skips-param-only-secrets.md`. The `repair: auto` hold applied only when the check's `secrets` map had a value. Fixed in #683. - **S1 (medium)**: `2026-10-25-01-ai-repair-grant-dropped-by-reference-resolution.md`. The repair grant was compared after `${…}` references were resolved. Fixed in #678; U1 closed the remaining gap. - **R1 (medium)**: `2026-10-24-01-ai-repair-auto-apply-partial-runtime-host.md`. `repair: auto` applied a candidate that kept a literal host and added one built at runtime. Fixed in #663. - **Q1 (medium)**: `2026-10-23-02-ai-loop-secret-relay-through-model.md`. AI loops relayed an encoded secret through the model. - **P1 (medium)**: `2026-10-22-01-ai-script-secret-host-guard-runtime.md`. AI runs with real secrets were only host-checked by regex. - **K1 (medium)**: `2026-10-20-01-sender-response-body-caps.md`. Notification senders and RabbitMQ read responses uncapped. - **J1 (medium)**: `2026-10-19-01-a2a-response-size-cap.md`. A2A responses were read uncapped. - **I1 (low)**: `2026-10-18-01-plugin-schema-file-ref.md`. Plugin schema `$ref` could load local files. - **G1/G2 (low)**: `2026-10-17-01-postgres-check-connection-config.md`. Postgres conninfo escaping and fallback to the worker's `PG*` env. - **F1**: `2026-10-16-15-pat-cache-revocation.md`. The PAT cache outlived revocation. - **E1**: `2026-10-16-14-totp-on-federated-sign-in.md`. No TOTP on federated sign-in. - **E2**: `2026-10-16-13-atomic-auth-attempt-counters.md`. Auth attempt counters were not atomic. - **H3**: `2026-10-16-12-mcp-tokens-rejected-on-rest.md`. MCP OAuth tokens worked on REST. - **H2**: `2026-10-16-11-slack-signature-fail-closed.md`. Slack signature check failed open. - **T1 / M2 (high)**: `2026-10-16-10-discovery-scans-egress-guard.md`. Discovery scans were outside the egress policy. - **N4**: `2026-10-16-09-js-check-nested-docker-guard.md`. A JS `docker` sub-check bypassed the gate. - **N3 (high)**: `2026-10-16-08-status-page-components-cross-org.md`. Status-page components could be edited across orgs. - **D2/D3 (high)**: `2026-10-16-07-guard-status-subscriber-and-publication-webhooks.md`. Subscriber and publication webhooks were not guarded. - **C3**: `2026-10-16-06-accept-invite-existing-account.md`. Accepting an invite logged in as an existing account. - **C1**: `2026-10-16-05-kubeconfig-exec-and-incluster.md`. Kubeconfig `exec` and `inCluster` were allowed. - **N2**: `2026-10-16-04-mysql-dsn-injection.md`. MySQL DSN injection. - **N1**: `2026-10-16-03-env-secret-reference-allowlist.md`. No allowlist for `${env:}` references. - **C2/H1**: `2026-10-16-02-token-purpose-separation.md`. Purpose tokens were accepted as access tokens. - **D1**: `2026-10-16-01-microsoft-signin-unverified-email-linking.md`. Microsoft nOAuth email linking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.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 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.
Specs filed from the daily security scans. Each spec is the tracker for its finding. This PR adds the specs and implements them.
What changed
031_v0_43_0stores the requester IP and user agent.DELETE /auth/2faspends the shared per-user 2FA budget (5 per 15 minutes) before comparing the code, answers 429RATE_LIMITED, and resets on success. The dash0 dialog shows the message, and no longer refreshes and retries on a wrong code.Decided by autopilot
Specs (now implemented, archived in
specs/done/2026/10/)specs/done/2026/10/2026-10-27-01-device-consent-phishing-guard.md. The device-flow consent page approves a code anyone can mint without an account and send by link, already filled in. It shows no warning to approve only a sign-in you started yourself, and no detail about who opened the request. One click from a signed-in member gives the requester a 90-day PAT with the member's role. The fix adds the requester's details, a warning and an email notification, and keeps the CLI flow one click.specs/done/2026/10/2026-10-27-02-disable-2fa-attempt-throttle.md.DELETE /auth/2fachecks the TOTP code without the per-user attempt budget that login 2FA uses. Someone holding a stolen session or PAT can guess the code at the global request rate and remove the second factor for good. The fix spends the shared 2FA budget before comparing.Earlier scan specs (implemented, in
specs/done/2026/10/)2026-10-26-02-ai-repair-hold-skips-param-only-secrets.md. Therepair: autohold applied only when the check'ssecretsmap had a value. Fixed in fix(ai): hold every scheduled repair-auto run to its granted hosts #683.2026-10-25-01-ai-repair-grant-dropped-by-reference-resolution.md. The repair grant was compared after${…}references were resolved. Fixed in fix(ai): hold the repair: auto host grant when the script or env holds a reference #678; U1 closed the remaining gap.2026-10-24-01-ai-repair-auto-apply-partial-runtime-host.md.repair: autoapplied a candidate that kept a literal host and added one built at runtime. Fixed in feat(ai): hold auto-applied repairs to the previous version's hosts (+ scan specs) #663.2026-10-23-02-ai-loop-secret-relay-through-model.md. AI loops relayed an encoded secret through the model.2026-10-22-01-ai-script-secret-host-guard-runtime.md. AI runs with real secrets were only host-checked by regex.2026-10-20-01-sender-response-body-caps.md. Notification senders and RabbitMQ read responses uncapped.2026-10-19-01-a2a-response-size-cap.md. A2A responses were read uncapped.2026-10-18-01-plugin-schema-file-ref.md. Plugin schema$refcould load local files.2026-10-17-01-postgres-check-connection-config.md. Postgres conninfo escaping and fallback to the worker'sPG*env.2026-10-16-15-pat-cache-revocation.md. The PAT cache outlived revocation.2026-10-16-14-totp-on-federated-sign-in.md. No TOTP on federated sign-in.2026-10-16-13-atomic-auth-attempt-counters.md. Auth attempt counters were not atomic.2026-10-16-12-mcp-tokens-rejected-on-rest.md. MCP OAuth tokens worked on REST.2026-10-16-11-slack-signature-fail-closed.md. Slack signature check failed open.2026-10-16-10-discovery-scans-egress-guard.md. Discovery scans were outside the egress policy.2026-10-16-09-js-check-nested-docker-guard.md. A JSdockersub-check bypassed the gate.2026-10-16-08-status-page-components-cross-org.md. Status-page components could be edited across orgs.2026-10-16-07-guard-status-subscriber-and-publication-webhooks.md. Subscriber and publication webhooks were not guarded.2026-10-16-06-accept-invite-existing-account.md. Accepting an invite logged in as an existing account.2026-10-16-05-kubeconfig-exec-and-incluster.md. KubeconfigexecandinClusterwere allowed.2026-10-16-04-mysql-dsn-injection.md. MySQL DSN injection.2026-10-16-03-env-secret-reference-allowlist.md. No allowlist for${env:}references.2026-10-16-02-token-purpose-separation.md. Purpose tokens were accepted as access tokens.2026-10-16-01-microsoft-signin-unverified-email-linking.md. Microsoft nOAuth email linking.🤖 Generated with Claude Code