Skip to content

Hardening pass: 24 findings, one commit each - #6

Open
belisarh wants to merge 51 commits into
mainfrom
redactor/hardening
Open

Hardening pass: 24 findings, one commit each#6
belisarh wants to merge 51 commits into
mainfrom
redactor/hardening

Conversation

@belisarh

@belisarh belisarh commented Aug 27, 2026

Copy link
Copy Markdown
Member

Closes the 24 findings from the hardening review. One commit per finding.

411 tests · 1,100 assertions · 95.3% coverage · PHPStan level 10, no baseline · Pint clean.

Redaction

  • Replaces the matched span, not the whole value: User bob@example.com placed order 123User [REDACTED] placed order 123.
  • Safe keys preserve their entire subtree; message, title, url, path, ip, user_agent, source and target removed from the shipped safe lists.
  • session_id moved from safe to blocked; it was previously in both, and safe won.
  • Safe keys support the * wildcards the README documents.
  • Strategies chain, so entropy detection still inspects what pattern rules leave standing.
  • Recursion is depth-bounded (max_depth, default 32) and cycle-aware.
  • PCRE failures fail closed instead of reading as "no match".
  • Entropy measured per character rather than per byte, with optional per-alphabet thresholds (charset_thresholds).
  • Each node is dispatched through the strategy chain once instead of twice.

Patterns

  • Rules gain mode (replace/mask/partial/remove/full), keep, mask_character, capture and validator.
  • Validators luhn, iban and ssn reject values of the right shape that cannot be the real thing.
  • aws_secret_key no longer matches any 40-character alphanumeric run.
  • api_key_generic, base64_key and password_assignment keep their labels and replace only the value.
  • url_with_auth captures just the credentials and precedes email in all profiles.
  • credit_card uses partial mode; iban is detectable for the first time.

API

  • redactWithMetadata() returns a RedactionResult carrying value, wasRedacted, redactedKeys and findings.
  • redactSafely() never throws and fails closed.
  • _redacted markers are no longer written into lists or over an existing key.
  • Removed addStrategy(), removeStrategy(), calculateShannonEntropy() and isCommonPattern(); the last two are public on ShannonEntropyStrategy.
  • Redactor and Scanner are container singletons.

Logging

  • RedactorProcessor / RedactorTap redact message, context and extra without replacing the channel's formatter.
  • ReadactFormatter::formatBatch() formats every record; it previously returned only the first.
  • ReadactFormatter accepts an inner formatter to wrap.
  • Diagnostics cannot re-enter the logger that raised them.

Scanning

  • Findings carry rule, line, column, a redacted excerpt and a fingerprint.
  • --output=sarif emits SARIF 2.1.0 for GitHub code scanning.
  • --baseline / --update-baseline suppress accepted findings; the file stores hashes, never secrets.
  • Exclude patterns match paths as well as basenames, so vendor/* and node_modules/* work.
  • Binary files and gitignored files are skipped.
  • php artisan redactor:validate resolves every profile and fails on broken ones.

Config

  • Every documented environment variable takes effect; REDACTOR_MAX_OBJECT_SIZE was ignored and REDACTOR_SCAN_MAX_FILE_SIZE crashed the scan command.
  • Invalid values throw with the offending path named instead of falling back silently.
  • mergeConfigFrom() runs in register(), not boot().
  • New: max_depth, charset_thresholds, scan.skip_binary, scan.respect_gitignore, scan.baseline.

Performance

  • BlockedKeysStrategy::shouldHandle: 1.223 µs → 0.288 µs, via a key matcher compiled once per pattern list.
  • Default profile: 15.0k → 21.2k redactions/sec. Strict: 10.8k → 16.4k.

Packaging and CI

  • Laravel 11 support dropped; requires illuminate/support ^12.0|^13.0. Every 11.x release is flagged by a Packagist advisory, so Composer refuses to install any of them.
  • Laravel 13 supported and in the matrix; symfony/finder widened to ^7.0|^8.0.
  • PHP 8.5 supported and in the matrix; fail-fast disabled.
  • Dropped the unused pestphp/pest-plugin-laravel dev dependency; it was the only thing pinning the test toolchain to one Laravel major.
  • Tests\ removed from the production autoload; .gitattributes added.
  • Dropped unused spatie/laravel-package-tools; declared symfony/finder and monolog/monolog.
  • Coverage floor 90; failOnWarning, failOnRisky, failOnDeprecation enabled.
  • tests/Performance runs in a coverage: none job; boundary tests pin every redaction threshold.
  • Mutation testing available locally via composer mutate; not run in CI.
  • LICENCE.md renamed to LICENSE.md, fixing the README links and Packagist licence detection.

Breaking changes

Pre-1.0. Full list in CHANGELOG.md; the significant ones are span replacement, the safe_keys semantics and default list, the Monolog processor move, structured scan findings, and the four removed methods.

@belisarh
belisarh force-pushed the redactor/hardening branch from adffa8d to 8986d3b Compare August 27, 2026 07:41
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