HarperFast / HarperFast/harper-pro

A WAF rule written with an IPv4-mapped IPv6 address compiles but can never match

Open
#830 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
3
Forks
0
Avg merge
1d 21h
Merged PRs (30d)
80

Description

Request IPs and rule anchors are normalized differently, so a rule written with an IPv4-mapped IPv6 literal never matches the client it names.

Request side, `normalizeIp` in `waf/matcher.ts`:

```
if (ip.startsWith('::ffff:') && ip.indexOf('.') !== -1) return ip.slice(7);
```

The mapped form is stripped to a dotted quad, which then resolves through `parseIpv4` and is matched against the v4 interval index only.

Rule side, `parseAnchor` applies no such normalization: `parseIpv4('::ffff:1.2.3.4')` fails on the colons, `parseIpv6` succeeds, and the anchor is staged into `v6Exact`. Nothing ever consults `v6Exact` for a request whose address was normalized to v4.

Net effect: `ip: "::ffff:203.0.113.9"` compiles into a rule that can never fire, with no error — it is a valid v6 anchor as far as the compiler is concerned. `ip: "203.0.113.9"` works. Which form an operator reaches for depends on which form they saw in a log or an upstream header, so this is a coin flip at authoring time, not an exotic input.

**Suggested fix:** run rule anchors through the same normalization as request addresses before `parseAnchor` decides v4 vs v6, so both sides share one canonical space. `normalizeIp` already carries a `TODO(M5)` about handling the full `::ffff:0:0/96` range rather than only the canonical lowercase form; the rule side needs whatever that resolves to as well.

Found by cross-model review while reviewing an unrelated change; not customer-reported. The WAF is unreleased — `main` and `v5.3.0-alpha.1` only.

Contributor guide

Open the contributing guide

Research direction

Start in waf/matcher.ts by reading normalizeIp and tracing how parseAnchor classifies rule addresses into the v4 and v6 indexes. Confirm the current behavior with an IPv4-mapped IPv6 rule and request address, then make both paths use the same canonical form. Done means the mapped rule matches the named client without changing the working dotted-quad case.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.