dd-trace 5.96.0 → 5.98.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +60 -2
- package/package.json +9 -7
- package/packages/datadog-esbuild/index.js +20 -9
- package/packages/datadog-instrumentations/src/child_process.js +7 -17
- package/packages/datadog-instrumentations/src/crypto.js +1 -2
- package/packages/datadog-instrumentations/src/cucumber.js +69 -4
- package/packages/datadog-instrumentations/src/cypress-config.js +318 -0
- package/packages/datadog-instrumentations/src/cypress.js +86 -4
- package/packages/datadog-instrumentations/src/dns.js +1 -2
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fs.js +27 -29
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
- package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
- package/packages/datadog-instrumentations/src/http/client.js +2 -3
- package/packages/datadog-instrumentations/src/http/server.js +2 -5
- package/packages/datadog-instrumentations/src/http2/client.js +1 -3
- package/packages/datadog-instrumentations/src/http2/server.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +117 -16
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +12 -1
- package/packages/datadog-instrumentations/src/net.js +2 -8
- package/packages/datadog-instrumentations/src/pino.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +1 -2
- package/packages/datadog-instrumentations/src/redis.js +12 -6
- package/packages/datadog-instrumentations/src/selenium.js +4 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/url.js +1 -3
- package/packages/datadog-instrumentations/src/vitest.js +5 -1
- package/packages/datadog-instrumentations/src/vm.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -4
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-cucumber/src/index.js +13 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +166 -6
- package/packages/datadog-plugin-cypress/src/index.js +59 -2
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +10 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +10 -2
- package/packages/datadog-plugin-jest/src/index.js +4 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +3 -3
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +10 -16
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/datadog-plugin-ws/src/close.js +1 -1
- package/packages/datadog-plugin-ws/src/receiver.js +1 -1
- package/packages/datadog-webpack/index.js +3 -3
- package/packages/dd-trace/index.js +12 -10
- package/packages/dd-trace/src/agent/url.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +26 -22
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
- package/packages/dd-trace/src/appsec/blocking.js +64 -33
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
- package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/config/defaults.js +315 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +9 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +587 -1496
- package/packages/dd-trace/src/config/parsers.js +256 -0
- package/packages/dd-trace/src/config/remote_config.js +59 -2
- package/packages/dd-trace/src/config/supported-configurations.json +406 -432
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
- package/packages/dd-trace/src/crashtracking/index.js +1 -7
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +12 -9
- package/packages/dd-trace/src/encode/0.4.js +8 -7
- package/packages/dd-trace/src/encode/span-stats.js +4 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
- package/packages/dd-trace/src/exporters/common/request.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +12 -2
- package/packages/dd-trace/src/heap_snapshots.js +3 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
- package/packages/dd-trace/src/llmobs/index.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
- package/packages/dd-trace/src/llmobs/sdk.js +12 -8
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +9 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
- package/packages/dd-trace/src/log/index.js +20 -59
- package/packages/dd-trace/src/log/writer.js +7 -19
- package/packages/dd-trace/src/noop/proxy.js +8 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +17 -2
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
- package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
- package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +75 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +66 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +332 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/opentracing/tracer.js +9 -4
- package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +11 -13
- package/packages/dd-trace/src/plugins/storage.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +22 -5
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +6 -88
- package/packages/dd-trace/src/process-tags/index.js +3 -0
- package/packages/dd-trace/src/profiler.js +27 -2
- package/packages/dd-trace/src/profiling/config.js +73 -241
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
- package/packages/dd-trace/src/profiling/profiler.js +78 -109
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
- package/packages/dd-trace/src/propagation-hash/index.js +2 -1
- package/packages/dd-trace/src/proxy.js +40 -6
- package/packages/dd-trace/src/remote_config/index.js +3 -0
- package/packages/dd-trace/src/require-package-json.js +8 -4
- package/packages/dd-trace/src/ritm.js +58 -26
- package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +18 -11
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/service-naming/index.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +17 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +11 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
- package/packages/dd-trace/src/span_stats.js +5 -1
- package/packages/dd-trace/src/standalone/index.js +3 -0
- package/packages/dd-trace/src/telemetry/index.js +2 -3
- package/packages/dd-trace/src/telemetry/send-data.js +5 -19
- package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
- package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
- package/packages/dd-trace/src/tracer.js +2 -2
- package/packages/dd-trace/src/util.js +0 -9
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
- package/vendor/dist/protobufjs/index.js +1 -1
- package/packages/dd-trace/src/log/utils.js +0 -16
|
@@ -32,7 +32,7 @@ class PGPlugin extends DatabasePlugin {
|
|
|
32
32
|
span.setTag('db.stream', 1)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
query.__ddInjectableQuery = this.injectDbmQuery(span, query.text, service, !!query.name)
|
|
35
|
+
query.__ddInjectableQuery = this.injectDbmQuery(span, query.text, service.name, !!query.name)
|
|
36
36
|
|
|
37
37
|
return ctx.currentStore
|
|
38
38
|
}
|
|
@@ -28,7 +28,7 @@ class TediousPlugin extends DatabasePlugin {
|
|
|
28
28
|
|
|
29
29
|
// SQL Server includes comments when caching queries
|
|
30
30
|
// For that reason we allow service mode but not full mode
|
|
31
|
-
ctx.sql = this.injectDbmQuery(span, ctx.queryOrProcedure, service, true)
|
|
31
|
+
ctx.sql = this.injectDbmQuery(span, ctx.queryOrProcedure, service.name, true)
|
|
32
32
|
return ctx.currentStore
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -47,7 +47,7 @@ class WSClosePlugin extends TracingPlugin {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (isPeerClose && traceWebsocketMessagesInheritSampling && traceWebsocketMessagesSeparateTraces) {
|
|
50
|
-
span.setTag('_dd.dm.service', spanTags['service.name'] || service)
|
|
50
|
+
span.setTag('_dd.dm.service', spanTags['service.name'] || service.name)
|
|
51
51
|
span.setTag('_dd.dm.resource', spanTags['resource.name'] || `websocket ${path}`)
|
|
52
52
|
span.setTag('_dd.dm.inherited', 1)
|
|
53
53
|
}
|
|
@@ -48,7 +48,7 @@ class WSReceiverPlugin extends TracingPlugin {
|
|
|
48
48
|
}, ctx)
|
|
49
49
|
|
|
50
50
|
if (traceWebsocketMessagesInheritSampling && traceWebsocketMessagesSeparateTraces) {
|
|
51
|
-
span.setTag('_dd.dm.service', spanTags['service.name'] || service)
|
|
51
|
+
span.setTag('_dd.dm.service', spanTags['service.name'] || service.name)
|
|
52
52
|
span.setTag('_dd.dm.resource', spanTags['resource.name'] || `websocket ${path}`)
|
|
53
53
|
span.setTag('_dd.dm.inherited', 1)
|
|
54
54
|
}
|
|
@@ -21,12 +21,12 @@ for (const hook of Object.values(hooks)) {
|
|
|
21
21
|
|
|
22
22
|
const modulesOfInterest = new Set()
|
|
23
23
|
|
|
24
|
-
for (const instrumentation of Object.
|
|
24
|
+
for (const [name, instrumentation] of Object.entries(instrumentations)) {
|
|
25
25
|
for (const entry of instrumentation) {
|
|
26
26
|
if (entry.file) {
|
|
27
|
-
modulesOfInterest.add(`${
|
|
27
|
+
modulesOfInterest.add(`${name}/${entry.file}`) // e.g. "redis/my/file.js"
|
|
28
28
|
} else {
|
|
29
|
-
modulesOfInterest.add(
|
|
29
|
+
modulesOfInterest.add(name) // e.g. "redis"
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
if (!global._ddtrace) {
|
|
4
|
-
const TracerProxy = require('./src')
|
|
5
|
-
|
|
6
|
-
Object.defineProperty(global, '_ddtrace', {
|
|
7
|
-
value: new TracerProxy(),
|
|
8
|
-
enumerable: false,
|
|
9
|
-
configurable: true,
|
|
10
|
-
writable: true,
|
|
11
|
-
})
|
|
12
|
-
|
|
13
4
|
const ddTraceSymbol = Symbol.for('dd-trace')
|
|
14
5
|
|
|
6
|
+
// Set up beforeExitHandlers before loading the tracer so that modules loaded
|
|
7
|
+
// during require('./src') can register handlers.
|
|
15
8
|
Object.defineProperty(globalThis, ddTraceSymbol, {
|
|
16
9
|
value: {
|
|
17
10
|
beforeExitHandlers: new Set(),
|
|
18
11
|
},
|
|
19
12
|
enumerable: false,
|
|
20
|
-
configurable: true,
|
|
13
|
+
configurable: true,
|
|
21
14
|
writable: false,
|
|
22
15
|
})
|
|
23
16
|
|
|
@@ -29,6 +22,15 @@ if (!global._ddtrace) {
|
|
|
29
22
|
}
|
|
30
23
|
})
|
|
31
24
|
|
|
25
|
+
const TracerProxy = require('./src')
|
|
26
|
+
|
|
27
|
+
Object.defineProperty(global, '_ddtrace', {
|
|
28
|
+
value: new TracerProxy(),
|
|
29
|
+
enumerable: false,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
})
|
|
33
|
+
|
|
32
34
|
global._ddtrace.default = global._ddtrace
|
|
33
35
|
global._ddtrace.tracer = global._ddtrace
|
|
34
36
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { URL, format } = require('url')
|
|
4
|
-
const defaults = require('../config/defaults')
|
|
4
|
+
const { defaults } = require('../config/defaults')
|
|
5
5
|
|
|
6
6
|
module.exports = { getAgentUrl }
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ module.exports = { getAgentUrl }
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Gets the agent URL from config, constructing it from hostname/port if needed
|
|
15
|
-
* @param {
|
|
15
|
+
* @param {Partial<import('../config/config-base')>} config - Tracer configuration object
|
|
16
16
|
* @returns {URL} The agent URL
|
|
17
17
|
*/
|
|
18
18
|
function getAgentUrl (config) {
|
|
@@ -25,11 +25,12 @@ const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
|
|
|
25
25
|
const ALLOW = 'ALLOW'
|
|
26
26
|
|
|
27
27
|
class AIGuardAbortError extends Error {
|
|
28
|
-
constructor (reason, tags, sds) {
|
|
28
|
+
constructor (reason, tags, tagProbs, sds) {
|
|
29
29
|
super(reason)
|
|
30
30
|
this.name = 'AIGuardAbortError'
|
|
31
31
|
this.reason = reason
|
|
32
32
|
this.tags = tags
|
|
33
|
+
this.tagProbabilities = tagProbs
|
|
33
34
|
this.sds = sds || []
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -57,6 +58,10 @@ class AIGuard extends NoopAIGuard {
|
|
|
57
58
|
#maxContentSize
|
|
58
59
|
#meta
|
|
59
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @param {import('../tracer')} tracer - Tracer instance
|
|
63
|
+
* @param {import('../config/config-base')} config - Tracer configuration
|
|
64
|
+
*/
|
|
60
65
|
constructor (tracer, config) {
|
|
61
66
|
super()
|
|
62
67
|
|
|
@@ -184,38 +189,37 @@ class AIGuard extends NoopAIGuard {
|
|
|
184
189
|
`AI Guard service call failed, status ${response.status}`,
|
|
185
190
|
{ errors: response.body?.errors })
|
|
186
191
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const attr = response.body.data.attributes
|
|
190
|
-
if (!attr.action) {
|
|
191
|
-
throw new Error('Action missing from response')
|
|
192
|
-
}
|
|
193
|
-
action = attr.action
|
|
194
|
-
reason = attr.reason
|
|
195
|
-
tags = attr.tags
|
|
196
|
-
sdsFindings = attr.sds_findings || []
|
|
197
|
-
blockingEnabled = attr.is_blocking_enabled ?? false
|
|
198
|
-
} catch (e) {
|
|
192
|
+
const attr = response.body?.data?.attributes
|
|
193
|
+
if (!attr?.action) {
|
|
199
194
|
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
|
|
200
|
-
throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}
|
|
195
|
+
throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}`)
|
|
196
|
+
}
|
|
197
|
+
const action = attr.action
|
|
198
|
+
const reason = attr.reason
|
|
199
|
+
const tags = attr.tags ?? []
|
|
200
|
+
if (tags.length > 0) {
|
|
201
|
+
metaStruct.attack_categories = tags
|
|
201
202
|
}
|
|
203
|
+
const sdsFindings = attr.sds_findings ?? []
|
|
204
|
+
if (sdsFindings.length > 0) {
|
|
205
|
+
metaStruct.sds = sdsFindings
|
|
206
|
+
}
|
|
207
|
+
const tagProbabilities = attr.tag_probs ?? {}
|
|
208
|
+
if (attr.tag_probs) {
|
|
209
|
+
metaStruct.tag_probs = tagProbabilities
|
|
210
|
+
}
|
|
211
|
+
const blockingEnabled = attr.is_blocking_enabled ?? false
|
|
202
212
|
const shouldBlock = block && blockingEnabled && action !== ALLOW
|
|
203
213
|
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { action, error: false, block: shouldBlock }).inc(1)
|
|
204
214
|
span.setTag(AI_GUARD_ACTION_TAG_KEY, action)
|
|
205
215
|
if (reason) {
|
|
206
216
|
span.setTag(AI_GUARD_REASON_TAG_KEY, reason)
|
|
207
217
|
}
|
|
208
|
-
if (tags?.length > 0) {
|
|
209
|
-
metaStruct.attack_categories = tags
|
|
210
|
-
}
|
|
211
|
-
if (sdsFindings?.length > 0) {
|
|
212
|
-
metaStruct.sds = sdsFindings
|
|
213
|
-
}
|
|
214
218
|
if (shouldBlock) {
|
|
215
219
|
span.setTag(AI_GUARD_BLOCKED_TAG_KEY, 'true')
|
|
216
|
-
throw new AIGuardAbortError(reason, tags, sdsFindings)
|
|
220
|
+
throw new AIGuardAbortError(reason, tags, tagProbabilities, sdsFindings)
|
|
217
221
|
}
|
|
218
|
-
return { action, reason, tags, sds: sdsFindings }
|
|
222
|
+
return { action, reason, tags, tagProbabilities, sds: sdsFindings }
|
|
219
223
|
})
|
|
220
224
|
}
|
|
221
225
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @stylistic/max-len */
|
|
2
|
+
/* eslint-disable @stylistic/quotes */
|
|
2
3
|
'use strict'
|
|
3
4
|
|
|
4
|
-
const html =
|
|
5
|
+
const html = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>You've been blocked</title><style>a,body,div,html,span{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}body{background:-webkit-radial-gradient(26% 19%,circle,#fff,#f4f7f9);background:radial-gradient(circle at 26% 19%,#fff,#f4f7f9);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;width:100%;min-height:100vh;line-height:1;flex-direction:column}p{display:block}main{text-align:center;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;flex-direction:column}p{font-size:18px;line-height:normal;color:#646464;font-family:sans-serif;font-weight:400}a{color:#4842b7}footer{width:100%;text-align:center}footer p{font-size:16px}.security-response-id{font-size:14px;color:#999;margin-top:20px;font-family:monospace}</style></head><body><main><p>Sorry, you cannot access this page. Please contact the customer service team.</p><p class="security-response-id">Security Response ID: [security_response_id]</p></main><footer><p>Security provided by <a href="https://www.datadoghq.com/product/security-platform/application-security-monitoring/" target="_blank" rel="noopener noreferrer">Datadog</a></p></footer></body></html>`
|
|
5
6
|
|
|
6
|
-
const json =
|
|
7
|
+
const json = `{"errors":[{"title":"You've been blocked","detail":"Sorry, you cannot access this page. Please contact the customer service team. Security provided by Datadog."}],"security_response_id":"[security_response_id]"}`
|
|
7
8
|
|
|
8
|
-
const graphqlJson =
|
|
9
|
+
const graphqlJson = `{"errors":[{"message":"You've been blocked","extensions":{"detail":"Sorry, you cannot perform this operation. Please contact the customer service team. Security provided by Datadog."}}],"security_response_id":"[security_response_id]"}`
|
|
9
10
|
|
|
10
11
|
module.exports = {
|
|
11
12
|
html,
|
|
@@ -6,9 +6,27 @@ const { updateBlockFailureMetric } = require('./telemetry')
|
|
|
6
6
|
|
|
7
7
|
const detectedSpecificEndpoints = {}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const templateKeyword = '[security_response_id]'
|
|
10
|
+
|
|
11
|
+
const templates = {
|
|
12
|
+
html: {
|
|
13
|
+
body: null,
|
|
14
|
+
idIndex: -1,
|
|
15
|
+
type: 'text/html; charset=utf-8',
|
|
16
|
+
},
|
|
17
|
+
json: {
|
|
18
|
+
body: null,
|
|
19
|
+
idIndex: -1,
|
|
20
|
+
type: 'application/json',
|
|
21
|
+
},
|
|
22
|
+
graphqlJson: {
|
|
23
|
+
body: null,
|
|
24
|
+
idIndex: -1,
|
|
25
|
+
type: 'application/json',
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setTemplates()
|
|
12
30
|
|
|
13
31
|
let defaultBlockingActionParameters
|
|
14
32
|
|
|
@@ -17,7 +35,7 @@ const responseBlockedSet = new WeakSet()
|
|
|
17
35
|
const blockDelegations = new WeakMap()
|
|
18
36
|
|
|
19
37
|
const specificBlockingTypes = {
|
|
20
|
-
GRAPHQL: '
|
|
38
|
+
GRAPHQL: 'graphqlJson',
|
|
21
39
|
}
|
|
22
40
|
|
|
23
41
|
function getSpecificKey (method, url) {
|
|
@@ -33,21 +51,14 @@ function getBlockWithRedirectData (actionParameters) {
|
|
|
33
51
|
if (!statusCode || statusCode < 300 || statusCode >= 400) {
|
|
34
52
|
statusCode = 303
|
|
35
53
|
}
|
|
36
|
-
const headers = {
|
|
37
|
-
Location: actionParameters.location,
|
|
38
|
-
}
|
|
39
54
|
|
|
40
|
-
|
|
41
|
-
}
|
|
55
|
+
const headers = { Location: actionParameters.location }
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
case specificBlockingTypes.GRAPHQL:
|
|
46
|
-
return {
|
|
47
|
-
type: 'application/json',
|
|
48
|
-
body: templateGraphqlJson,
|
|
49
|
-
}
|
|
57
|
+
if (headers.Location) {
|
|
58
|
+
headers.Location = headers.Location.replace(templateKeyword, actionParameters.security_response_id ?? '')
|
|
50
59
|
}
|
|
60
|
+
|
|
61
|
+
return { headers, statusCode }
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
function getBlockWithContentData (req, specificType, actionParameters) {
|
|
@@ -56,7 +67,7 @@ function getBlockWithContentData (req, specificType, actionParameters) {
|
|
|
56
67
|
|
|
57
68
|
const specificBlockingType = specificType || detectedSpecificEndpoints[getSpecificKey(req.method, req.url)]
|
|
58
69
|
if (specificBlockingType) {
|
|
59
|
-
const specificBlockingContent =
|
|
70
|
+
const specificBlockingContent = getTemplate(specificBlockingType, actionParameters)
|
|
60
71
|
type = specificBlockingContent?.type
|
|
61
72
|
body = specificBlockingContent?.body
|
|
62
73
|
}
|
|
@@ -65,23 +76,17 @@ function getBlockWithContentData (req, specificType, actionParameters) {
|
|
|
65
76
|
// parse the Accept header, ex: Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
|
|
66
77
|
const accept = req.headers.accept?.split(',').map((str) => str.split(';', 1)[0].trim())
|
|
67
78
|
|
|
79
|
+
let templateName = 'json'
|
|
80
|
+
|
|
68
81
|
if (!actionParameters || actionParameters.type === 'auto') {
|
|
69
82
|
if (accept?.includes('text/html') && !accept.includes('application/json')) {
|
|
70
|
-
|
|
71
|
-
body = templateHtml
|
|
72
|
-
} else {
|
|
73
|
-
type = 'application/json'
|
|
74
|
-
body = templateJson
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
if (actionParameters.type === 'html') {
|
|
78
|
-
type = 'text/html; charset=utf-8'
|
|
79
|
-
body = templateHtml
|
|
80
|
-
} else {
|
|
81
|
-
type = 'application/json'
|
|
82
|
-
body = templateJson
|
|
83
|
+
templateName = 'html'
|
|
83
84
|
}
|
|
85
|
+
} else if (actionParameters.type === 'html') {
|
|
86
|
+
templateName = 'html'
|
|
84
87
|
}
|
|
88
|
+
|
|
89
|
+
({ type, body } = getTemplate(templateName, actionParameters))
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
const statusCode = actionParameters?.status_code || 403
|
|
@@ -164,12 +169,38 @@ function getBlockingAction (actions) {
|
|
|
164
169
|
return actions?.redirect_request || actions?.block_request
|
|
165
170
|
}
|
|
166
171
|
|
|
172
|
+
/**
|
|
173
|
+
* @param {import('../config/config-base')} [config] - Tracer configuration
|
|
174
|
+
*/
|
|
167
175
|
function setTemplates (config) {
|
|
168
|
-
|
|
176
|
+
templates.html.body = config?.appsec?.blockedTemplateHtml
|
|
177
|
+
templates.json.body = config?.appsec?.blockedTemplateJson
|
|
178
|
+
templates.graphqlJson.body = config?.appsec?.blockedTemplateGraphql
|
|
179
|
+
|
|
180
|
+
for (const type of Object.keys(templates)) {
|
|
181
|
+
const template = templates[type]
|
|
182
|
+
|
|
183
|
+
// set default template if not set by config
|
|
184
|
+
if (!template.body) template.body = blockedTemplates[type]
|
|
185
|
+
|
|
186
|
+
template.idIndex = template.body.indexOf(templateKeyword)
|
|
187
|
+
|
|
188
|
+
if (template.idIndex !== -1) {
|
|
189
|
+
template.body = [
|
|
190
|
+
template.body.slice(0, template.idIndex),
|
|
191
|
+
template.body.slice(template.idIndex + templateKeyword.length),
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getTemplate (type, actionParameters) {
|
|
198
|
+
const template = templates[type]
|
|
199
|
+
if (template.idIndex === -1) return template
|
|
169
200
|
|
|
170
|
-
|
|
201
|
+
const body = template.body[0] + (actionParameters?.security_response_id ?? '') + template.body[1]
|
|
171
202
|
|
|
172
|
-
|
|
203
|
+
return { body, type: template.type }
|
|
173
204
|
}
|
|
174
205
|
|
|
175
206
|
function isBlocked (res) {
|
|
@@ -168,7 +168,7 @@ class IastPlugin extends Plugin {
|
|
|
168
168
|
loadChannel.subscribe(this.onInstrumentationLoadedListener)
|
|
169
169
|
|
|
170
170
|
// check for already instrumented modules
|
|
171
|
-
for (const name
|
|
171
|
+
for (const name of Object.keys(instrumentations)) {
|
|
172
172
|
this._onInstrumentationLoaded(name)
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const log = require('../../../../log')
|
|
5
5
|
const vulnerabilities = require('../../vulnerabilities')
|
|
6
|
-
const defaults = require('../../../../config/defaults')
|
|
6
|
+
const { defaults } = require('../../../../config/defaults')
|
|
7
7
|
|
|
8
8
|
const { contains, intersects, remove } = require('./range-utils')
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto')
|
|
4
4
|
|
|
5
|
-
const defaults = require('../../../config/defaults')
|
|
5
|
+
const { defaults } = require('../../../config/defaults')
|
|
6
6
|
|
|
7
7
|
const STRINGIFY_RANGE_KEY = 'DD_' + crypto.randomBytes(20).toString('hex')
|
|
8
8
|
const STRINGIFY_SENSITIVE_KEY = STRINGIFY_RANGE_KEY + 'SENSITIVE'
|
|
@@ -26,6 +26,10 @@ class EventTrackingV2 {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
class AppsecSdk {
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../../tracer')} tracer - Tracer instance
|
|
31
|
+
* @param {import('../../config/config-base')} config - Tracer configuration
|
|
32
|
+
*/
|
|
29
33
|
constructor (tracer, config) {
|
|
30
34
|
this._tracer = tracer
|
|
31
35
|
if (config) {
|
|
@@ -21,7 +21,7 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) {
|
|
|
21
21
|
|
|
22
22
|
incrementSdkEventMetric('login_success', 'v1')
|
|
23
23
|
|
|
24
|
-
const rootSpan = getRootSpan(
|
|
24
|
+
const rootSpan = getRootSpan()
|
|
25
25
|
if (!rootSpan) {
|
|
26
26
|
log.warn('[ASM] Root span not available in trackUserLoginSuccessEvent')
|
|
27
27
|
return
|
|
@@ -54,7 +54,7 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) {
|
|
|
54
54
|
...metadata,
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan(
|
|
57
|
+
trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan())
|
|
58
58
|
|
|
59
59
|
runWaf('users.login.failure', { login: userId })
|
|
60
60
|
|
|
@@ -67,7 +67,7 @@ function trackCustomEvent (tracer, eventName, metadata) {
|
|
|
67
67
|
return
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan(
|
|
70
|
+
trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan())
|
|
71
71
|
|
|
72
72
|
incrementSdkEventMetric('custom', 'v1')
|
|
73
73
|
|
|
@@ -84,7 +84,7 @@ function trackUserLoginSuccessV2 (tracer, login, user, metadata) {
|
|
|
84
84
|
|
|
85
85
|
incrementSdkEventMetric('login_success', 'v2')
|
|
86
86
|
|
|
87
|
-
const rootSpan = getRootSpan(
|
|
87
|
+
const rootSpan = getRootSpan()
|
|
88
88
|
if (!rootSpan) {
|
|
89
89
|
log.warn('[ASM] Root span not available in eventTrackingV2.trackUserLoginSuccess')
|
|
90
90
|
return
|
|
@@ -122,7 +122,7 @@ function trackUserLoginFailureV2 (tracer, login, exists, metadata) {
|
|
|
122
122
|
|
|
123
123
|
incrementSdkEventMetric('login_failure', 'v2')
|
|
124
124
|
|
|
125
|
-
const rootSpan = getRootSpan(
|
|
125
|
+
const rootSpan = getRootSpan()
|
|
126
126
|
if (!rootSpan) {
|
|
127
127
|
log.warn('[ASM] Root span not available in eventTrackingV2.trackUserLoginFailure')
|
|
128
128
|
return
|
|
@@ -19,7 +19,7 @@ function checkUserAndSetUser (tracer, user) {
|
|
|
19
19
|
return false
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const rootSpan = getRootSpan(
|
|
22
|
+
const rootSpan = getRootSpan()
|
|
23
23
|
if (rootSpan) {
|
|
24
24
|
if (!rootSpan.context()._tags['usr.id']) {
|
|
25
25
|
setUserTags(user, rootSpan)
|
|
@@ -45,7 +45,7 @@ function blockRequest (tracer, req, res) {
|
|
|
45
45
|
return false
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const rootSpan = getRootSpan(
|
|
48
|
+
const rootSpan = getRootSpan()
|
|
49
49
|
if (!rootSpan) {
|
|
50
50
|
log.warn('[ASM] Root span not available in blockRequest')
|
|
51
51
|
return false
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const { storage } = require('../../../../datadog-core')
|
|
4
|
+
|
|
5
|
+
function getRootSpan () {
|
|
6
|
+
let span = storage('legacy').getStore()?.span
|
|
5
7
|
if (!span) return
|
|
6
8
|
|
|
7
9
|
const context = span.context()
|
|
@@ -11,6 +11,9 @@ const probeIdToResolveBreakpointSet = new Map()
|
|
|
11
11
|
const probeIdToResolveBreakpointRemove = new Map()
|
|
12
12
|
|
|
13
13
|
class TestVisDynamicInstrumentation {
|
|
14
|
+
/**
|
|
15
|
+
* @param {import('../../config/config-base')} config - Tracer configuration
|
|
16
|
+
*/
|
|
14
17
|
constructor (config) {
|
|
15
18
|
this._config = config
|
|
16
19
|
this.worker = null
|
|
@@ -83,7 +86,6 @@ class TestVisDynamicInstrumentation {
|
|
|
83
86
|
DD_TRACE_ENABLED: 'false',
|
|
84
87
|
DD_TEST_FAILED_TEST_REPLAY_ENABLED: 'false',
|
|
85
88
|
DD_CIVISIBILITY_MANUAL_API_ENABLED: 'false',
|
|
86
|
-
DD_TRACING_ENABLED: 'false',
|
|
87
89
|
DD_INSTRUMENTATION_TELEMETRY_ENABLED: 'false',
|
|
88
90
|
},
|
|
89
91
|
workerData: {
|
|
@@ -150,6 +152,9 @@ class TestVisDynamicInstrumentation {
|
|
|
150
152
|
|
|
151
153
|
let dynamicInstrumentation
|
|
152
154
|
|
|
155
|
+
/**
|
|
156
|
+
* @param {import('../../config/config-base')} config - Tracer configuration
|
|
157
|
+
*/
|
|
153
158
|
module.exports = function createAndGetTestVisDynamicInstrumentation (config) {
|
|
154
159
|
if (dynamicInstrumentation) {
|
|
155
160
|
return dynamicInstrumentation
|
|
@@ -54,6 +54,10 @@ class TestApiManualPlugin extends CiPlugin {
|
|
|
54
54
|
})
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @param {import('../../config/config-base')} config - Tracer configuration
|
|
59
|
+
* @param {boolean} shouldGetEnvironmentData - Whether to get environment data
|
|
60
|
+
*/
|
|
57
61
|
configure (config, shouldGetEnvironmentData) {
|
|
58
62
|
this._config = config
|
|
59
63
|
super.configure(config, shouldGetEnvironmentData)
|