← back to AgentAbrams

snippets/redact_lint.py

79 lines

#!/usr/bin/env python3
"""
redact_lint.py — lightweight linter to flag obvious sensitive patterns in markdown.

This is not a substitute for human review.
It is a "seatbelt," not a self-driving car.

Usage:
    python3 snippets/redact_lint.py posts/2026-02-22.md
"""

from __future__ import annotations

import re
import sys
from pathlib import Path

PATTERNS = {
    "email": re.compile(
        r"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", re.IGNORECASE
    ),
    "phone_us": re.compile(
        r"\b(\+1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b"
    ),
    "aws_access_key": re.compile(r"\bAKIA[0-9A-Z]{16}\b"),
    "private_key_header": re.compile(
        r"-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----"
    ),
    "slack_token": re.compile(r"\bxox[bpras]-[0-9a-zA-Z-]+\b"),
    "generic_secret_assignment": re.compile(
        r"""(?:api[_-]?key|secret|token|password|credential)[\s]*[=:]\s*['"][^'"]{8,}['"]""",
        re.IGNORECASE,
    ),
    "ip_address": re.compile(
        r"\b(?:\d{1,3}\.){3}\d{1,3}\b"
    ),
    "connection_string": re.compile(
        r"(?:postgres|mysql|mongodb|redis)(?:ql)?://[^\s]+", re.IGNORECASE
    ),
}


def lint_text(text: str) -> list[tuple[str, str]]:
    findings: list[tuple[str, str]] = []
    for name, rx in PATTERNS.items():
        for m in rx.finditer(text):
            start = max(0, m.start() - 24)
            end = min(len(text), m.end() + 24)
            snippet = text[start:end].replace("\n", " ")
            findings.append((name, snippet))
    return findings


def main() -> int:
    if len(sys.argv) != 2:
        print("Usage: redact_lint.py path/to/file.md", file=sys.stderr)
        return 2

    path = Path(sys.argv[1])
    if not path.exists():
        print(f"File not found: {path}", file=sys.stderr)
        return 2

    text = path.read_text(encoding="utf-8", errors="replace")
    findings = lint_text(text)

    if not findings:
        print(f"OK: {path} — no obvious sensitive patterns found.")
        return 0

    print(f"WARNING: {path} — potential sensitive content detected:")
    for name, snippet in findings:
        print(f"  [{name}]: ...{snippet}...")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())