Skip to content

fix(debugger): redact sensitive data in log probe messages - #9704

Draft
p-datadog wants to merge 5 commits into
masterfrom
fix/di-log-probe-message-redaction
Draft

fix(debugger): redact sensitive data in log probe messages#9704
p-datadog wants to merge 5 commits into
masterfrom
fix/di-log-probe-message-redaction

Conversation

@p-datadog

@p-datadog p-datadog commented Aug 5, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Makes the Dynamic Instrumentation log-probe message path honor the same redaction the snapshot path applies.

Log probe template segments were rendered with util.inspect ($dd_inspect) and no redaction. A template that references an object or map (e.g. {user}, {params}) interpolated every own property / entry verbatim, so sensitive identifiers (password, api_key, session, …) were emitted in plaintext to the debugger intake — even though the snapshot path (snapshot/processor.js) already redacts them.

The fix injects a redaction-aware segment serializer into the code evaluated in the paused process:

  • $dd_redactSegmentValue replaces a property/entry value with [redacted] when its key matches a redacted identifier, for plain objects, class instances, and Maps;
  • objects/maps whose own keys are all non-redacted are passed to util.inspect untouched, so the existing message format (including [Object], [Getter], circular/proxy rendering) is preserved;

Motivation

APMSP-3552 audited across all tracers - Node is the only one lacking redaction besides Ruby.

Additional Notes

Ruby fix: DataDog/dd-trace-rb#6155

Log probe template segments rendered EL expression results with
util.inspect and no redaction, so a template referencing an object or
map (e.g. {user}, {params}) interpolated every property/entry verbatim.
Sensitive identifiers (password, api_key, session, ...) leaked in
plaintext to the debugger intake, even though the snapshot path redacts
them.

Redact values whose key matches a redacted identifier before inspecting,
inside the code evaluated in the paused process. Objects and maps whose
own keys are all non-redacted are inspected unchanged, preserving the
existing message format.

Signed-off-by: ddsign <ddsign@bsdpower.com>
@p-datadog p-datadog added semver-patch AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos labels Aug 5, 2026
@github-actions github-actions Bot added the debugger Dynamic Instrumentation & Live Debugger label Aug 5, 2026
@dd-octo-sts

dd-octo-sts Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 7.85 MB
Deduped: 8.52 MB
No deduping: 8.52 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.3 | 125.43 kB | 441.68 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Aug 5, 2026

Copy link
Copy Markdown

Pipelines  Tests

⚠️ Warnings

🚦 5 Pipeline jobs failed

Debugger | Debugger / ubuntu (node-maintenance)   View in Datadog   GitHub Actions

🔧 Fix in code. This looks caused by changes in this PR. 1 failed test. AssertionError: Expected values to be strictly equal at integration-tests/debugger/redact.spec.js:80:14

Debugger | Debugger / ubuntu (node-oldest)   View in Datadog   GitHub Actions

🔧 Fix in code. This looks caused by changes in this PR. 2 failed tests due to assertion errors in PII redaction checks. Error: Expected values to be strictly equal in integration-tests/debugger/redact.spec.js.

Platform | integration-guardrails (20.0.0)   View in Datadog   GitHub Actions

🔧 Fix in code. This looks caused by changes in this PR. 1 failed test. AssertionError: expected output to contain message about incompatible runtime Node.js 20.0.0.

View all 5 failed jobs.

📋 Copy prompt for your agent
CI on my pull request is failing. Help me find and fix the root cause of each failing job below — they were flagged as caused by changes in this PR, so focus on the diff. For each job, explain the failure and propose a fix.

Branch: fix/di-log-probe-message-redaction

Debugger | Debugger / ubuntu (node-maintenance)
Commit: 9ff5c0ddc5bbb5a5bc388acbb6d23682cc4a1a26
Error (code / test):
1 failed test. AssertionError: Expected values to be strictly equal at integration-tests/debugger/redact.spec.js:80:14
CI job: https://github.com/DataDog/dd-trace-js/actions/runs/31044882426/job/92439052573

Debugger | Debugger / ubuntu (node-oldest)
Commit: 9ff5c0ddc5bbb5a5bc388acbb6d23682cc4a1a26
Error (code / test):
2 failed tests due to assertion errors in PII redaction checks. Error: Expected values to be strictly equal in integration-tests/debugger/redact.spec.js.
CI job: https://github.com/DataDog/dd-trace-js/actions/runs/31044882426/job/92439052630

Platform | integration-guardrails (20.0.0)
Commit: 9ff5c0ddc5bbb5a5bc388acbb6d23682cc4a1a26
Error (code / test):
1 failed test. AssertionError: expected output to contain message about incompatible runtime Node.js 20.0.0.
CI job: https://github.com/DataDog/dd-trace-js/actions/runs/31044882000/job/92438774130

Plus 1 more failing job not shown here.

❄️ 2 New flaky tests detected

Dynamic Instrumentation snapshot PII redaction log probe message should not leak a redacted key beyond the rendered window of a large Map from log probe message   View in Datadog
Expected values to be strictly equal:
&#43; actual - expected

&#43; &#34;Map(5) { &#39;k0&#39; =&gt; 0, &#39;k1&#39; =&gt; 1, &#39;k2&#39; =&gt; 2, &#39;k3&#39; =&gt; 3, &#39;password&#39; =&gt; &#39;shh!&#39; }&#34;
- &#34;Map(5) { &#39;k0&#39; =&gt; 0, &#39;k1&#39; =&gt; 1, &#39;k2&#39; =&gt; 2, ... 2 more items }&#34;

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
&#43; actual - expected

&#43; &#34;Map(5) { &#39;k0&#39; =&gt; 0, &#39;k1&#39; =&gt; 1, &#39;k2&#39; =&gt; 2, &#39;k3&#39; =&gt; 3, &#39;password&#39; =&gt; &#39;shh!&#39; }&#34;
...

New test introduced in this PR is flaky.

Dynamic Instrumentation snapshot PII redaction log probe message should redact sensitive identifiers when a template interpolates an object or map from log probe message   View in Datadog
Expected values to be strictly equal:
&#43; actual - expected

&#43; &#34;obj={ username: &#39;alice&#39;, password: &#39;[redacted]&#39;, [Symbol(password)]: &#39;[redacted]&#39; };map=Map(3) { &#39;username&#39; =&gt; &#39;alice&#39;, &#39;password&#39; =&gt; &#39;[redacted]&#39;, Symbol(password) =&gt; &#39;[redacted]&#39; }&#34;
- &#34;obj={ username: &#39;alice&#39;, password: &#39;[redacted]&#39;, Symbol(password): &#39;[redacted]&#39; };map=Map(3) { &#39;username&#39; =&gt; &#39;alice&#39;, &#39;password&#39; =&gt; &#39;[redacted]&#39;, Symbol(password) =&gt; &#39;[redacted]&#39; }&#34;

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
&#43; actual - expected

&#43; &#34;obj={ username: &#39;alice&#39;, password: &#39;[redacted]&#39;, [Symbol(password)]: &#39;[redacted]&#39; };map=Map(3) { &#39;username&#39; =&gt; &#39;alice&#39;, &#39;password&#39; =&gt; &#39;[redacted]&#39;, Symbol(password) =&gt; &#39;[redacted]&#39; }&#34;
...

New test introduced in this PR is flaky.

View in Flaky Test Management

ℹ️ Info

No other issues found (see more)

🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 98.46% (-0.05%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c3d58c7 | Docs | Datadog PR Page | Give us feedback!

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.46%. Comparing base (d678882) to head (c3d58c7).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9704      +/-   ##
==========================================
- Coverage   98.51%   98.46%   -0.06%     
==========================================
  Files         963      963              
  Lines      135796   135877      +81     
  Branches    11984    11815     -169     
==========================================
+ Hits       133785   133791       +6     
- Misses       2011     2086      +75     
Flag Coverage Δ
aiguard 56.97% <ø> (-0.03%) ⬇️
aiguard-integration 55.82% <ø> (ø)
apm-bucket-0 57.22% <ø> (-0.03%) ⬇️
apm-bucket-1 63.31% <ø> (-0.03%) ⬇️
apm-bucket-2 62.11% <ø> (-0.03%) ⬇️
apm-bucket-3 59.65% <ø> (-0.03%) ⬇️
apm-capabilities-tracing 62.61% <ø> (ø)
apm-integrations-aerospike 56.27% <ø> (-0.03%) ⬇️
apm-integrations-confluentinc-kafka-javascript 60.96% <ø> (-0.03%) ⬇️
apm-integrations-couchbase 56.69% <ø> (-0.03%) ⬇️
apm-integrations-http 62.10% <ø> (-0.03%) ⬇️
apm-integrations-kafkajs 61.54% <ø> (-0.03%) ⬇️
apm-integrations-next 59.26% <ø> (-0.03%) ⬇️
apm-integrations-prisma 58.27% <ø> (-0.03%) ⬇️
appsec 71.96% <ø> (-0.09%) ⬇️
appsec-express_fastify_graphql 69.45% <ø> (-0.02%) ⬇️
appsec-integration 50.22% <ø> (-0.01%) ⬇️
appsec-kafka_ldapjs_lodash 63.33% <ø> (-0.02%) ⬇️
appsec-mongodb-core_mongoose_mysql 66.96% <ø> (-0.02%) ⬇️
appsec-next 56.67% <ø> (-0.02%) ⬇️
appsec-node-serialize_passport_postgres 66.61% <ø> (-0.02%) ⬇️
appsec-sourcing_stripe_template 64.98% <ø> (-0.03%) ⬇️
debugger 64.19% <100.00%> (-0.02%) ⬇️
instrumentations-bucket-0 51.57% <ø> (-0.03%) ⬇️
instrumentations-bucket-1 59.60% <ø> (-0.03%) ⬇️
instrumentations-bucket-10 61.50% <ø> (-0.02%) ⬇️
instrumentations-bucket-11 51.48% <ø> (-0.03%) ⬇️
instrumentations-bucket-12 52.28% <ø> (-0.03%) ⬇️
instrumentations-bucket-13 51.59% <ø> (-0.03%) ⬇️
instrumentations-bucket-2 53.38% <ø> (-0.03%) ⬇️
instrumentations-bucket-3 58.66% <ø> (-0.03%) ⬇️
instrumentations-bucket-4 52.12% <ø> (-0.03%) ⬇️
instrumentations-bucket-5 57.16% <ø> (-0.02%) ⬇️
instrumentations-bucket-6 60.24% <ø> (-0.03%) ⬇️
instrumentations-bucket-7 58.02% <ø> (-0.03%) ⬇️
instrumentations-bucket-8 58.99% <ø> (-0.03%) ⬇️
instrumentations-bucket-9 61.04% <ø> (-0.02%) ⬇️
instrumentations-instrumentation-couchbase 50.84% <ø> (-0.03%) ⬇️
instrumentations-integration-esbuild 33.93% <ø> (ø)
llmobs-ai_anthropic_bedrock 62.81% <ø> (-0.02%) ⬇️
llmobs-bucket-1 61.28% <ø> (-0.02%) ⬇️
llmobs-openai 61.77% <ø> (-0.02%) ⬇️
llmobs-openai-agents_vertex-ai 59.75% <ø> (-0.02%) ⬇️
llmobs-sdk 66.46% <ø> (-0.03%) ⬇️
master-coverage 98.46% <100.00%> (?)
openfeature 55.61% <ø> (ø)
openfeature-unit 53.14% <ø> (-0.03%) ⬇️
platform-core_esbuild_instrumentations-misc 40.54% <ø> (-0.02%) ⬇️
platform-integration 60.48% <ø> (ø)
platform-shimmer_unit-guardrails_webpack 38.80% <ø> (-0.02%) ⬇️
plugins-bucket-0 56.78% <ø> (-0.02%) ⬇️
plugins-bucket-1 53.92% <ø> (ø)
plugins-bucket-11 61.36% <ø> (-0.48%) ⬇️
plugins-bucket-14 58.75% <ø> (?)
plugins-bucket-17 61.23% <ø> (?)
plugins-bucket-18 58.03% <ø> (-3.34%) ⬇️
plugins-bucket-19 61.28% <ø> (+1.69%) ⬆️
plugins-bucket-20 61.57% <ø> (-0.02%) ⬇️
plugins-bucket-4 58.17% <ø> (-0.03%) ⬇️
plugins-bullmq_cassandra_cookie 61.21% <ø> (-0.03%) ⬇️
plugins-cookie-parser_crypto_dd-trace-api 56.33% <ø> (-0.03%) ⬇️
plugins-fetch_fs_generic-pool 58.22% <ø> (+0.01%) ⬆️
plugins-google-cloud-pubsub_grpc_handlebars 64.05% <ø> (-0.03%) ⬇️
plugins-hapi_hono_ioredis 59.75% <ø> (-0.03%) ⬇️
plugins-jest_knex_langgraph ?
plugins-jest_langgraph_ldapjs 55.29% <ø> (?)
plugins-ldapjs_light-my-request_limitd-client ?
plugins-light-my-request_limitd-client_lodash 58.20% <ø> (?)
plugins-lodash_mariadb_memcached ?
plugins-mariadb_memcached_mercurius 61.22% <ø> (?)
plugins-moleculer_mongodb_mongodb-core ?
plugins-mongodb-core_mongoose_multer 58.85% <ø> (?)
plugins-mongoose_multer_mysql ?
plugins-mysql2_nats_node-serialize ?
plugins-mysql_mysql2_nats 60.40% <ø> (?)
plugins-opensearch_passport-http_pino ?
plugins-pino_postgres_process 58.62% <ø> (?)
plugins-postgres_process_pug ?
plugins-pug_redis_router 61.45% <ø> (?)
plugins-redis_router_sequelize ?
plugins-test-and-upstream-rhea_undici_url ?
plugins-url_valkey_vm 57.12% <ø> (?)
plugins-valkey_vm_winston ?
plugins-winston_ws 59.44% <ø> (?)
plugins-ws ?
profiling 61.44% <ø> (-0.03%) ⬇️
serverless-aws-sdk-aws-sdk 54.85% <ø> (-0.02%) ⬇️
serverless-aws-sdk-base-inject-field 50.79% <ø> (-0.03%) ⬇️
serverless-aws-sdk-bedrockruntime 54.50% <ø> (-0.03%) ⬇️
serverless-aws-sdk-client 56.10% <ø> (-0.03%) ⬇️
serverless-aws-sdk-dynamodb 55.36% <ø> (-0.02%) ⬇️
serverless-aws-sdk-eventbridge 49.36% <ø> (-0.03%) ⬇️
serverless-aws-sdk-kinesis 58.88% <ø> (-0.03%) ⬇️
serverless-aws-sdk-lambda 57.03% <ø> (-0.03%) ⬇️
serverless-aws-sdk-s3 55.45% <ø> (-0.03%) ⬇️
serverless-aws-sdk-serverless-peer-service 59.28% <ø> (-0.03%) ⬇️
serverless-aws-sdk-sns 59.70% <ø> (-0.03%) ⬇️
serverless-aws-sdk-sqs 60.13% <ø> (-0.02%) ⬇️
serverless-aws-sdk-stepfunctions 55.28% <ø> (-0.03%) ⬇️
serverless-aws-sdk-util 51.33% <ø> (-0.03%) ⬇️
serverless-bucket-0 53.99% <ø> (ø)
serverless-bucket-1 58.82% <ø> (-0.03%) ⬇️
test-optimization-cucumber 71.48% <ø> (+0.03%) ⬆️
test-optimization-cypress 65.24% <ø> (+0.10%) ⬆️
test-optimization-jest 72.96% <ø> (-0.13%) ⬇️
test-optimization-mocha 72.53% <ø> (+0.06%) ⬆️
test-optimization-playwright-playwright-atr 60.15% <ø> (+<0.01%) ⬆️
test-optimization-playwright-playwright-efd 60.36% <ø> (+0.08%) ⬆️
test-optimization-playwright-playwright-final-status 60.45% <ø> (+0.01%) ⬆️
test-optimization-playwright-playwright-impacted-tests 59.98% <ø> (+0.16%) ⬆️
test-optimization-playwright-playwright-reporting 61.24% <ø> (-0.02%) ⬇️
test-optimization-playwright-playwright-test-management 60.67% <ø> (-0.40%) ⬇️
test-optimization-playwright-playwright-test-span 60.20% <ø> (-0.05%) ⬇️
test-optimization-selenium 59.39% <ø> (-0.13%) ⬇️
test-optimization-testopt 57.89% <ø> (+0.07%) ⬆️
test-optimization-vitest 73.57% <ø> (+0.05%) ⬆️
test-optimization-vitest-browser 58.98% <ø> (+0.01%) ⬆️
test-optimization-webdriverio 64.43% <ø> (-0.40%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: ddsign <ddsign@bsdpower.com>
@p-datadog
p-datadog requested a review from Copilot August 5, 2026 16:54
@p-datadog

Copy link
Copy Markdown
Member Author

@codex review

…ient

index.js now requires ./snapshot/redaction at load, which transitively
requires ../config (worker-only). The onPause spec must pass the already
config-stubbed redaction module to proxyquire so the real config, which
reads null workerData in unit tests, is not loaded.

Signed-off-by: ddsign <ddsign@bsdpower.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Dynamic Instrumentation log-probe template rendering so that interpolated values (especially objects and Maps) honor the same sensitive-identifier redaction behavior already applied to snapshot capture, preventing plaintext secrets from being emitted in probe messages.

Changes:

  • Adds a redaction-aware $dd_inspectSegment serializer injected into the paused-process evaluation code used for template segment rendering.
  • Updates template segment compilation to use $dd_inspectSegment instead of direct util.inspect calls.
  • Extends the debugger redaction integration test target app and adds an integration test asserting object/Map message redaction.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/dd-trace/test/debugger/devtools_client/condition.spec.js Updates unit test expectations to use $dd_inspectSegment in compiled segment output.
packages/dd-trace/src/debugger/devtools_client/index.js Injects redaction-aware segment inspection helpers into the paused-frame evaluation prelude.
packages/dd-trace/src/debugger/devtools_client/condition.js Switches segment rendering to $dd_inspectSegment for consistent redaction behavior.
integration-tests/debugger/target-app/redact.js Adds an object and Map containing a redacted key to exercise message redaction.
integration-tests/debugger/redact.spec.js Adds an integration test verifying log-probe message redaction for object and Map interpolation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/dd-trace/src/debugger/devtools_client/index.js Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff7537cca8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/dd-trace/src/debugger/devtools_client/index.js Outdated
Comment thread packages/dd-trace/src/debugger/devtools_client/index.js
Comment thread packages/dd-trace/src/debugger/devtools_client/condition.js Outdated
Comment thread packages/dd-trace/src/debugger/devtools_client/index.js Outdated
Comment thread packages/dd-trace/src/debugger/devtools_client/index.js Outdated
@pr-commenter

pr-commenter Bot commented Aug 5, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-08-05 20:48:50

Comparing candidate commit c3d58c7 in PR branch fix/di-log-probe-message-redaction with baseline commit d678882 in branch master.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 2321 metrics, 37 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:appsec-appsec-enabled-24

  • unstable execution_time [-211.691ms; +206.365ms] or [-7.886%; +7.687%]

scenario:appsec-appsec-enabled-26

  • unstable execution_time [-231.262ms; +222.313ms] or [-9.011%; +8.662%]

scenario:appsec-appsec-enabled-with-attacks-24

  • unstable execution_time [-160.624ms; +155.102ms] or [-5.174%; +4.996%]

scenario:appsec-appsec-enabled-with-attacks-26

  • unstable execution_time [-191.793ms; +188.505ms] or [-6.466%; +6.355%]

scenario:appsec-control-20

  • unstable execution_time [-121.444ms; +119.173ms] or [-7.376%; +7.238%]

scenario:appsec-control-24

  • unstable execution_time [-115394.011µs; +115382.378µs] or [-9.203%; +9.202%]

scenario:appsec-control-26

  • unstable execution_time [-126.433ms; +130.888ms] or [-10.128%; +10.485%]

scenario:appsec-iast-no-vulnerability-control-20

  • unstable execution_time [-16388.602µs; +14671.269µs] or [-6.462%; +5.784%]

scenario:appsec-iast-no-vulnerability-iast-enabled-always-active-20

  • unstable execution_time [-15.003ms; +12.024ms] or [-5.924%; +4.747%]

scenario:appsec-iast-startup-time-iast-enabled-20

  • unstable execution_time [-18.803ms; +30.411ms] or [-4.676%; +7.562%]

scenario:appsec-iast-with-vulnerability-control-20

  • unstable execution_time [-28636.033µs; +27874.460µs] or [-5.157%; +5.020%]

scenario:debugger-line-probe-with-snapshot-default-24

  • unstable cpu_user_time [-2004.543ms; +2802.396ms] or [-24.082%; +33.667%]
  • unstable execution_time [-2014.954ms; +2834.691ms] or [-22.284%; +31.350%]
  • unstable instructions [-16.9G instructions; +23.8G instructions] or [-24.900%; +34.987%]
  • unstable max_rss_usage [-8899.711KB; +10802.911KB] or [-5.602%; +6.800%]
  • unstable throughput [-768.694op/s; +582.940op/s] or [-21.145%; +16.036%]

scenario:debugger-line-probe-without-snapshot-24

  • unstable cpu_user_time [-1986.471ms; +3177.798ms] or [-24.036%; +38.450%]
  • unstable execution_time [-1986.651ms; +3201.375ms] or [-22.124%; +35.651%]
  • unstable instructions [-17.2G instructions; +27.4G instructions] or [-25.412%; +40.488%]
  • unstable max_rss_usage [-8.493MB; +13.153MB] or [-5.408%; +8.375%]
  • unstable throughput [-857.800op/s; +528.749op/s] or [-23.384%; +14.414%]

scenario:debugger-line-probe-without-snapshot-26

  • unstable cpu_user_time [-2353.255ms; +772.824ms] or [-24.836%; +8.156%]
  • unstable execution_time [-2419.597ms; +849.303ms] or [-23.718%; +8.325%]
  • unstable instructions [-20.6G instructions; +6.6G instructions] or [-25.908%; +8.348%]
  • unstable throughput [-175.840op/s; +465.523op/s] or [-5.388%; +14.266%]

scenario:dogstatsd-with-tags-20

  • unstable cpu_user_time [-215.698ms; +457.362ms] or [-4.594%; +9.742%]
  • unstable execution_time [-215.620ms; +453.953ms] or [-4.521%; +9.519%]
  • unstable throughput [-161183.816op/s; +75956.583op/s] or [-9.159%; +4.316%]

scenario:plugin-aws-sdk-lambda-inject-with-context-24

  • unstable cpu_user_time [-212.865ms; +228.998ms] or [-5.520%; +5.939%]
  • unstable execution_time [-212.945ms; +229.695ms] or [-5.485%; +5.916%]
  • unstable throughput [-28946.015op/s; +26597.755op/s] or [-5.579%; +5.127%]

scenario:plugin-claude-agent-sdk-compact-stream-scan-26

  • unstable cpu_usage_percentage [-6.744%; +4.215%]

scenario:plugin-graphql-long-with-depth-off-26

  • unstable max_rss_usage [-29.399MB; +36.943MB] or [-14.584%; +18.326%]

scenario:plugin-graphql-long-with-depth-on-max-20

  • unstable cpu_user_time [-565.251ms; +604.062ms] or [-4.896%; +5.233%]
  • unstable execution_time [-573.204ms; +610.142ms] or [-4.866%; +5.179%]
  • unstable throughput [-3.561op/s; +3.315op/s] or [-5.214%; +4.854%]

scenario:test-optimization-large-suite-20

  • unstable max_rss_usage [-5257.485KB; +5734.485KB] or [-6.492%; +7.080%]

Address review comment: $dd_isRedactedIdentifier only handled string keys, so
symbol property names and symbol Map keys (e.g. Symbol('password')) were
interpolated verbatim into log probe messages while the snapshot path redacts
them via normalizeName(name, isSymbol).

- index.js: normalize symbol keys the same way as snapshot/redaction.js (strip
  the Symbol() wrapper) before checking the redacted-identifier set
- target-app/redact.js: add a Symbol('password') key to obj and map
- redact.spec.js: assert the symbol-keyed value is redacted

Verified: eslint clean, debugger unit suite (618 passing), redact integration
test (3 passing).

Signed-off-by: ddsign <ddsign@bsdpower.com>
Addresses four review comments on the message-path redactor:

- Detect Maps across realms: use util.types.isMap instead of instanceof, so a
  Map from node:vm is redacted rather than printed verbatim.
- Bound the Map scan: only the first maxArrayLength entries are rendered, so
  scan at most that many keys and rebuild only when a rendered key is redacted,
  keeping the common large-Map case constant-time on the paused thread.
- Render Proxy segments as [Proxy]: enumerating a proxy via Reflect.ownKeys runs
  its traps (customer code) in the paused frame, and letting util.inspect render
  the target would leak a proxy-wrapped secret.
- Redact direct references: compileSegments threads the terminal identifier of a
  direct reference to $dd_inspectSegment, which redacts by name like the snapshot
  path. Computed/dynamic terminals have no static name and fall through.

Tests: condition.spec.js identifier threading; redact.spec.js direct-ref,
cross-realm Map, Proxy, and large-Map-window cases + target-app locals;
template.spec.js proxy assertion updated to [Proxy].

Verified: eslint clean; debugger unit suite (619 passing); redact + template
integration tests (11 passing).

Signed-off-by: ddsign <ddsign@bsdpower.com>
@p-datadog
p-datadog requested a review from Copilot August 5, 2026 23:02
@p-datadog

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (3)

integration-tests/debugger/redact.spec.js:84

  • Expected object rendering should tolerate the bracketed vs non-bracketed symbol property key format across Node majors; otherwise this strict equality assertion will be version-fragile.
      assert.strictEqual(
        message,
        "obj={ username: 'alice', password: '[redacted]', Symbol(password): '[redacted]' };" +
          "map=Map(3) { 'username' => 'alice', 'password' => '[redacted]', Symbol(password) => '[redacted]' }"
      )

packages/dd-trace/src/debugger/devtools_client/index.js:59

  • The comment here says bounding the scan keeps the large-Map case constant-time, but when a redacted key is within the rendered window the code still clones the entire Map (O(n) in Map size). This is misleading and can understate pause-time cost for very large Maps; please clarify the comment (and consider whether an additional cap is needed).
      // Only the first maxArrayLength entries are rendered, so scanning past that
      // window cannot affect the output. Bounding the scan keeps the common
      // large-Map case constant-time on the paused application thread.

integration-tests/debugger/redact.spec.js:6

  • This spec currently hard-codes the symbol-key rendering shape (Symbol(password): ...). Node’s util.inspect output for symbol property keys differs across Node majors (see template.spec’s handling of Symbol(nodejs.util.inspect.custom)), so this test may fail on older majors unless it gates on the runtime version.

This issue also appears on line 80 of the same file.

'use strict'

const assert = require('node:assert/strict')
const { once } = require('node:events')
const { assertObjectContains } = require('../helpers')
const { setup } = require('./utils')

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d58c7be5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +63 to +64
for (const key of value.keys()) {
if ($dd_index++ >= $dd_max) break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scan every Map entry rendered on Node 18

On Node.js 18, util.inspect does not apply maxArrayLength to Maps—the existing expectation in integration-tests/debugger/template.spec.js explicitly renders all five entries on that runtime. Consequently, a Map whose fourth or later key is password passes this three-entry scan unchanged and emits the sensitive value. The redaction window must follow the runtime's actual Map rendering behavior rather than assuming the configured cap applies.

AGENTS.md reference: AGENTS.md:L179-L185

Useful? React with 👍 / 👎.

maxStringLength: 8 * 1024,
breakLength: Infinity
};
const $dd_redactedIdentifiers = new Set(${JSON.stringify([...REDACTED_IDENTIFIERS])});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve Set outside the paused lexical scope

When the paused function has a local or parameter named Set, this unqualified constructor resolves to that application binding; for example, const Set = 'shadow' makes the entire setup throw TypeError: Set is not a constructor before any template result is produced. In that context every evaluated log probe at the pause is sent with an empty message, so the setup should obtain the intrinsic from an explicit global reference rather than the call frame's lexical scope.

Useful? React with 👍 / 👎.

if ($dd_index++ >= $dd_max) break;
if ($dd_isRedactedIdentifier(key)) { $dd_hasRenderedRedactedKey = true; break; }
}
if (!$dd_hasRenderedRedactedKey) return value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact own properties attached to Maps

When a Map also has a sensitive own property, such as map.password = 'shh!', this branch examines only Map entry keys and returns the original value if none of the first entries are sensitive. util.inspect renders that property as Map(0) { password: 'shh!' }, so interpolating the Map still leaks it; Map values need their own string/symbol properties checked as well as their entries.

Useful? React with 👍 / 👎.

Comment on lines +68 to +69
const redacted = new Map();
for (const [key, val] of value) redacted.set(key, $dd_isRedactedIdentifier(key) ? '[redacted]' : val);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid cloning an entire Map for three rendered entries

The new bounded pre-scan still falls through to a full copy when a sensitive key occurs near the front: a million-entry Map whose first key is password causes this loop to iterate and allocate all million entries while the application thread is paused, although util.inspect renders only three on affected runtimes. This redacted-near-front case preserves the whole-Map pause cost from the earlier implementation, so redaction should avoid materializing entries outside the rendered window.

AGENTS.md reference: AGENTS.md:L194-L200

Useful? React with 👍 / 👎.

return false;
};
const $dd_redactSegmentValue = (value) => {
if (value === null || typeof value !== 'object') return value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact properties attached to functions

When a template interpolates a function with a sensitive own property, such as handler.password = 'shh!', this early return skips redaction because functions have typeof value === 'function'. util.inspect then renders [Function: handler] { password: 'shh!' }, so function-valued configuration objects can still leak secrets; functions need the same own-property redaction path as objects.

Useful? React with 👍 / 👎.

const $dd_max = $dd_segmentInspectOptions.maxArrayLength;
let $dd_index = 0;
let $dd_hasRenderedRedactedKey = false;
for (const key of value.keys()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bypass overridden Map keys methods

When an interpolated value is a Map subclass that overrides keys(), this call dispatches into application code while the frame is paused. An override that mutates state or throws therefore changes the application or turns the segment into an evaluation error, whereas util.inspect renders the same Map without calling the override; iterate with the intrinsic Map.prototype.keys instead.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos debugger Dynamic Instrumentation & Live Debugger semver-patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants