Repository navigation
Fix partial query redaction caused by encoded ampersands - #12995
Conversation
06ff9e2 to
476c2f9
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
476c2f9 to
9d71c1f
Compare
|
@DataDog review |
HTTP client spans tagged http.query with the decoded query, so an encoded %26 in a value became a literal '&'. Sensitive parameter redaction stopped there, exposing the remainder in http.query and http.url. Preserve %26 and %23 when decoding queries to retain parameter and fragment boundaries. Apply this to client spans and to server spans when http.server.raw.query-string=false and raw queries are available.
9d71c1f to
627effe
Compare
|
@DataDog review |
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
There was a problem hiding this comment.
More details
Focused generated-query checks supported correct delimiter preservation across Java 21 and Java 8 decoder behavior, including bracketed queries. The completed static review returned no actionable findings.
🤖 Bits Code Review · Commit 627effe
|
/merge |
|
View all feedbacks in Devflow UI.
The expected merge time in
|
Preserve the query delimiter redaction fix from #12995 in the Datadog and OpenTelemetry URL extractors, retaining both branches' regression coverage.
Configure required settings for OpenTelemetry HTTP semantics:
- Http client error status codes default to 400-600 (instead of 400-500)
- The environment variable DD_TRACE_OTEL_SEMANTICS_ENABLED automatically configures the following
- OTEL_TRACES_EXPORTER=otlp
- DD_WRITER_TYPE=OtlpWriter
- DD_TRACE_SPAN_ATTRIBUTE_SCHEMA=v0
- DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED=false
Add the following tags:
http:
- http.request.method_original (OTel)
- server.address (OTel)
- server.port (OTel)
http.server:
- url.path (OTel)
- url.query (OTel)
- url.scheme (OTel)
mixins:
peer:
tags:
- network.peer.address (OTel)
- peer.port (DD) => network.peer.port (OTel)
Map peer port to the OTel network attribute
Fixup http tag conventions. Squash so we can edit the message
Implement OpenTelemetry HTTP client semantic conventions
Implement OpenTelemetry HTTP server semantic conventions
Test end-to-end OpenTelemetry HTTP client semantics
- Apache HTTP client
- Apache HTTP Async Client
- Google HTTP Client
- HttpURLConnection
- JAX-RS Client
- OkHttp
- Play WSClient
Test end-to-end OpenTelemetry HTTP server semantics
- Akka-Http Server
- JAX-RS Server
- Jersey Server
- Jetty
- Netty HTTP server
- Servlet
- Play HTTP server
- Ratpack HTTP server
- Spring MVC
- Spring WebFlux
- Tomcat
- Undertow
- Vert.x
PR feedback on logic/processing, avoiding tags definitions:
- Restore IP tags collection so it is opt-in. The DD->OTel tag mapping remains
- Restore query tags collection so it honors the user's query tag opt-out
- Improve OtelHttpSemantics.parsePort performance (especially since this can be influenced by a user)
- Stores the OTel http client span's "url.full" URL in a lazy wrapper so redaction and query removal only occur at export time
PR feedback on tag-conventions: Restore network.client.ip so it is not span-kind-neutral
PR feedback on tag-conventions: Fix the tag definitions of OTel server.port and server.address while keeping the span direction relationships correct
HTTP server spans:
- http.server: restore "http.hostname" => OTel "server.address"
- http.server: add standalone (OTel-only) "server.port"
HTTP client spans:
- outbound_peer: restore "peer.hostname" => OTel "server.address"
- outbound_peer: restore "peer.port" => OTel "server.port"
Polish: Update the obfuscator tag name for OpenTelemetry semantics to DDTags.HTTP_QUERY_OTEL_NAME, which mimics DDTags.HTTP_QUERY so we have one consistent tag name
Polish: Update setters to use IDs rather than tag names
Fix: Add regression tests for identified errors when enabling the opt-in changes, including:
HttpDecoratorsOtelSemanticsForkedTest.java
- Elasticsearch and OpenSearch spans should be unchanged
- There must not be duplicate attributes for client destination ports (server.port)
- InferredProxySpan should record server.port=443 due to the default https scheme
- When OTel semantics are enabled, Forwarded-header extraction should be run and determine client span attributes, even if DD_TRACE_CLIENT_IP_ENABLED=false or AppSec+AI Guard are disabled
- When OTel semantics are enabled, url.full (OTel equivalent of http.url) decodes the query before storing and sending to QueryObfuscator.
OtelHttpSemanticsTest.java
- When OTel semantics are enabled, url.full (OTel equivalent of http.url) decodes the query before storing and sending to QueryObfuscator.
HttpClientPathMappingOtelSemanticsForkedTest.java
- TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING takes precedence and replaces the http.route placeholder in the OTel HTTP server span name "{http.request.method} {http.route}"
LambdaHttpOtelSemanticsForkedTest.java & LambdaAppSecHandlerTest.java
- Lambda query tags should continue to be obfuscated
GatewayBridgeOtelSemanticsForkedTest.java
- API Security must continue to fall back to the http.url span attribute when the server span does not have an http.route span attribute
Fix: Implement fixes for the noted regressions
Fix: Address two issues identified by automated code review.
- QueryObfuscator: Obfuscate both the DD and OTel query string tags as a preventative measure to make sure we do not store an unobfuscated query string on a span. When OTel semantics mode is enabled, the OTel value will be take precedence as the final recorded value (the DD value will be discarded if present).
- Ensure that we record the correct origin port when handling forwarded schemes
fix linting issue
Apply spotless formatting
Fix: Address issues identified by automated code review:
- Correct obfuscated-query expectations
- Fix the IAST missing-HSTS detection by allowing it to also check the "url.scheme" OTel HTTP server tag to confirm HTTPS, since the "http.url" tag is only emitted with DD semantic conventions
PR feedback: Address the following issues:
- In the BaseDecorator.setPeerPort methods (used by both clients and servers), set the tag via the directionless KnownTags.PEER_PORT_ID key.
- In HttpServerDecorator, strip the query and fragment from the URL before setting the OTel attribute "url.path". Also, set the OTel attribute "url.query" if a query string is present
- In AxwayHTTPPluginDecorator make sure to honor the query opt-out before setting the OTel attribute "url.query"
PR Feedback: Remove DDTags.HTTP_QUERY_OTEL_NAME (public API) and use KnownTags.URL_QUERY_NAME (OTel "url.query") in its place
PR Feedback: Use the TagExtractor infrastructure to simplify setting the url-based tags on http clients and servers, for both Datadog and OTel semantics.
Key details include:
- HttpServerUrl is created as an abstract class to expose a consistent interface for accessing underlying URL facts from various request objects -- there is no equivalent for client spans as the logic is simple enough that operating on a URL object is sufficient
- OtelServerUrl and DatadogServerUrl implement TagExtractor<HttpServerUrl> to provide the "OTEL_SEMANTICS branching" for populating http server span tags
- DatadogClientUrl and OtelClientUrl implement TagExtractor<URI> to provide the "OTEL_SEMANTICS branching" for populating http client span tags
- The host and hostPort calculations from OtelHttpSemantics.setServerAddressAndPort are migrated to HttpServerUrl.Origin.resolve
- Additional logic from OtelHttpSemantics is ported to the new UrlExtractors, so a handful of tests in OtelHttpSemanticsTest.java are simply ported to HttpUrlExtractorsTest.java
- HttpUrlExtractorsTest.java provides testing of the TagExtractor implementations
Preserve default HTTP behavior with OTel semantics disabled
Preserve existing query concatenation for captured URLs with decoded
path characters when OTel semantics are disabled. Restore port-based
service splitting precedence and skip the OTel-only Host header lookup
in that mode.
Add regression coverage for all three issues. Each new regression failed
before the fixes; all 102 selected query obfuscator and decorator tests
now pass, including existing OTel and client path-mapping coverage.
Simplify HTTP URL string assembly
Use string concatenation and trailing substrings when inserting or removing queries while retaining fragments. Verify query obfuscation, HTTP semantics helpers, URL extractors, and OTel decorators with their existing tests and formatting checks.
Cleanup: Update tag-conventions to allow "http.query.string" (DD) to map to "url.query" (OTel), to simplify query obfuscation
Cleanup:
- Remove the unused origin caches in HttpServerUrl (only used once per request)
- Simplify inferred proxy resource naming
- Refactor the "FullUrl" extractor into URLConnection where it is exclusively used today
- In OtelHttpSemantics, reuse parseNonNegativeInt in the parsePort logic
- In HttpServerDecorator, avoid rereading a client IP from tags that were just set
- Add a shared URL fallback that GatewayBridge and HttpEndpointPostProcessor can use for getting the "http.url" first then "url.path" if null
- Inherit the OTEL_SEMANTICS boolean in AxwayHTTPPluginDecorator
- Clean upthe http client span resource name setting
Fix query obfuscator URL expectations for Datadog semantics
Commit 8a57978 added Datadog server and client cases while retaining the OTel-only expected URL. Datadog semantics deliberately append queries after the captured path to preserve decoded hash characters, as established by ba672e9.
Specify the expected URL per scenario while preserving query retention checks for both semantics modes. No production behavior changes.
Validation: reproduced 2 failures out of 34 cases before the fix; all 34 QueryObfuscatorTest cases pass after it. Ran :dd-trace-core:spotlessApply and git diff --check.
Keep Datadog and OpenTelemetry query tags separate
Aliasing url.query to http.query.string in the tag registry applies even
when OTel semantics are disabled. It changes exported tag names, merges
independently supplied values, and routes url.query through the legacy
query appender. A complete URL such as /orders?page=1 can consequently
become /orders?page=1?page=1.
These tags are not interchangeable: http.query.string feeds legacy URL
reconstruction, while url.query may accompany an already complete URL.
Keep distinct registry entries and have the OTel producers select
url.query explicitly, including the Lambda HTTP path.
Share redaction between the tags, process url.query only when OTel
semantics are enabled, and replace any existing query before the fragment
when rebuilding an OTel URL. Preserve the original URL concatenation and
leave separately supplied url.query tags untouched in default mode.
Validation: 891 selected query, registry, URL, HTTP decorator, Lambda and
OTLP tests passed. All 176 emitted-tag comparisons against local master
matched across eight default-mode query/raw-query/raw-resource settings.
Reduce retained memory in lazy OpenTelemetry client URLs
The lazy client URL wrapper kept its original URI after rendering, retaining
query data that was excluded from the exported URL even when query capture
was disabled. A 100,035-character input URI remained reachable through a
wrapper whose rendered URL was only 26 characters.
Cache the rendered URL and decoded path, then release the source URI. This
reduces retained heap after rendering while preserving deferred URL assembly
and redaction on the request path. It also avoids recomputing the URL when
get() is called directly more than once.
Publish the cached values before clearing the volatile URI reference so
concurrent readers can safely use either their local URI or the cached data.
Validation: 323 selected URL, query-obfuscation and HTTP semantics tests
passed, including repeated supplier/string reads and concurrent path reads
and rendering. The long-query probe confirms that the wrapper releases its
source URI after rendering with query capture disabled.
Fix server query tag assertions for OpenTelemetry semantics
Cover HTTP URL extractor edge cases
Fix query tag assertions for OpenTelemetry HTTP semantics
Simplify OpenTelemetry HTTP client resource name fallback
Merge origin/master into otel-http-semconv
Preserve the query delimiter redaction fix from #12995 in the Datadog and OpenTelemetry URL extractors, retaining both branches' regression coverage.
Co-authored-by: mcculls <stuart.mcculloch@datadoghq.com>
What Does This Do
Preserve
%26and%23in otherwise decoded query strings so encoded value characters retain their parameter and fragment boundaries. Apply this to HTTP client spans and to server spans whenhttp.server.raw.query-string=falseand raw queries are available.Motivation
Decoding
token=first%26SECOND_HALF&view=fullbefore redaction turned%26into a literal&, causing sensitive parameter redaction to stop early and exposeSECOND_HALFinhttp.queryandhttp.url. The query now becomes<redacted>&view=full, while encoded parameter names remain decoded for sensitive-name matching.Additional Notes
Java has used decoded client queries (
URI.getQuery()) since query tagging was introduced in 2019, before query obfuscation was added in 2022. The obfuscator can process raw queries, as other tracers do, but switching togetRawQuery()would change reported tag values and the input seen by custom obfuscation regexes. This fix preserves the existing decoded representation while retaining encoded delimiters, and continues to decode parameter names such ast%6fkenfor sensitive-name matching. Server spans already support raw queries; this change covers the explicitly decoded mode when raw queries are available.Formatting checks passed for
internal-api,dd-trace-core, andagent-bootstrap. Targeted tests passed:URIUtilsTestQueryObfuscatorTestHttpClientDecoratorTestandHttpServerDecoratorTestHttpClientQueryRedactionForkedTest, including assertions on the written span'shttp.queryandhttp.urlContributor Checklist