Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion manifests/agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ manifest:
tests/appsec/smoke_tests/test_apm_standalone.py:
- component_version: "<7.77.0-0"
declaration: irrelevant (APM Standalone option was added in 7.77.0)
tests/cws/test_thread_context_sharing.py::Test_ThreadContextSharing: bug (APPSEC-70532)
tests/cws/test_thread_context_sharing.py::Test_ThreadContextSharing:
- declaration: missing_feature (Trace collection not available in agents pre 7.84)
component_version: '<7.84.0-devel'
tests/debugger/test_debugger_condition_errors.py::Test_Debugger_Invalid_Condition_DSL:
- component_version: "<7.77.1"
weblog_declaration:
Expand Down
5 changes: 4 additions & 1 deletion manifests/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,10 @@ manifest:
tests/auto_inject/test_auto_inject_install.py::TestContainerAutoInjectInstallScriptAppsec: *ref_5_43_0
tests/auto_inject/test_auto_inject_install.py::TestHostAutoInjectInstallScriptAppsec: *ref_5_43_0
tests/auto_inject/test_auto_inject_install.py::TestSimpleInstallerAutoInjectManualAppsec: *ref_5_43_0
tests/cws/test_thread_context_sharing.py::Test_ThreadContextSharing: missing_feature (missing /security/thread_context_sharing endpoint on weblog)
tests/cws/test_thread_context_sharing.py::Test_ThreadContextSharing:
- weblog_declaration:
"*": irrelevant (requires AsyncContextFrame, Node.js 22.9+; covered on fastify)
fastify: *ref_4_1_0
tests/debugger/test_debugger_capture_expressions.py::Test_Debugger_Line_Capture_Expressions:
- weblog_declaration:
"*": irrelevant
Expand Down
32 changes: 32 additions & 0 deletions mirror_images.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,18 @@ images:
digest: sha256:b71678692a476b6acc3eb235edbb98bbb9c6b943e17c246ecb24937276807bc3
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:django-py3.13.base-d8262a2c816c
tag: django-py3.13.base-d8262a2c816c
datadog/system-tests:express4-typescript.base-5a66898a3a49:
digest: sha256:9e5fd36cdd73416a07c690fc3d11ca6feef6988cb1b882de4ef1de4d594eee24
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express4-typescript.base-5a66898a3a49
tag: express4-typescript.base-5a66898a3a49
datadog/system-tests:express4-typescript.base-eb800c09d602:
digest: sha256:4c1359af1571b63dfcb95471fb9fa6a368329368ab5b51d755f35a347161e388
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express4-typescript.base-eb800c09d602
tag: express4-typescript.base-eb800c09d602
datadog/system-tests:express4.base-93dbfc9a5699:
digest: sha256:96a80f92a127af451ac5a1f2324ba2d22a3def21f8c70bd3e250ae6729169115
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express4.base-93dbfc9a5699
tag: express4.base-93dbfc9a5699
datadog/system-tests:express4.base-cb2b80abf6d1:
digest: sha256:06f818aebeadbcaf9614e5f9b75f388b98afe0903b458be96ee1aa7c47aae9b3
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express4.base-cb2b80abf6d1
Expand All @@ -178,6 +186,10 @@ images:
digest: sha256:89561e1d8fa4a4effbb68f840847454c11249f3d0b4e4f4fb1e7f954dc7a095f
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express5.base-3ef9e2c68c47
tag: express5.base-3ef9e2c68c47
datadog/system-tests:express5.base-6df40f6a8621:
digest: sha256:8221ab40116f5421ff278df706c3d20a8c1146a4687222f1ef76dc401b96bd83
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:express5.base-6df40f6a8621
tag: express5.base-6df40f6a8621
datadog/system-tests:fastapi.base-1795d4d88178:
digest: sha256:bf65195d25f6e0d663c0f414590471fba7f18b1a0e3d284dda0cbd1896bea9a0
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastapi.base-1795d4d88178
Expand All @@ -186,10 +198,22 @@ images:
digest: sha256:f72a31702ffaabc1ba5e43042963e9cea965d1be6256d9d8a58e7e2381090d40
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastapi.base-2917769b3665
tag: fastapi.base-2917769b3665
datadog/system-tests:fastify.base-9613346d64d0:
digest: sha256:a4fa8c8c475c3d854a935bc753c1b13f774459f5d79b2712486d637e8659356f
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastify.base-9613346d64d0
tag: fastify.base-9613346d64d0
datadog/system-tests:fastify.base-9dddb89b99c4:
digest: sha256:e09ccb29386b7ae3cfd07e99cf11a532d0ccd14bf7b6b5415199fc96d79799c5
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastify.base-9dddb89b99c4
tag: fastify.base-9dddb89b99c4
datadog/system-tests:fastify.base-bce27c61b3f5:
digest: sha256:984e566d8eb604d53c1532a55559549f4c443ac73caf41664bb73241e529357c
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastify.base-bce27c61b3f5
tag: fastify.base-bce27c61b3f5
datadog/system-tests:fastify.base-edcf078de5d9:
digest: sha256:07f1aa403fa5be8ea02687fda1c9cd58f25dc02939be00762240a74fad3e4db5
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:fastify.base-edcf078de5d9
tag: fastify.base-edcf078de5d9
datadog/system-tests:flask-poc.base-fa81f4f89ea4:
digest: sha256:f300cff471470574ce8263292f54ab745ffacfa8af741dd41be15a8c947e2e0e
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:flask-poc.base-fa81f4f89ea4
Expand All @@ -210,6 +234,10 @@ images:
digest: sha256:2b09f33c61b2b19f4a239e4d8f10164ece66d925b72337720998ce43d7090d2f
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:lambda-proxy-v1
tag: lambda-proxy-v1
datadog/system-tests:nextjs.base-312a008bf0e8:
digest: sha256:e7c6ccd084c27819ea41b0ca2c2a03b6b372c18f2c8ac4cac2891fe9d1e54661
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:nextjs.base-312a008bf0e8
tag: nextjs.base-312a008bf0e8
datadog/system-tests:nextjs.base-95582a903467:
digest: sha256:128b7524cde00a739246166feef66b0d512388005dc125b0f11034555a8b6a70
target: registry.ddbuild.io/system-tests/mirror/datadog/system-tests:nextjs.base-95582a903467
Expand Down Expand Up @@ -454,6 +482,10 @@ images:
digest: sha256:c610fcdfb1d5b4740dd70c284ed3cb16bb857e0f7166196e36a5501df7a3aa32
target: registry.ddbuild.io/system-tests/mirror/node:22-alpine
tag: 22-alpine
node:24-alpine:
digest: sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1
target: registry.ddbuild.io/system-tests/mirror/node:24-alpine
tag: 24-alpine
otel/opentelemetry-collector-contrib:0.137.0:
digest: sha256:886722fe0f37af9d1fe24d29529253ec59fbf263b3b1df4facaf221373e19d23
target: registry.ddbuild.io/system-tests/mirror/otel/opentelemetry-collector-contrib:0.137.0
Expand Down
9 changes: 9 additions & 0 deletions mirror_images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,25 @@
- "datadog/system-tests:apache-mod-8.2.base-d1aeacb6306a"
- "datadog/system-tests:django-poc.base-78e2159815b1"
- "datadog/system-tests:django-py3.13.base-d8262a2c816c"
- "datadog/system-tests:express4-typescript.base-5a66898a3a49"
- "datadog/system-tests:express4-typescript.base-eb800c09d602"
- "datadog/system-tests:express4.base-93dbfc9a5699"
- "datadog/system-tests:express4.base-cb2b80abf6d1"
- "datadog/system-tests:express5.base-3ef9e2c68c47"
- "datadog/system-tests:express5.base-6df40f6a8621"
- "datadog/system-tests:fastapi.base-1795d4d88178"
- "datadog/system-tests:fastapi.base-2917769b3665"
- "datadog/system-tests:fastify.base-9613346d64d0"
- "datadog/system-tests:fastify.base-9dddb89b99c4"
- "datadog/system-tests:fastify.base-bce27c61b3f5"
- "datadog/system-tests:fastify.base-edcf078de5d9"
- "datadog/system-tests:fastify.base-f42683fff2b3"
- "datadog/system-tests:flask-poc.base-fa81f4f89ea4"
- "datadog/system-tests:golang_buddy-v2"
- "datadog/system-tests:java-lambda-runtime.base-e849230b09df"
- "datadog/system-tests:java_buddy-v1"
- "datadog/system-tests:lambda-proxy-v1"
- "datadog/system-tests:nextjs.base-312a008bf0e8"
- "datadog/system-tests:nextjs.base-95582a903467"
- "datadog/system-tests:nodejs_buddy-v1"
- "datadog/system-tests:openai-py.base-b4fd56aee3f2"
Expand Down Expand Up @@ -121,6 +129,7 @@
- "node:18-alpine"
- "node:20-alpine"
- "node:22-alpine"
- "node:24-alpine"
- "otel/opentelemetry-collector-contrib:0.137.0"
- "postgres:alpine"
- "public.ecr.aws/lambda/java:17"
Expand Down
10 changes: 5 additions & 5 deletions utils/build/docker/base-images.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"version": 1,
"images": {
"system_tests_base_java_lambda_java_lambda_runtime": "datadog/system-tests:java-lambda-runtime.base-e849230b09df",
"system_tests_base_nodejs_express4": "datadog/system-tests:express4.base-cb2b80abf6d1",
"system_tests_base_nodejs_express4_typescript": "datadog/system-tests:express4-typescript.base-eb800c09d602",
"system_tests_base_nodejs_express5": "datadog/system-tests:express5.base-3ef9e2c68c47",
"system_tests_base_nodejs_fastify": "datadog/system-tests:fastify.base-bce27c61b3f5",
"system_tests_base_nodejs_nextjs": "datadog/system-tests:nextjs.base-95582a903467",
"system_tests_base_nodejs_express4": "datadog/system-tests:express4.base-93dbfc9a5699",
"system_tests_base_nodejs_express4_typescript": "datadog/system-tests:express4-typescript.base-5a66898a3a49",
"system_tests_base_nodejs_express5": "datadog/system-tests:express5.base-6df40f6a8621",
"system_tests_base_nodejs_fastify": "datadog/system-tests:fastify.base-f42683fff2b3",
"system_tests_base_nodejs_nextjs": "datadog/system-tests:nextjs.base-312a008bf0e8",
"system_tests_base_php_apache_mod_7_0": "datadog/system-tests:apache-mod-7.0.base-8c8102938177",
"system_tests_base_php_apache_mod_7_0_zts": "datadog/system-tests:apache-mod-7.0-zts.base-01cc5715b403",
"system_tests_base_php_apache_mod_7_1": "datadog/system-tests:apache-mod-7.1.base-96cd329b60b0",
Expand Down
17 changes: 17 additions & 0 deletions utils/build/docker/nodejs/express/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,23 @@ app.get('/make_distant_call', (req, res) => {
request.end()
})

app.get('/security/thread_context_sharing', (req, res) => {
const path = req.query.path
if (typeof path !== 'string' || path === '') {
return res.status(400).send('missing path query parameter')
}

// Synchronous on purpose: async fs opens the file on a libuv worker thread, which does not carry
// the request's thread context that the security agent reads.
fs.writeFileSync(path, 'thread context sharing')

const context = tracer.scope().active().context()
res.json({
trace_id: BigInt(`0x${context.toTraceId(true)}`).toString(),
span_id: context.toSpanId()
})
})

app.get('/user_login_success_event', (req, res) => {
const userId = req.query.event_user_id || 'system_tests_user'

Expand Down
18 changes: 18 additions & 0 deletions utils/build/docker/nodejs/express4-typescript/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,24 @@ app.get("/make_distant_call", (req: Request, res: Response) => {
request.end()
})

app.get("/security/thread_context_sharing", (req: Request, res: Response) => {
const path = req.query.path;
if (typeof path !== "string" || path === "") {
res.status(400).send("missing path query parameter");
return;
}

// Synchronous on purpose: async fs opens the file on a libuv worker thread, which does not carry
// the request's thread context that the security agent reads.
require("fs").writeFileSync(path, "thread context sharing");

const context = tracer.scope().active().context();
res.json({
trace_id: BigInt(`0x${context.toTraceId(true)}`).toString(),
span_id: context.toSpanId()
});
});

app.get("/user_login_success_event", (req: Request, res: Response) => {
const userId = req.query.event_user_id || "system_tests_user";

Expand Down
4 changes: 4 additions & 0 deletions utils/build/docker/nodejs/fastify.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ CMD ./app.sh
COPY utils/build/docker/nodejs/install_ddtrace.sh binaries* /binaries/
RUN /binaries/install_ddtrace.sh && rm -rf /root/.bun
ENV DD_TRACE_HEADER_TAGS=user-agent
# TEMPORARY (do not merge): run the thread context writer end to end on Node.js 24.
ENV DD_TRACE_OTEL_CTX_ENABLED=true
# TEMPORARY (do not merge): Node.js 22 control run, AsyncContextFrame needs the flag.
ENV NODE_OPTIONS=--experimental-async-context-frame
24 changes: 21 additions & 3 deletions utils/build/docker/nodejs/fastify/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ fastify.get('/make_distant_call', async (request, reply) => {
resolve({
url,
status_code: response.statusCode,
request_headers: response.req._headers,
request_headers: response.req.getHeaders(),
response_headers: response.headers,
response_body: responseBody
})
Expand All @@ -273,6 +273,24 @@ fastify.get('/make_distant_call', async (request, reply) => {
})
})

fastify.get('/security/thread_context_sharing', async (request, reply) => {
const path = request.query.path
if (typeof path !== 'string' || path === '') {
reply.status(400)
return 'missing path query parameter'
}

// Synchronous on purpose: async fs opens the file on a libuv worker thread, which does not carry
// the request's thread context that the security agent reads.
require('fs').writeFileSync(path, 'thread context sharing')

const context = tracer.scope().active().context()
return {
trace_id: BigInt(`0x${context.toTraceId(true)}`).toString(),
span_id: context.toSpanId()
}
})

fastify.get('/user_login_success_event', async (request, reply) => {
const userId = request.query.event_user_id || 'system_tests_user'

Expand Down Expand Up @@ -681,7 +699,7 @@ fastify.get('/otel_drop_in_baggage_api_otel', async (request, reply) => {
resolve({
url,
status_code: response.statusCode,
request_headers: response.req._headers,
request_headers: response.req.getHeaders(),
response_headers: response.headers,
response_body: responseBody
})
Expand Down Expand Up @@ -743,7 +761,7 @@ fastify.get('/otel_drop_in_baggage_api_datadog', async (request, reply) => {
resolve({
url,
status_code: response.statusCode,
request_headers: response.req._headers,
request_headers: response.req.getHeaders(),
response_headers: response.headers,
response_body: responseBody
})
Expand Down
1 change: 1 addition & 0 deletions utils/build/docker/nodejs/nextjs.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ EXPOSE 7777
# Refresh the application route and dependencies baked into the base image.
COPY utils/build/docker/nodejs/nextjs/package.json utils/build/docker/nodejs/nextjs/bun.lock ./
COPY utils/build/docker/nodejs/nextjs/src/app/ffe ./src/app/ffe
COPY utils/build/docker/nodejs/nextjs/src/app/security ./src/app/security
RUN rm -rf node_modules \
&& bun install --frozen-lockfile --network-concurrency 8 --linker=hoisted

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NextResponse } from 'next/server'
import { writeFileSync } from 'fs'

export const dynamic = 'force-dynamic'

export async function GET (request) {
const path = request.nextUrl.searchParams.get('path')
if (!path) {
return new NextResponse('missing path query parameter', { status: 400 })
}

// Synchronous on purpose: async fs opens the file on a libuv worker thread, which does not carry
// the request's thread context that the security agent reads.
writeFileSync(path, 'thread context sharing')

const context = global._ddtrace.scope().active().context()
return NextResponse.json({
trace_id: BigInt(`0x${context.toTraceId(true)}`).toString(),
span_id: context.toSpanId()
})
}
29 changes: 27 additions & 2 deletions utils/build/docker/nodejs/weblog_metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ express5:
categories: [dd_trace]
fastify:
build_mode: local
supported_scenarios: &framework_scenarios
supported_scenarios:
- DEFAULT
- APPSEC_API_SECURITY
- APPSEC_API_SECURITY_NO_RESPONSE_BODY
Expand All @@ -51,9 +51,34 @@ fastify:
- APPSEC_STANDALONE_RASP
- IAST_DEDUPLICATION
- IAST_STANDALONE
- THREAD_CONTEXT_SHARING
nextjs:
build_mode: local
supported_scenarios: *framework_scenarios
supported_scenarios:
- DEFAULT
- APPSEC_API_SECURITY
- APPSEC_API_SECURITY_NO_RESPONSE_BODY
- APPSEC_API_SECURITY_RC
- APPSEC_API_SECURITY_WITH_SAMPLING
- APPSEC_APM_STANDALONE
- APPSEC_ATO_SDK
- APPSEC_AUTO_EVENTS_EXTENDED
- APPSEC_AUTO_EVENTS_RC
- APPSEC_BLOCKING
- APPSEC_BLOCKING_FULL_DENYLIST
- APPSEC_LOW_WAF_TIMEOUT
- APPSEC_RASP
- APPSEC_RASP_NON_BLOCKING
- APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_MAX
- APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_SAMPLE_RATE
- APPSEC_RATE_LIMITER
- APPSEC_RUNTIME_ACTIVATION
- APPSEC_STANDALONE
- APPSEC_STANDALONE_API_SECURITY
- APPSEC_STANDALONE_APM_STANDALONE
- APPSEC_STANDALONE_RASP
- IAST_DEDUPLICATION
- IAST_STANDALONE
uds-express4:
build_mode: local
supported_scenarios:
Expand Down
Loading