Skip to content

feat(scrubber): v1.5 hardening — elfproef BSN, secret-class expansion, path/DB carrier-strip (KD-0887)#14

Open
CdeJong wants to merge 2 commits into
script-development:mainfrom
CdeJong:KD-0887-v1-5-scrubber-hardening
Open

feat(scrubber): v1.5 hardening — elfproef BSN, secret-class expansion, path/DB carrier-strip (KD-0887)#14
CdeJong wants to merge 2 commits into
script-development:mainfrom
CdeJong:KD-0887-v1-5-scrubber-hardening

Conversation

@CdeJong

@CdeJong CdeJong commented Jul 1, 2026

Copy link
Copy Markdown

Summary

Deferred follow-ups from the KD-0885 audit (war-room Sapper debrief), plus a v1.5 scope addition surfaced by the emmie annexation.

  • BSN eleven-test (Dutch: elfproef) checksum validation. Grouped and bare 9+-digit candidates are now checksum-validated before redaction, resolving the KD-0885 M-1 over-redaction of legitimate 9+-digit IDs (order numbers, invoice IDs, timestamps) while still catching a real BSN embedded in a longer digit run (e.g. a phone number).
  • Secret-class expansion. Database DSN passwords (scheme://user:pass@host), API-key prefixes (sk_live_..., AKIA...), and IPv4 addresses are now redacted.
  • PathNormalizer username redaction fallback (M-3). A frame whose path doesn't start with base_path() no longer leaks the OS username verbatim — /home/<user>/ and /Users/<user>/ segments are redacted.
  • QueryException/PDOException carrier-strip. The highest-value item raised in review: a QueryException message embeds the full SQL string with bound parameter values interpolated in, which is free-text PII (e.g. a client name) that no regex can catch. ErrorTracker now replaces any PDOException-family message with class [SQLSTATE x] [driver code y] before the Scrubber runs, dropping the SQL and bindings entirely.

README/CLAUDE.md/CHANGELOG.md updated accordingly. All new behavior ships with negative-coverage tests (per the KD-0885 root-cause lesson: happy-path-only coverage on security-load-bearing code).

Deferred, not in this PR: a RequestException message-body carrier-strip (raised as a "consider" without a concrete shape/threshold) and a per-project configurable scrub-rule API (a separate, larger feature) — both flagged as follow-ups rather than scope creep here.

Test plan

  • composer test — full Pest suite green (4 pre-existing PathNormalizerTest failures are a Windows-local DIRECTORY_SEPARATOR artifact, confirmed present on unmodified main too; CI runs ubuntu-latest so unaffected)
  • composer phpstan — level max, no errors
  • New negative-coverage tests for every redaction rule (elfproef pass/fail, DSN, API keys, IPv4, path username fallback, QueryException/PDOException carrier-strip)

🤖 Generated with Claude Code

…, path/DB carrier-strip (KD-0887)

- BSN candidates (grouped and bare digit runs) are now validated with the
  eleven-test (Dutch: elfproef) checksum before redaction, resolving the
  KD-0885 M-1 over-redaction of legitimate 9+-digit IDs while still catching
  a real BSN embedded in a longer digit run.
- Scrubber gains DB-DSN password, API-key prefix (sk_live_/AKIA), and IPv4
  redaction.
- PathNormalizer redacts the OS username from any /home/<user>/ or
  /Users/<user>/ path that falls outside the exact base_path() prefix strip
  (M-3).
- ErrorTracker replaces any PDOException-family message (including Laravel's
  QueryException) with a class + SQLSTATE + driver-code fingerprint before
  the Scrubber runs, dropping the SQL string and bound parameter values —
  closing the free-text care-data leak surfaced by the emmie annexation
  (per-exception-type carrier-strip rather than a regex pass).
- README/CLAUDE.md updated for the new scrubbing coverage and out-of-scope
  boundaries; CHANGELOG.md documents all of the above under [Unreleased].

All new behavior ships with negative-coverage tests (KD-0885 root-cause
lesson: happy-path-only coverage on security-load-bearing code).

Deferred: a RequestException message-body carrier-strip was raised as a
"consider" in the ticket discussion but has no concrete shape/threshold
specified — left out-of-scope pending the referenced war-room Nightwatch-
egress recon. A per-project configurable scrub-rule API was also raised in
review but is a separate, larger feature outside this ticket's scope.
@kendo-dev-tracker

Copy link
Copy Markdown

Linked Issue


KD-0887: [kendo-error-tracker] v1.5 scrubber hardening — elfproef BSN + secret-class expansion + path username redaction

Field Value
Project Kendo.dev
Lane To Do
Assignee Christiaan de Jong

View in kendo

pint.json sets fully_qualified_strict_types.leading_backslash_in_global_namespace
to false, so bare RuntimeException/PDOException/Throwable is the house style
in these unnamespaced test files, not \RuntimeException etc. CI's
composer format:check caught this; my local format-on-edit hook did not
(it was normalizing the other direction on this machine).
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