Skip to content

Commit a1380af

Browse files
fix(debugger): redact mappings with bytes keys [backport 3.11] (#14222)
Backport 48b4f55 from #14200 to 3.11. We extend the redaction logic to include the case of mappings whose keys are of type bytes. Resolves #14199. ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) Co-authored-by: Gabriele N. Tornetta <[email protected]>
1 parent e648997 commit a1380af

File tree

5 files changed

+24
-10
lines changed

5 files changed

+24
-10
lines changed

ddtrace/debugging/_redaction.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import typing as t
2+
13
from ddtrace.debugging._expressions import DDCompiler
24
from ddtrace.debugging._expressions import DDExpression
35
from ddtrace.internal.logger import get_logger
@@ -108,8 +110,8 @@
108110

109111

110112
@cached()
111-
def redact(ident: str) -> bool:
112-
normalized = normalize_ident(ident)
113+
def redact(ident: t.Union[str, bytes]) -> bool:
114+
normalized = normalize_ident(ident if isinstance(ident, str) else ident.decode("utf-8", errors="replace"))
113115
return normalized in REDACTED_IDENTIFIERS and normalized not in config.redaction_excluded_identifiers
114116

115117

@@ -135,7 +137,7 @@ def __getmember__(cls, s, a):
135137

136138
@classmethod
137139
def __index__(cls, o, i):
138-
if isinstance(i, str) and redact(i):
140+
if isinstance(i, (str, bytes)) and redact(i):
139141
raise DDRedactedExpressionError(f"Access to entry {i!r} is not allowed")
140142

141143
return super().__index__(o, i)

ddtrace/debugging/_signal/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def serialize(
109109
": ".join(
110110
(
111111
serialize(_, level - 1, maxsize, maxlen, maxfields)
112-
for _ in (k, v if not (_isinstance(k, str) and redact(k)) else REDACTED_PLACEHOLDER)
112+
for _ in (k, v if not (_isinstance(k, (str, bytes)) and redact(k)) else REDACTED_PLACEHOLDER)
113113
)
114114
)
115115
for k, v in islice(value.items(), maxsize)
@@ -279,7 +279,7 @@ def capture_value(
279279
maxfields=maxfields,
280280
stopping_cond=cond,
281281
)
282-
if not (_isinstance(k, str) and redact(k))
282+
if not (_isinstance(k, (str, bytes)) and redact(k))
283283
else redacted_value(v),
284284
)
285285
for k, v in takewhile(lambda _: not cond(_), islice(value.items(), maxsize))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
dynamic instrumentation: extended captured value redaction in mappings with
5+
keys of type ``bytes``.

tests/debugging/test_debugger.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,8 @@ def test_debugger_redacted_identifiers():
11601160

11611161
assert (
11621162
msg_line["message"] == f"token={REDACTED} answer=42 "
1163-
f"pii_dict={{'jwt': '{REDACTED}', 'password': '{REDACTED}', 'username': 'admin'}} "
1163+
f"pii_dict={{'jwt': '{REDACTED}', 'password': '{REDACTED}', 'username': 'admin', "
1164+
f"b'authorization': '{REDACTED}'}} "
11641165
f"pii_dict['jwt']={REDACTED}"
11651166
)
11661167

@@ -1179,8 +1180,9 @@ def test_debugger_redacted_identifiers():
11791180
[{"type": "str", "value": "'jwt'"}, redacted_value(str())],
11801181
[{"type": "str", "value": "'password'"}, redacted_value(str())],
11811182
[{"type": "str", "value": "'username'"}, {"type": "str", "value": "'admin'"}],
1183+
[{"type": "bytes", "value": "b'authorization'"}, redacted_value(str())],
11821184
],
1183-
"size": 3,
1185+
"size": 4,
11841186
},
11851187
},
11861188
"staticFields": {},
@@ -1207,8 +1209,12 @@ def test_debugger_redacted_identifiers():
12071209
{"type": "str", "notCapturedReason": "redactedIdent"},
12081210
],
12091211
[{"type": "str", "value": "'username'"}, {"type": "str", "value": "'admin'"}],
1212+
[
1213+
{"type": "bytes", "value": "b'authorization'"},
1214+
{"type": "str", "notCapturedReason": "redactedIdent"},
1215+
],
12101216
],
1211-
"size": 3,
1217+
"size": 4,
12121218
},
12131219
"@return": {"type": "str", "value": "'top secret'"}, # TODO: Ouch!
12141220
},
@@ -1254,7 +1260,8 @@ def test_debugger_redaction_excluded_identifiers():
12541260
# Only the token value be visible now because it's explicitly excluded from redaction
12551261
assert (
12561262
msg_line["message"] == f"token='deadbeef' answer=42 "
1257-
f"pii_dict={{'jwt': '{REDACTED}', 'password': '{REDACTED}', 'username': 'admin'}} "
1263+
f"pii_dict={{'jwt': '{REDACTED}', 'password': '{REDACTED}', 'username': 'admin', "
1264+
f"b'authorization': '{REDACTED}'}} "
12581265
f"pii_dict['jwt']={REDACTED}"
12591266
)
12601267

tests/submod/stuff.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,5 @@ def __init__(self):
165165

166166
def sensitive_stuff(pwd):
167167
token, answer, data = "deadbeef", 42, SensitiveData() # noqa:F841
168-
pii_dict = {"jwt": "deadbeef", "password": "hunter2", "username": "admin"} # noqa:F841
168+
pii_dict = {"jwt": "deadbeef", "password": "hunter2", "username": "admin", b"authorization": "shh"} # noqa
169169
return pwd

0 commit comments

Comments
 (0)