← back to Cli Printing Press
fix(cli): tighten phone-us PII regex to NANP-valid first digits (#1405)
15964974d79e0366e641ea1bbb90af11282c9f90 · 2026-05-14 12:54:07 -0700 · Trevin Chow
* fix(cli): tighten phone-us PII regex to NANP-valid first digits
The phone-us detector matched any 10-digit numeric of the shape
NNN[sep]?NNN[sep]?NNNN, which false-positived on 10-digit product UPCs
that start with 0 (`0190074442`) and coordinate-shaped numerics like
longitudes that start with 1 (`106.0512973`). Both shapes appeared in
the upstream DataForSEO OpenAPI spec and tripped the publish gate on a
spec the operator can't edit.
NANP requires the area code and exchange code to each start with 2-9 —
leading 0 or 1 is not a real US phone number. Constraining each quadrant
to `[2-9]\d{2}` filters out the documented false positives plus the
whole class of leading-0/1 numerics (epoch timestamps, latitudes/
longitudes 0-199, ISBNs, UPCs with check-digit position 0) without
losing any real US phone shape — every existing positive test still
passes.
Closes #1149
* test(cli): rename phone-us test to reflect actual area code 212
Files touched
M internal/artifacts/pii.goM internal/artifacts/pii_test.go
Diff
commit 15964974d79e0366e641ea1bbb90af11282c9f90
Author: Trevin Chow <trevin@trevinchow.com>
Date: Thu May 14 12:54:07 2026 -0700
fix(cli): tighten phone-us PII regex to NANP-valid first digits (#1405)
* fix(cli): tighten phone-us PII regex to NANP-valid first digits
The phone-us detector matched any 10-digit numeric of the shape
NNN[sep]?NNN[sep]?NNNN, which false-positived on 10-digit product UPCs
that start with 0 (`0190074442`) and coordinate-shaped numerics like
longitudes that start with 1 (`106.0512973`). Both shapes appeared in
the upstream DataForSEO OpenAPI spec and tripped the publish gate on a
spec the operator can't edit.
NANP requires the area code and exchange code to each start with 2-9 —
leading 0 or 1 is not a real US phone number. Constraining each quadrant
to `[2-9]\d{2}` filters out the documented false positives plus the
whole class of leading-0/1 numerics (epoch timestamps, latitudes/
longitudes 0-199, ISBNs, UPCs with check-digit position 0) without
losing any real US phone shape — every existing positive test still
passes.
Closes #1149
* test(cli): rename phone-us test to reflect actual area code 212
---
internal/artifacts/pii.go | 10 +++++++---
internal/artifacts/pii_test.go | 14 ++++++++++++++
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/internal/artifacts/pii.go b/internal/artifacts/pii.go
index 97189c27..57acfc53 100644
--- a/internal/artifacts/pii.go
+++ b/internal/artifacts/pii.go
@@ -109,9 +109,13 @@ var piiDetectors = []piiDetector{
{
kind: PIIKindPhoneUS,
// US-shaped 10-digit phone with optional +1 prefix and
- // parens/separators. Word boundaries on each end. Catches
- // "(415) 555-0123", "415-555-0123", "+1 415 555 0123".
- pattern: regexp.MustCompile(`\b(?:\+?1[\s.\-]?)?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}\b`),
+ // parens/separators. NANP requires the area code and the
+ // exchange code to each start with 2-9 — leading 0 or 1 is
+ // not a real US phone. That constraint filters out 10-digit
+ // product UPCs (`0190074442`) and coordinate-shaped numerics
+ // (`106.0512973`) without rejecting any real phone shape.
+ // Catches "(415) 555-0123", "415-555-0123", "+1 415 555 0123".
+ pattern: regexp.MustCompile(`\b(?:\+?1[\s.\-]?)?\(?[2-9]\d{2}\)?[\s.\-]?[2-9]\d{2}[\s.\-]?\d{4}\b`),
},
{
kind: PIIKindZipPlus4,
diff --git a/internal/artifacts/pii_test.go b/internal/artifacts/pii_test.go
index 794453d0..d6a3f82a 100644
--- a/internal/artifacts/pii_test.go
+++ b/internal/artifacts/pii_test.go
@@ -72,6 +72,20 @@ func TestFindPII_PhoneUS(t *testing.T) {
{name: "country-code", line: `"phone": "+1 415 555 0123"`, expectKinds: []string{PIIKindPhoneUS}},
{name: "version-string", line: `"version": "1.2.3"`, expectKinds: nil},
{name: "ip-address", line: `"addr": "192.168.1.1"`, expectKinds: nil},
+ // NANP-shape filters — area code and exchange code must each
+ // start with 2-9. Regression for the dataforseo retro: 10-digit
+ // product UPCs and coordinate-shaped numerics false-positived.
+ {name: "no-product-upc-leading-zero", line: `"upc": "0190074442"`, expectKinds: nil},
+ {name: "no-coordinate-leading-one", line: `"lng": 106.0512973`, expectKinds: nil},
+ {name: "no-epoch-timestamp", line: `"updated_at": 1700000000`, expectKinds: nil},
+ // Boundary cases that prove the constraint is on the leading
+ // digit of each quadrant, not on the whole string.
+ {name: "no-area-code-leading-zero", line: `"phone": "015-555-0123"`, expectKinds: nil},
+ {name: "no-area-code-leading-one", line: `"phone": "115-555-0123"`, expectKinds: nil},
+ {name: "no-exchange-leading-zero", line: `"phone": "415-055-0123"`, expectKinds: nil},
+ {name: "no-exchange-leading-one", line: `"phone": "415-155-0123"`, expectKinds: nil},
+ {name: "area-code-212-valid", line: `"phone": "(212) 555-0123"`, expectKinds: []string{PIIKindPhoneUS}},
+ {name: "area-code-900-valid", line: `"phone": "(900) 234-5678"`, expectKinds: []string{PIIKindPhoneUS}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
← fdca9f7a fix(cli): make cookie-auth login --chrome work on Windows (#
·
back to Cli Printing Press
·
fix(cli): derive doctor probe path from auth.verify_path or d0226602 →