Skip to content

fix(test): de-flake XC1-PF-01 look-alike recipient (checksum-case nibble flip) - #1518

Merged
DealAppSeo merged 1 commit into
mainfrom
claude/2026-11-05-xc1pf-flake
Nov 6, 2026
Merged

DealAppSeo merged 1 commit into
mainfrom
claude/2026-11-05-xc1pf-flake

Conversation

@DealAppSeo

Copy link
Copy Markdown
Owner

What

tests/xc1-l1-regrade-2.test.ts [XC1-PF-01] intermittently fails with Received array: [] where it expects recipient_substitution. Not a product bug — a bug in the test's own look-alike generator.

Root cause

The one-nibble-different recipient is built as:

`${seller.address.slice(0, 41)}${seller.address[41] === 'f' ? '0' : 'f'}`

ethers returns an EIP-55 checksummed (mixed-case) address. When the seller's last nibble is a checksum-uppercased 'F', 'F' === 'f' is false, so the flip appends 'f' — a case-only change. evaluateNpa compares addresses case-insensitively (asserted by the XC1-PF-00 control), so it reads the look-alike as the same address, returns no refusal ([]), and the probe fails.

Rate ≈ P(last nibble = f) × P(checksum uppercases it) ≈ 1/32, so it reddens the test job on unrelated PRs at random (observed on #1517, not on #1516).

Fix

Compare the last char case-insensitively so the flip is always value-distinct:

seller.address[41].toLowerCase() === 'f' ? '0' : 'f'

Proven over every last-nibble case: 'F' now maps to a genuinely different nibble; all other cases unchanged. Test-only — no src/ or behavior change.

🤖 Generated with Claude Code

…nibble flip)

tests/xc1-l1-regrade-2.test.ts built its one-nibble-different recipient with
`seller.address[41] === 'f' ? '0' : 'f'`. ethers returns an EIP-55 checksummed
(mixed-case) address, so when the seller's last nibble is a checksum-uppercased
'F', `'F' === 'f'` is false and the flip appends 'f' — a CASE-only change that
evaluateNpa (which compares addresses case-insensitively, asserted by XC1-PF-00)
reads as the SAME address. The probe then sees no refusal (`[]`) and fails,
~1/32 runs (P(last nibble = f) x P(checksum uppercases it)). This intermittently
reddens the `test` job on unrelated PRs (seen on #1517, not #1516).

Fix: compare the last char case-insensitively so the flip is always
value-distinct. Proven over all last-nibble cases: uppercase 'F' now maps to a
genuinely different nibble; every other case is unchanged. Test-only; no src/
or behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@strix-security

strix-security Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Strix Security Review

✅ No open security findings.

PR summary: Fixes an intermittent failure in the XC1-PF-01 NPA preflight test by making its generated look-alike recipient address genuinely value-distinct: the last nibble is now compared case-insensitively before being flipped, so an uppercase checksummed 'F' no longer yields a case-only change that the evaluator treats as the same address.

Review summary

This PR contains a single test-only change: in tests/xc1-l1-regrade-2.test.ts the XC1-PF-01 look-alike recipient generator now compares the address's last character case-insensitively (toLowerCase() === 'f'), so the synthetic "one nibble changed" recipient is always value-distinct instead of sometimes being only a case change on an EIP-55 checksummed address. I reviewed the full hunk and its surrounding test context. The change tightens the adversarial assertion rather than relaxing it, removes no security control, and touches no production code, configuration, or dependency, so there is nothing attacker-exploitable introduced here.

Review 1 on this PR · 41279f4 · requested Nov 5 05:22 UTC when the PR was opened


Reviewed by Strix
Re-run review · Configure security review settings

@strix-security strix-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR contains a single test-only change: in tests/xc1-l1-regrade-2.test.ts the XC1-PF-01 look-alike recipient generator now compares the address's last character case-insensitively (toLowerCase() === 'f'), so the synthetic "one nibble changed" recipient is always value-distinct instead of sometimes being only a case change on an EIP-55 checksummed address. I reviewed the full hunk and its surrounding test context. The change tightens the adversarial assertion rather than relaxing it, removes no security control, and touches no production code, configuration, or dependency, so there is nothing attacker-exploitable introduced here.


Reviewed by Strix
Configure security review settings

@DealAppSeo
DealAppSeo merged commit e4200b2 into main Nov 6, 2026
18 checks passed
@DealAppSeo
DealAppSeo deleted the claude/2026-11-05-xc1pf-flake branch November 6, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant