Option C oc_diagnostics
Loading...
Searching...
No Matches
test_redaction.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/test_redaction.py
4
5"""
6Purpose
7-------
8OI-506 / FS-506 — regression coverage for the built-in secret/URL/token
9scrubbers added to ``_apply_redaction``. These run unconditionally when
10``REDACT_SECRETS`` is True (the default) inside production mode.
11
12The three built-in regexes:
13
141. ``_GIT_URL_RE`` — strips ``user:token@`` from http(s) URLs.
152. ``_TOKEN_PREFIXES_RE`` — redacts common opaque-prefix tokens
16 (GitHub PATs, Slack bot tokens, OpenAI keys, JWTs).
173. ``_KV_SECRET_RE`` — redacts ``secret=value`` / ``secret: value``
18 style pairs for a fixed allowlist of key names.
19
20The tests restore ``PROD_MODE`` and ``REDACT_SECRETS`` in ``finally`` so
21they never leak state into neighbouring tests.
22
23Diagnostics
24-----------
25Domain: TEST
26Levels:
27 L2 — test lifecycle
28
29Contracts
30---------
31- Built-ins must scrub even when ``REDACTION_PATTERNS`` is empty.
32- The ``REDACT_SECRETS=False`` toggle must bypass all three built-ins.
33- Dev mode (``PROD_MODE=False``) must never redact.
34"""
35
36from __future__ import annotations
37
38import os
39import sys
40from pathlib import Path
41
42_REPO_ROOT = Path(__file__).resolve().parents[1]
43if str(_REPO_ROOT) not in sys.path:
44 sys.path.insert(0, str(_REPO_ROOT))
45
46from oc_diagnostics import unified_debug as _ud # noqa: E402
47
48
50 """Flip PROD_MODE on and return the restore callable."""
51 old_prod = _ud.PROD_MODE
52 old_toggle = _ud.REDACT_SECRETS
53 _ud.PROD_MODE = True
54 _ud.REDACT_SECRETS = True
55
56 def _restore():
57 _ud.PROD_MODE = old_prod
58 _ud.REDACT_SECRETS = old_toggle
59
60 return _restore
61
62
64 """OI-506: ``https://user:token@host/path`` → ``https://***@host/path``."""
65 restore = _prod_on()
66 try:
67 out = _ud._apply_redaction(
68 "cloning https://alice:ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@github.com/org/repo.git"
69 )
70 assert "alice" not in out
71 assert "ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" not in out
72 assert "https://***@github.com/org/repo.git" in out
73 finally:
74 restore()
75
76
78 """OI-506: ``ghp_…`` tokens outside URL context are still redacted."""
79 restore = _prod_on()
80 try:
81 out = _ud._apply_redaction(
82 "exported GH_TOKEN=ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
83 )
84 assert "ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" not in out
85 assert "ghp_[REDACTED]" in out or "[REDACTED]" in out
86 finally:
87 restore()
88
89
91 """OI-506: ``sk-…`` and ``xoxb-…`` tokens match the prefix regex."""
92 restore = _prod_on()
93 try:
94 out = _ud._apply_redaction(
95 "OPENAI=sk-abcdefghijklmnopqrstuvwxyz0123 SLACK=xoxb-1234567890-AbCdEfGhIj"
96 )
97 assert "sk-abcdefghijklmnopqrstuvwxyz0123" not in out
98 assert "xoxb-1234567890-AbCdEfGhIj" not in out
99 finally:
100 restore()
101
102
104 """OI-506: ``password=…`` is redacted even with no REDACTION_PATTERNS."""
105 old_patterns = _ud.REDACTION_PATTERNS
106 _ud.REDACTION_PATTERNS = []
107 restore = _prod_on()
108 try:
109 out = _ud._apply_redaction("logging in with password=hunter2")
110 assert "hunter2" not in out
111 assert "password=[REDACTED]" in out
112 finally:
113 restore()
114 _ud.REDACTION_PATTERNS = old_patterns
115
116
118 """OI-506: ``api_key``, ``api-key``, and ``apikey`` all match the KV regex."""
119 old_patterns = _ud.REDACTION_PATTERNS
120 _ud.REDACTION_PATTERNS = []
121 restore = _prod_on()
122 try:
123 for key in ("api_key", "api-key", "apikey"):
124 out = _ud._apply_redaction(f"config {key}=supersecret123")
125 assert "supersecret123" not in out, (key, out)
126 assert "[REDACTED]" in out, (key, out)
127 finally:
128 restore()
129 _ud.REDACTION_PATTERNS = old_patterns
130
131
133 """OI-506: with REDACT_SECRETS=False the three built-ins are inert."""
134 old_patterns = _ud.REDACTION_PATTERNS
135 old_prod = _ud.PROD_MODE
136 old_toggle = _ud.REDACT_SECRETS
137 _ud.PROD_MODE = True
138 _ud.REDACT_SECRETS = False
139 _ud.REDACTION_PATTERNS = []
140 try:
141 text = (
142 "https://alice:ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@host/ "
143 "password=hunter2"
144 )
145 out = _ud._apply_redaction(text)
146 assert out == text
147 finally:
148 _ud.PROD_MODE = old_prod
149 _ud.REDACT_SECRETS = old_toggle
150 _ud.REDACTION_PATTERNS = old_patterns
151
152
154 """OI-506: PROD_MODE=False short-circuits the full redaction stack."""
155 old_prod = _ud.PROD_MODE
156 _ud.PROD_MODE = False
157 try:
158 text = "password=hunter2 https://u:t@h/"
159 assert _ud._apply_redaction(text) == text
160 finally:
161 _ud.PROD_MODE = old_prod
test_kv_password_scrubbed_without_configured_pattern()
test_dev_mode_still_skips_all_redaction()
test_git_url_credentials_stripped()
test_github_pat_prefix_redacted_in_bare_text()
test_redact_secrets_toggle_bypasses_builtins()
test_kv_api_key_variants_all_redacted()
test_openai_and_slack_prefixes_redacted()