AntFleet

Anatomy · 5bbcd2d3-0

Allowlist comparisons use normalized lists but compare against unnormalized candidates (can mis-block/allow DMs/groups)

highbug
repo 5149da9d·PR #3·reviewed 2 days ago

The vulnerable code

src/web/inbound/access-control.ts:70-74

Code snippet unavailable.

The reasoning

Opus

Group allowlist comparison uses raw senderE164 against normalized allowlist

mediumbughigh
  • src/web/inbound/access-control.ts:79-92
  • src/web/inbound/access-control.ts:117-119
`normalizedGroupAllowFrom` is built by passing each entry through `normalizeE164`, but the membership check compares against the raw `params.senderE164` without normalizing it. If the configured allowlist contains values like `+1 555-111-2222` (which normalize to e.g. `15551112222`) but the inbound senderE164 already arrives as `15551112222`, this may work coincidentally; but if the formats differ (config with `+`, sender without, or vice versa) the check will reject legitimate senders. The DM path is consistent because it also compares `params.from` (which is the raw form) — but the asymmetry is identical: normalized list vs. raw candidate. The author clearly intended to normalize both sides.

Recommendation

Compare against `normalizeE164(params.senderE164)` (and likewise normalize `candidate` for the DM path) so both sides of the comparison are in the same canonical form.

GPT-5

Allowlist comparisons use normalized lists but compare against unnormalized candidates (can mis-block/allow DMs/groups)

highbughigh
  • src/web/inbound/access-control.ts:70-74
  • src/web/inbound/access-control.ts:142-147
  • src/web/inbound/access-control.ts:75-79
  • src/web/inbound/access-control.ts:106-109
  • src/web/inbound/access-control.ts:58-59
The allowlists are normalized (digits-only) but comparisons use unnormalized candidates (params.from and params.senderE164). Formatting differences (e.g., leading '+', spaces) will cause includes() to fail, incorrectly blocking legitimate senders or allowing mismatches depending on data shape. Similarly, isSamePhone uses raw string equality and may misclassify the same phone due to formatting differences.

Recommendation

Normalize candidates before comparison: - For DMs: const candidate = normalizeE164(params.from); - For groups: const candidateSender = params.senderE164 ? normalizeE164(params.senderE164) : null; - For same-phone checks: compare normalizeE164(params.from) with normalizeE164(params.selfE164 ?? "").

The agreement

Both frontier models flagged this within the same line range. AntFleet's unanimous gate fired — the finding posted on the PR.

Closure

Tweet thread template

tweet 1 of 8199 / 280

Two frontier models reviewed PR #3 on 5149da9d. Both found this bug: high bug: Allowlist comparisons use normalized lists but compare against unnormalized candidates (can mis-block/allow DMs/groups)

tweet 2 of 8125 / 280

The vulnerable code (src/web/inbound/access-control.ts:70-74): (full snippet at https://www.antfleet.dev/anatomy/5bbcd2d3-0)

tweet 3 of 8280 / 280

What Opus saw: "`normalizedGroupAllowFrom` is built by passing each entry through `normalizeE164`, but the membership check compares against the raw `params.senderE164` without normalizing it. If the configured allowlist contains values like `+1 555-111-2222` (which normalize t…

tweet 4 of 8280 / 280

What GPT-5 saw: "The allowlists are normalized (digits-only) but comparisons use unnormalized candidates (params.from and params.senderE164). Formatting differences (e.g., leading '+', spaces) will cause includes() to fail, incorrectly blocking legitimate senders or allowing mi…

tweet 5 of 897 / 280

Both flagged the same line range. AntFleet's unanimous gate fired — the finding posted on the PR.

tweet 6 of 893 / 280

The fix landed in commit pending: (view diff at https://www.antfleet.dev/anatomy/5bbcd2d3-0)

tweet 7 of 881 / 280

AntFleet reviews every PR with two frontier models. Only unanimous findings post.

tweet 8 of 877 / 280

Full anatomy + reasoning + diffs: https://www.antfleet.dev/anatomy/5bbcd2d3-0

Paste into X composer one tweet at a time. X has no multi-tweet intent API.

high bug: Allowlist comparisons use normalized lists but compare agai… — AntFleet anatomy