Skill Details
Runtime
(claude-5-5-sonnet)
Example user message
[userMessage]: User Story: As a registered user, I want to reset my password using my email address so that I can regain access to my account if I forget my login details. Acceptance Criteria: User enters email, receives a link, clicks link, enters new password twice, password is updated.
Example agent response
### 🔬 Functional Edge-Cases
* **Unregistered or mistyped email:** The email doesn't match any account. The flow must behave identically for registered and unregistered addresses, otherwise it leaks who has an account.
* **Case and whitespace variants:** `User@Mail.com`, ` user@mail.com `, and Unicode look-alikes may or may not map to the same account depending on normalization. Users get locked out, or two accounts collide.
* **Plus-addressing and aliases:** `user+test@mail.com` is a different string but the same mailbox. Decide whether it matches the account.
* **Multiple reset requests:** The user requests 3 links in a row. If all stay valid, an old link leaked from a mailbox is still dangerous. If only the newest works, a user who clicks an older email gets confused.
* **Link used twice:** The user clicks the link, sets a password, then clicks it again (back button, email client prefetch, a second device). A reused token must fail.
* **Link expiry mid-flow:** The token is valid when the page loads but expires while the user types the new password. The submit must be re-validated server-side, and the user's work shouldn't vanish without explanation.
* **Concurrent resets:** Two browser tabs submit new passwords at the same moment. Define a deterministic outcome so the account isn't left in an ambiguous state.
* **Password change while a reset is pending:** The user remembers their password, logs in, and changes it. Outstanding reset tokens should be invalidated.
* **Account state conflicts:** Unverified email, suspended, locked, deleted, or SSO-only accounts (no local password). Each needs a defined behavior rather than a generic failure.
* **Email change during flow:** The user changes the account email after requesting a reset. The token should be bound to the account, and the old email's links should die.
* **Password mismatch and policy edge-cases:** The two fields differ by trailing whitespace, copy-paste adds invisible characters, passwords are very long (bcrypt's 72-byte truncation), contain emoji or multi-byte Unicode, or are identical to the current or previous passwords.
* **Session state after reset:** Existing sessions and refresh tokens on other devices stay alive unless explicitly revoked. Define whether the user is auto-logged-in after the reset.
* **Email client interference:** Security scanners and link previewers (Outlook SafeLinks, Gmail, Slack unfurls) pre-fetch the URL. A GET request that consumes the token breaks legitimate users.
* **Delivery delays and spam folders:** The email arrives 20 minutes late, after the token has expired, or never arrives.
### ⚠️ Error States & UX Handling
* **Email service outage:** The provider (SES, SendGrid) is down or returns an error. Show the same neutral confirmation, queue and retry the send, and alert on-call. Never expose provider errors to the user.
* **Expired or invalid token page:** Show a clear "link expired or already used" message with a one-click option to request a new link. Avoid dead ends or raw 400/500 pages.
* **Network drop on submit:** The password update succeeds on the server but the response is lost. The user retries and sees "invalid token." Make the final state obvious and offer a login link.
* **Database or transaction failure mid-update:** The password is written but the token isn't invalidated (or vice versa). The update and token invalidation must be atomic.
* **Validation feedback:** Show policy requirements before submission, inline errors on mismatch, and a strength indicator. Don't clear both fields on a single error.
* **Rate limit hit:** A legitimate user who clicks "resend" repeatedly gets blocked. Show a cooldown timer instead of a generic error.
* **Browser back/refresh after success:** The form must not resubmit or leave a usable form on screen. Redirect to a confirmation page.
* **Mobile deep links:** The link opens in an in-app browser or the wrong app, losing the token. Test across email clients and devices.
* **Localization and accessibility:** Emails and error messages in the user's language, screen-reader-friendly errors, and a plain-text email fallback for the link.
### 🛡️ Security & Abuse Vectors
* **Account enumeration:** Different messages, response times, or status codes for registered vs. unregistered emails reveal valid accounts. Use identical responses and equalize timing (send asynchronously).
* **Weak or predictable tokens:** Sequential IDs, timestamps, or MD5 of the email are guessable. Use a CSPRNG with at least 128 bits of entropy.
* **Token stored in plaintext:** A database leak hands out working reset links. Store only a hash (SHA-256) of the token.
* **Host header injection:** An attacker sets a malicious `Host` or `X-Forwarded-Host` header so the emailed link points to their domain and the victim's token is captured. Build links from a configured base URL only.
* **Token leakage via Referer:** The reset page loads third-party scripts, images, or analytics, leaking the token in the URL via the Referer header. Use `Referrer-Policy: no-referrer`, exchange the token for a session on first load, and strip it from the URL.
* **Brute force on tokens:** Rate limit and lock out token attempts per IP and per token. Keep tokens long enough that brute force is infeasible.
* **Email bombing:** An attacker floods a victim's inbox by repeatedly submitting their email. Apply per-email and per-IP throttles plus CAPTCHA after a threshold.
* **Reset-link poisoning through email parameter tampering:** Submitting `email=victim@x.com&email=attacker@x.com` or array/JSON variants may send the victim's token to the attacker. Accept exactly one validated email string.
* **Token not bound to account:** The reset endpoint takes `user_id` from the request body, enabling IDOR (reset any user's password with any valid token). Derive the user solely from the token server-side.
* **CSRF on the reset form:** Include anti-CSRF protection on the submission endpoint.
* **Injection via email field:** SQL, LDAP, or header injection (CRLF in the email to add `Bcc:` headers) can hijack the outgoing message. Validate strictly and use parameterized queries and a safe mail library.
* **Account takeover after email compromise:** A reset link is a single factor. For high-risk accounts, consider MFA step-up or a notice to secondary contacts.
* **No post-reset notification:** The owner isn't told their password changed. Send a "your password was changed" email to the address, with a recovery path.
* **Sessions not revoked:** An attacker who already holds a session keeps access after the legitimate owner resets. Invalidate all sessions and API tokens on reset.
* **Password breach reuse:** Users set a known-breached password. Check against a breach corpus (e.g., HIBP k-anonymity).
* **Logging sensitive data:** Tokens and passwords written to application logs, APM traces, or analytics events. Scrub them.
* **Timing attacks on token comparison:** Use constant-time comparison.
* **Open redirect:** A `redirect_to` or `next` parameter on the reset or confirmation page sends users to a phishing site. Allowlist destinations.
### 🛠️ Recommended AC Additions
* The "request reset" endpoint returns the **same message and similar response time** regardless of whether the email exists (e.g., "If an account exists, we've sent a link").
* Reset tokens are **cryptographically random (≥128 bits), stored hashed, single-use, and expire in 15-60 minutes**. Requesting a new link invalidates all earlier ones.
* Tokens are invalidated on use, on password change by other means, and on account email change.
* The emailed link is built from a **server-configured base URL**, never from request headers.
* The reset page uses a **POST for consumption** (the GET only renders the form), so link scanners and prefetchers can't burn the token. Set `Referrer-Policy: no-referrer` and avoid third-party resources on this page.
* Rate limiting: max **3 reset requests per email/hour** and **10 per IP/hour**, with CAPTCHA after repeated attempts; token submission attempts are throttled too.
* Password and token-update happen in a **single atomic transaction**; the user is derived from the token only.
* Password policy enforced server-side (minimum length, max length handled without silent truncation, breached-password check, mismatch validation) with clear inline errors.
* On success: **revoke all existing sessions and refresh tokens**, send a **"password changed" notification email**, and redirect to login (or log in with a fresh session).
* Expired, used, or invalid link shows a friendly page with a **"request a new link" button**.
* Define behavior for unverified, suspended, deleted, and SSO-only accounts, and log all reset events (request, success, failure) **without logging tokens or passwords**.
* Email send failures are retried via a queue, monitored with alerting, and never surfaced to the end user as account-specific errors.
* QA test matrix covers major email clients with link scanning, mobile in-app browsers, double-click and back-button behavior, and two concurrent reset attempts.
By purchasing this skill, you agree to our terms of service
CLAUDE-5-5-SONNET
Supercharge your sprint planning with the Agile User Story Edge-Case Predictor! This essential Claude skill instantly analyzes standard Product Manager user stories and generates a brutal, exhaustive list of edge-cases, error states, and security vulnerabilities. Perfect for developers, QA engineers, and Scrum Masters aiming to prevent scope creep, eliminate bugs, and secure releases before a single line of code is written.
...more
Added 2 weeks ago
