Skip to content

Add system-tests for API Security Testing - Headers collection RFC#6915

Merged
christophe-papazian merged 6 commits into
mainfrom
christophe-papazian/api-security-testing-headers-collection
May 15, 2026
Merged

Add system-tests for API Security Testing - Headers collection RFC#6915
christophe-papazian merged 6 commits into
mainfrom
christophe-papazian/api-security-testing-headers-collection

Conversation

@christophe-papazian
Copy link
Copy Markdown
Contributor

@christophe-papazian christophe-papazian commented May 13, 2026

APPSEC-63235

Summary

System-tests for the API Security Testing — Headers collection RFC. Tracers must tag the x-datadog-endpoint-scan and x-datadog-security-test request headers on service entry spans as http.request.headers.<name> unconditionally (regardless of DD_TRACE_HEADER_TAGS or AppSec being enabled), and must not propagate them to downstream services.

Reference tracer implementation (Python): DataDog/dd-trace-py#18049.

Tests added

tests/appsec/api_security_testing/test_headers_collection.py::Test_SecurityTestingHeaders, three test methods:

  • test_collected_when_present — both headers tagged on the entry span.
  • test_absent_when_not_in_request — no tags set when the headers are not in the request.
  • test_not_propagated_downstream/make_distant_call is used to assert the headers do not appear in the outbound request (inspects the request_headers returned in the JSON response).

Every test starts with a positive-collection check on the request under test, so the class fails entirely when a tracer has not implemented the RFC (no absence/non-propagation test silently passing).

Scenarios

The class is stacked on three scenarios to cover the unconditional contract on three orthogonal axes:

  • @scenarios.default — AppSec on.
  • @scenarios.everything_disabled — AppSec off.
  • @scenarios.library_conf_custom_header_tags — AppSec on, DD_TRACE_HEADER_TAGS set to unrelated headers.

Other changes

  • New @features.api_security_testing_headers_collection decorator (feature-parity id 556, owner asm).
  • missing_feature manifest entries added for java, python, nodejs, php, golang, ruby, dotnet, rust. cpp.yml is intentionally skipped (only parametric tests run there per its own header comment); proxy/lambda/otel manifests are not in scope (the test runs only in the three scenarios above).

Verify that tracers tag x-datadog-endpoint-scan and x-datadog-security-test
on service entry spans as http.request.headers.<name> unconditionally, and
do not propagate them to downstream services.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

CODEOWNERS have been resolved as:

tests/appsec/api_security_testing/__init__.py                           @DataDog/asm-libraries @DataDog/system-tests-core
tests/appsec/api_security_testing/test_headers_collection.py            @DataDog/asm-libraries @DataDog/system-tests-core
manifests/cpp_nginx.yml                                                 @DataDog/dd-trace-cpp
manifests/dotnet.yml                                                    @DataDog/apm-dotnet @DataDog/asm-dotnet
manifests/envoy.yml                                                     @DataDog/system-tests-core
manifests/golang.yml                                                    @DataDog/dd-trace-go-guild
manifests/haproxy.yml                                                   @DataDog/system-tests-core
manifests/java.yml                                                      @DataDog/asm-java @DataDog/apm-java
manifests/nodejs.yml                                                    @DataDog/dd-trace-js
manifests/php.yml                                                       @DataDog/apm-php @DataDog/asm-php
manifests/python.yml                                                    @DataDog/apm-python @DataDog/asm-python
manifests/ruby.yml                                                      @DataDog/ruby-guild @DataDog/asm-ruby
manifests/rust.yml                                                      @DataDog/apm-rust
utils/_features.py                                                      @DataDog/system-tests-core

@datadog-official
Copy link
Copy Markdown

datadog-official Bot commented May 13, 2026

Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

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

christophe-papazian and others added 2 commits May 13, 2026 14:48
Mark Test_SecurityTestingHeaders as irrelevant in cpp_nginx, envoy and
haproxy manifests. These proxy manifests don't have a tests/appsec/
catch-all (unlike cpp_httpd and cpp_kong), so the test class was being
collected on cpp_nginx. The RFC targets tracer libraries, not proxies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christophe-papazian christophe-papazian marked this pull request as ready for review May 13, 2026 13:24
@christophe-papazian christophe-papazian requested review from a team as code owners May 13, 2026 13:24
@christophe-papazian christophe-papazian requested review from claponcet, jandro996, mhlidd, rithikanarayan and wconti27 and removed request for a team May 13, 2026 13:24
gh-worker-dd-mergequeue-cf854d Bot pushed a commit to DataDog/dd-trace-py that referenced this pull request May 15, 2026
#18049)

APPSEC-62412

## Summary

Tags two new Datadog markers — `x-datadog-endpoint-scan` and `x-datadog-security-test` — on every span that goes through `set_http_meta`, as `http.request.headers.<name>`. Collection is unconditional: it happens regardless of `DD_TRACE_HEADER_TAGS` or AppSec being enabled. Scope intentionally matches the existing user-agent/referrer extraction.

These let the API endpoint reducer distinguish Datadog scan/test traffic from real user traffic and keep it out of the API inventory.

The dd-style tag name (`http.request.headers.<name>`) is what dd-trace-py emits; the OTel-style variant (`http.request.header.<name>`) is handled by the reducer, not by tracers.

RFC: [Security Testing: Trace Attribution for Inventory Enrichment and Pollution Prevention](https://docs.google.com/document/d/1uR4QQvU8pItEV2zFqr3-L6jO2jxzmvLrFTX_yyvqIOA)

## Test plan

- [x] Unit tests in `tests/tracer/test_trace_utils.py::TestHeaders` (5 new): unconditional collection, absent, case-sensitive lookup, empty-value, non-propagation via `HTTPPropagator.inject`
- [x] System tests: DataDog/system-tests#6915

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: christophe.papazian <christophe.papazian@datadoghq.com>
@e-n-0
Copy link
Copy Markdown
Member

e-n-0 commented May 15, 2026

@codex review

Copy link
Copy Markdown

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

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: ef71ab9685

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread tests/appsec/api_security_testing/test_headers_collection.py Outdated
Copy link
Copy Markdown
Member

@e-n-0 e-n-0 left a comment

Choose a reason for hiding this comment

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

LGTM, but please look at the Codex comment!

christophe-papazian and others added 3 commits May 15, 2026 14:25
The previous `or {}` defensive guard converted a null request_headers
(serialized by some weblogs on inner-request errors) into an empty
header set, which trivially passes the absence assertions. Assert the
inner /make_distant_call status_code is 200 and request_headers is
non-null before checking the security testing headers are absent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christophe-papazian christophe-papazian merged commit 9777e7b into main May 15, 2026
449 checks passed
@christophe-papazian christophe-papazian deleted the christophe-papazian/api-security-testing-headers-collection branch May 15, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants