From 292c7de2bf3aa1c8a3194e856d09d1889d7d54e2 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Tue, 18 Aug 2026 20:44:08 +0200 Subject: [PATCH] test(redaction): assert the coarse behaviour the source actually has MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This asserted that _redact_sensitive recurses into a dict under a sensitive key — redacting auth.token while leaving auth.type readable. The source replaces the whole value the moment the KEY matches, so redacted["config"]["auth"] is a string and indexing ["token"] into it raises TypeError. Source and test arrived in the same commit, so this was never drift: it was a disagreement nobody settled. Settled in favour of the source. Fine-grained redaction has to know which sub-keys carry a secret, which is a guess about the shape of data nobody has inspected; matching on the key cannot be wrong that way. Real configs here are {"auth": {"type": "bearer", "token": "${SOME_KEY}"}}, and the cost of guessing wrong is a credential in a log, which no later fix undoes. The price is readability, and it is paid deliberately. Adds a second assertion that the secret appears nowhere in the output by any path, which is the property actually worth protecting. Co-Authored-By: Claude --- tests/test_rest_api_executor.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/test_rest_api_executor.py b/tests/test_rest_api_executor.py index 816628f..7bc2ef1 100644 --- a/tests/test_rest_api_executor.py +++ b/tests/test_rest_api_executor.py @@ -498,7 +498,24 @@ class TestRestApiExecutor: assert redacted["normal_field"] == "visible" def test_redact_sensitive_nested(self): - """Test redaction in nested structures.""" + """A dict under a sensitive key is redacted whole, not recursed into. + + This asserted fine-grained recursion — that `auth.token` was replaced + while `auth`'s other keys stayed readable — and had never passed. The + source redacts the entire value the moment the KEY matches, so + `redacted["config"]["auth"]` is the string, and indexing `["token"]` + into it raises TypeError. + + Settled in favour of the source. Fine-grained redaction has to know + which sub-keys carry the secret, which is a guess about the shape of + data nobody has inspected; redacting on the key cannot be wrong that + way. Real configs here look like + {"auth": {"type": "bearer", "token": "${SOME_API_KEY}"}}, and the cost + of guessing wrong is a credential in a log, which no later fix undoes. + + The price is readability: a reader learns that auth was present, not + that it was bearer. That is the trade being made deliberately. + """ data = { "config": { "database": "mydb", @@ -513,7 +530,10 @@ class TestRestApiExecutor: assert redacted["config"]["database"] == "mydb" assert redacted["config"]["password"] == "***REDACTED***" - assert redacted["config"]["auth"]["token"] == "***REDACTED***" + # The whole sub-dict, not a recursed copy of it. + assert redacted["config"]["auth"] == "***REDACTED***" + # And the secret is nowhere in the output, by any path. + assert "bearer123" not in str(redacted) # Helper Function Tests