#!/usr/bin/env perl
# redact-secrets — a stdin -> stdout filter that masks secret-shaped material.
#
# The 2026-07 Stripe exposure happened because a validation tool interpolated a
# live key into stderr. Rule #1 is "never interpolate secrets into a shell/jq
# program" (see docs/security/SECRET_HANDLING.md); THIS is the defence-in-depth
# net: pipe any command that might touch a secret through it, so a slip never
# reaches the terminal, a log, or scrollback.
#
#   stripe posture-check ... 2>&1 | redact-secrets
#   some-tool | redact-secrets | tee run.log
#
# Over-redaction is safe here (unlike the commit gate, which must be precise):
# a masked value in operator output costs nothing; a leaked one is an incident.
use strict;
use warnings;

# (label, regex) — provider-prefixed secrets keep their prefix so output stays
# diagnosable ("which credential"), only the random tail is masked.
my @rules = (
    [ 'sk_live_',  qr/\b((?:sk|rk)_live_)[0-9A-Za-z]{6,}/ ],
    [ 'sk_test_',  qr/\b((?:sk|rk)_test_)[0-9A-Za-z]{6,}/ ],
    [ 'whsec_',    qr/\b(whsec_)[0-9A-Za-z]{6,}/ ],
    [ 'pk_live_',  qr/\b(pk_live_)[0-9A-Za-z]{6,}/ ],
    [ 'AKIA',      qr/\b((?:AKIA|ASIA))[0-9A-Z]{16}/ ],
    [ 'ghp_',      qr/\b(gh[pousr]_)[0-9A-Za-z]{20,}/ ],
    [ 'slack',     qr/\b(xox[baprs]-)[0-9A-Za-z-]{10,}/ ],
);

my $in_private_key = 0;
while (my $line = <STDIN>) {
    if ($in_private_key) {
        $in_private_key = 0 if $line =~ /-----END [A-Z ]{0,24}PRIVATE KEY-----/;
        next;
    }
    if ($line =~ /^(.*?)-----BEGIN [A-Z ]{0,24}PRIVATE KEY-----/) {
        print $1 . "[PEM PRIVATE KEY ***REDACTED***]\n";
        $in_private_key = 1
            unless $line =~ /-----END [A-Z ]{0,24}PRIVATE KEY-----/;
        next;
    }
    for my $r (@rules) {
        my ($label, $re) = @$r;
        $line =~ s/$re/$1 . "***REDACTED***"/ge;
    }
    # Generic: an assignment to a secret-ish name with a long high-entropy value
    # (covers CORTEX_ADMIN_TOKEN and any *_SECRET/_KEY/_TOKEN/_PASSWORD=... slip).
    $line =~ s/((?:SECRET|TOKEN|API[_-]?KEY|PASSWORD|PRIVATE[_-]?KEY|ADMIN[_-]?TOKEN)[A-Z0-9_]*\s*[:=]\s*["']?)[0-9A-Za-z\/\+=_-]{16,}/$1***REDACTED***/gi;
    print $line;
}
