Use this finding-to-fix worksheet

Write closure criteria beside each finding before the engineer changes code. For an ownership flaw, denial must hold across the original object and another object in the same class. For a payment flaw, no provider call or ledger mutation may follow a rejected request.

Finding-to-fix worksheet
ItemCheck or ownerEvidence
Original findingTesterAffected route, role, and exact precondition
Fix claimEngineerChange ID and affected versions
RetestTesterSame abuse path plus nearby variants
ClosureRisk ownerDecision, date, and remaining risk

Test and retest

Use the same role and precondition as the original report. Capture the deployed build ID and run the attack on that build. If the first path fails but a sibling endpoint still accepts it, record partial remediation and keep the finding open. Do not replace the original proof with a green CI badge.

Evidence to keep

Write a separate result for a fix that changes the failure mode. If the original exploit now returns 403 but exposes whether an account exists, the main finding may be fixed while a smaller information leak remains. Keep it as a new finding or a stated residual issue. Do not force every result into pass/fail for the original ticket. The reviewer needs the exact request, data state, test role, build hash, and time. That record lets the team repeat the check after a later refactor.

Retest the rule at three points

Synthetic finding: a customer could change an invoice ID in a refund request and refund another customer’s payment. The original proof used invoice A and invoice B. Keep those same seeded records for the retest. First, send the old attack to the fixed route. Expect a denial and zero provider refund calls. Second, send a valid refund for invoice A. Expect one provider request; if the provider reports pending, expect one reserved refund and no final refund journal yet. After verified success, expect one final refund effect. Third, try the sibling mobile route and the batch refund path with invoice B. Expect the same denial.

Record the build ID, user IDs, invoice owners, HTTP responses, provider sandbox event IDs, and resulting balances. A 403 response is not a pass if a queued refund still runs. If the first test fails, reopen the finding. If only the sibling route fails, keep the finding open and extend the fix to the shared authorization layer. This is the role-and-data matrix described by OWASP’s authorization testing guidance.

Set closure states before testing

Use four closure states with fixed meanings. Fixed means the original case and agreed nearby paths fail safely on the target build while the valid user still completes the task. Partial means at least one affected path still works. Blocked means a needed account, provider, or release is unavailable. Regression means a previously fixed path now works again. A risk acceptance is a separate dated decision; it does not turn a failed retest into fixed.

For a refund finding, define “no forbidden effect” as no refund intent, provider request, or financial journal for the denied case. Security logging of that denial is expected. For the allowed case, distinguish request accepted, refund pending, and refund succeeded. One provider request can be correct before any final refund journal exists. Observe the worker through its configured retry window or force each queued attempt in the sandbox.

Save the finding ID, original setup, each path checked, current build for API and worker, expected result, observed effect, tester, and date. List exclusions beside the closure decision. This gives the risk owner enough evidence to accept closure without treating an HTTP status as financial proof.

Primary source