Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff changes a workflow with states, money, credits, quotas, approvals, invites, coupons, counters or expiry - skipped or replayed steps, check-then-act races with real impact, negative or overflowing quantities, partial-failure rollback, fail-open defaults, and legitimate features (export, import, search, preview, invite) used against their own rules
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Logic flaws have no dangerous-looking line: no exec, no string-built query, nothing a scanner matches. Every request in the attack is valid on its own; the vulnerability is the sequence, the timing or the number. They are also where the money is — free credits, double refunds, skipped approvals, a role nobody granted.
Core principle: name the invariant the workflow promises ("an order ships only after it is paid", "a coupon is redeemed once", "an invite cannot grant more than the inviter has"), then look for a sequence of individually valid requests that breaks it.
// ❌ the transition never checks the current state: ship an unpaid order, refund a refunded one
func (s *Service) Ship(ctx context.Context, id string) error {
return s.repo.SetStatus(ctx, id, StatusShipped)
}
// ✅ the precondition is part of the write; zero rows means the transition is not allowed
res, err := s.db.ExecContext(ctx,
`UPDATE orders SET status = 'shipped' WHERE id = $1 AND org_id = $2 AND status = 'paid'`, id, orgID)
if n, _ := res.RowsAffected(); n == 0 { return ErrInvalidTransition }
Look for: a status taken from the request body; a step endpoint that does not check the previous step completed (verify-email, MFA, payment, approval, KYC); a completed flow that can be replayed (redeem, claim, confirm, accept-invite); a "cancel" that leaves the side effect (credits granted, access given) in place.
Not a "theoretical race": here the attacker sends both requests. A finding when the window is one read-then-write in a handler and the impact is money, quota, a unique claim or a privilege.
// ❌ two parallel requests both read balance=100 and both withdraw 100
const acct = await db.account.findUnique({ where: { id } });
if (acct.balance < amount) throw new Error("insufficient");
await db.account.update({ where: { id }, data: { balance: acct.balance - amount } });
// ✅ one atomic conditional write
const n = await db.$executeRaw`UPDATE account SET balance = balance - ${amount}
WHERE id = ${id} AND balance >= ${amount}`;
if (n === 0) throw new Error("insufficient");
Fixes that work: a conditional UPDATE … WHERE, SELECT … FOR UPDATE inside a transaction, a unique constraint (one redemption row per coupon and user), an idempotency key stored with the result. Fixes that do not: an in-process mutex in a horizontally scaled service, a check in the client, "the UI disables the button".
quantity: -5 turns a purchase into a refund; a negative transfer moves money the other way; a negative duration extends a trial.limit=0 meaning "unlimited".price * qty in 32-bit ints; a total stored in a narrower column than it is computed in; JavaScript numbers above 2^53."1e9", " 5 ", "0x10", true reaching a numeric field through a loose parser.Step 1 commits and step 2 fails: credits granted but the charge declined, a seat allocated but the invite email errored and the retry allocates another, a file stored but the scan that should gate it timed out and the record says clean. Look for multi-step side effects outside one transaction, an external call between two writes, and a catch that logs and continues past a security-relevant step. Compensation must run with the same authorization as the original action.
< where <= is meant at a boundary that matters (a token valid one extra window).What does the code do when the config key is missing, the feature flag is off, the policy service times out, or the record predates the migration?
# ❌ a missing plan means "no limits"
limit = PLAN_LIMITS.get(org.plan)
if limit is not None and usage >= limit: raise QuotaExceeded()
# ✅ unknown plans get the most restrictive limit
limit = PLAN_LIMITS.get(org.plan, PLAN_LIMITS["free"])
Fail-open authorization is access-control-and-idor §5; here the same question applies to entitlements, quotas, approval requirements and review gates.
?filter=salary>100000), sorting by a hidden field and watching the order, a count that reveals existence.Individually harmless outputs can be the prerequisite of a later trust decision: a self-service rename that produces a name another component treats as an admin group, an "unverified" email that a later SSO link trusts, a draft visible to its author that a preview token then exposes to everyone. Write each step's output and the later decision that relies on it; report only when every link is shown in source.
Unpaid goods, free credits, double refunds or a role nobody granted → HIGH; CRITICAL when unauthenticated or unbounded. Bypass of a paid entitlement or quota → MEDIUM to HIGH by value. An oracle that reveals a protected value or record → MEDIUM. A user doing something the product allows them to do → not a finding.
find then update of a balance, counter or stock level with no lock, condition or constraint.default: branch, ?? true, getOrDefault(…, true) or if err != nil { return nil } on an entitlement or approval check.catch that continues past it.OWASP Top 10:2025 A06 Insecure Design · OWASP API Security Top 10 2023 API6 Unrestricted Access to Sensitive Business Flows · CWE-20, 190, 362, 367, 681, 841 · Cloudflare security-audit-skill
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。