dd-trace 5.56.0 → 5.57.1
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 +44 -2
- package/init.js +4 -1
- package/package.json +20 -20
- package/packages/datadog-esbuild/index.js +22 -0
- package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
- package/packages/datadog-instrumentations/src/cucumber.js +4 -6
- package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
- package/packages/datadog-instrumentations/src/fastify.js +91 -9
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
- package/packages/datadog-instrumentations/src/ioredis.js +8 -13
- package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
- package/packages/datadog-instrumentations/src/jest.js +28 -6
- package/packages/datadog-instrumentations/src/memcached.js +17 -24
- package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
- package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
- package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
- package/packages/datadog-instrumentations/src/openai.js +30 -2
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +116 -0
- package/packages/datadog-instrumentations/src/redis.js +32 -43
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/sharedb.js +10 -16
- package/packages/datadog-instrumentations/src/vitest.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-bunyan/src/index.js +2 -2
- package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +4 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
- package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
- package/packages/datadog-plugin-http/src/client.js +1 -0
- package/packages/datadog-plugin-http/src/server.js +2 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -0
- package/packages/datadog-plugin-http2/src/server.js +1 -0
- package/packages/datadog-plugin-jest/src/index.js +4 -3
- package/packages/datadog-plugin-memcached/src/index.js +6 -2
- package/packages/datadog-plugin-mocha/src/index.js +3 -2
- package/packages/datadog-plugin-moleculer/src/client.js +15 -9
- package/packages/datadog-plugin-moleculer/src/server.js +9 -5
- package/packages/datadog-plugin-next/src/index.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +127 -80
- package/packages/datadog-plugin-pino/src/index.js +2 -2
- package/packages/datadog-plugin-prisma/src/client.js +62 -0
- package/packages/datadog-plugin-prisma/src/engine.js +81 -0
- package/packages/datadog-plugin-prisma/src/index.js +22 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +9 -3
- package/packages/datadog-plugin-router/src/index.js +1 -0
- package/packages/datadog-plugin-sharedb/src/index.js +13 -5
- package/packages/datadog-plugin-winston/src/index.js +2 -2
- package/packages/dd-trace/src/appsec/channels.js +26 -21
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
- package/packages/dd-trace/src/appsec/index.js +16 -1
- package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
- package/packages/dd-trace/src/config.js +286 -270
- package/packages/dd-trace/src/constants.js +2 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
- package/packages/dd-trace/src/datastreams/context.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/writer.js +3 -3
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
- package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
- package/packages/dd-trace/src/dogstatsd.js +3 -3
- package/packages/dd-trace/src/exporters/agent/index.js +10 -5
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
- package/packages/dd-trace/src/exporters/log/index.js +1 -1
- package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
- package/packages/dd-trace/src/guardrails/index.js +3 -1
- package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/index.js +11 -5
- package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +13 -13
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
- package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
- package/packages/dd-trace/src/opentracing/span.js +1 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/cache.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
- package/packages/dd-trace/src/plugins/database.js +3 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
- package/packages/dd-trace/src/plugins/outbound.js +8 -6
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +83 -30
- package/packages/dd-trace/src/plugins/util/git.js +1 -0
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/test.js +80 -10
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiler.js +0 -2
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
- package/packages/dd-trace/src/proxy.js +12 -27
- package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/supported-configurations.json +12 -3
- package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
- package/packages/dd-trace/src/tracer.js +11 -0
- package/packages/dd-trace/src/tracer_metadata.js +25 -0
- package/packages/dd-trace/src/util.js +11 -4
- package/version.js +3 -1
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const DatabasePlugin = require('../../dd-trace/src/plugins/database')
|
|
4
|
+
const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
|
|
5
|
+
|
|
6
|
+
const databaseDriverMapper = {
|
|
7
|
+
postgresql: {
|
|
8
|
+
type: 'sql',
|
|
9
|
+
'db.type': 'postgres'
|
|
10
|
+
},
|
|
11
|
+
mysql: {
|
|
12
|
+
type: 'sql',
|
|
13
|
+
'db.type': 'mysql'
|
|
14
|
+
},
|
|
15
|
+
mongodb: {
|
|
16
|
+
type: 'mongodb',
|
|
17
|
+
'db.type': 'mongodb'
|
|
18
|
+
},
|
|
19
|
+
sqlite: {
|
|
20
|
+
type: 'sql',
|
|
21
|
+
'db.type': 'sqlite'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class PrismaEngine extends DatabasePlugin {
|
|
26
|
+
static get id () { return 'prisma' }
|
|
27
|
+
static get operation () { return 'engine' }
|
|
28
|
+
static get system () { return 'prisma' }
|
|
29
|
+
|
|
30
|
+
start (ctx) {
|
|
31
|
+
const { engineSpan, allEngineSpans, childOf, dbConfig } = ctx
|
|
32
|
+
const service = this.serviceName({ pluginConfig: this.config, system: this.system })
|
|
33
|
+
const spanName = engineSpan.name.slice(14) // remove 'prisma:engine:' prefix
|
|
34
|
+
const options = {
|
|
35
|
+
childOf,
|
|
36
|
+
resource: spanName,
|
|
37
|
+
service,
|
|
38
|
+
kind: engineSpan.kind,
|
|
39
|
+
meta: {
|
|
40
|
+
prisma: {
|
|
41
|
+
name: spanName,
|
|
42
|
+
type: 'engine'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (spanName === 'db_query') {
|
|
48
|
+
const query = engineSpan.attributes['db.query.text']
|
|
49
|
+
const originalStatement = this.maybeTruncate(query)
|
|
50
|
+
const type = databaseDriverMapper[engineSpan.attributes['db.system']]?.type
|
|
51
|
+
const dbType = databaseDriverMapper[engineSpan.attributes['db.system']]?.['db.type']
|
|
52
|
+
|
|
53
|
+
options.resource = originalStatement
|
|
54
|
+
options.type = type || engineSpan.attributes['db.system']
|
|
55
|
+
options.meta['db.type'] = dbType || engineSpan.attributes['db.system']
|
|
56
|
+
options.meta['db.instance'] = dbConfig?.database
|
|
57
|
+
options.meta['db.name'] = dbConfig?.user
|
|
58
|
+
options.meta['out.host'] = dbConfig?.host
|
|
59
|
+
options.meta[CLIENT_PORT_KEY] = dbConfig?.port
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const activeSpan = this.startSpan(this.operationName({ operation: this.operation }), options)
|
|
63
|
+
activeSpan._startTime = hrTimeToUnixTimeMs(engineSpan.startTime)
|
|
64
|
+
for (const span of allEngineSpans) {
|
|
65
|
+
if (span.parentId === engineSpan.id) {
|
|
66
|
+
const startCtx = { engineSpan: span, allEngineSpans, childOf: activeSpan, dbConfig }
|
|
67
|
+
this.start(startCtx)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const unixEndTime = hrTimeToUnixTimeMs(engineSpan.endTime)
|
|
71
|
+
activeSpan.finish(unixEndTime)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Opentelemetry time format is defined here
|
|
76
|
+
// https://github.com/open-telemetry/opentelemetry-js/blob/cbc912d/api/src/common/Time.ts#L19-L30.
|
|
77
|
+
function hrTimeToUnixTimeMs ([seconds, nanoseconds]) {
|
|
78
|
+
return seconds * 1000 + nanoseconds / 1e6
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = PrismaEngine
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
4
|
+
|
|
5
|
+
const PrismaClientPlugin = require('./client')
|
|
6
|
+
const PrismaEnginePlugin = require('./engine')
|
|
7
|
+
|
|
8
|
+
class PrismaPlugin extends CompositePlugin {
|
|
9
|
+
static get id () { return 'prisma' }
|
|
10
|
+
static get plugins () {
|
|
11
|
+
return {
|
|
12
|
+
client: PrismaClientPlugin,
|
|
13
|
+
engine: PrismaEnginePlugin
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
configure (config) {
|
|
18
|
+
return super.configure(config)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = PrismaPlugin
|
|
@@ -108,7 +108,7 @@ class SchemaExtractor {
|
|
|
108
108
|
}
|
|
109
109
|
for (const field of schema.fieldsArray) {
|
|
110
110
|
if (!this.extractProperty(field, schemaName, field.name, builder, depth)) {
|
|
111
|
-
log.warn(
|
|
111
|
+
log.warn('DSM: Unable to extract field with name: %s from Avro schema with name:', field.name, schemaName)
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
return true
|
|
@@ -13,10 +13,14 @@ class RedisPlugin extends CachePlugin {
|
|
|
13
13
|
this._spanType = 'redis'
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
bindStart (ctx) {
|
|
17
|
+
const { db, command, args, connectionOptions, connectionName } = ctx
|
|
18
|
+
|
|
17
19
|
const resource = command
|
|
18
20
|
const normalizedCommand = command.toUpperCase()
|
|
19
|
-
if (!this.config.filter(normalizedCommand))
|
|
21
|
+
if (!this.config.filter(normalizedCommand)) {
|
|
22
|
+
return { noop: true }
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
this.startSpan({
|
|
22
26
|
resource,
|
|
@@ -29,7 +33,9 @@ class RedisPlugin extends CachePlugin {
|
|
|
29
33
|
'out.host': connectionOptions.host,
|
|
30
34
|
[CLIENT_PORT_KEY]: connectionOptions.port
|
|
31
35
|
}
|
|
32
|
-
})
|
|
36
|
+
}, ctx)
|
|
37
|
+
|
|
38
|
+
return ctx.currentStore
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
configure (config) {
|
|
@@ -106,6 +106,7 @@ class RouterPlugin extends WebPlugin {
|
|
|
106
106
|
|
|
107
107
|
const span = this.tracer.startSpan(`${this.constructor.id}.middleware`, {
|
|
108
108
|
childOf,
|
|
109
|
+
integrationName: this.constructor.id,
|
|
109
110
|
tags: {
|
|
110
111
|
[COMPONENT]: this.constructor.id,
|
|
111
112
|
'resource.name': name || '<anonymous>'
|
|
@@ -5,7 +5,9 @@ const ServerPlugin = require('../../dd-trace/src/plugins/server')
|
|
|
5
5
|
class SharedbPlugin extends ServerPlugin {
|
|
6
6
|
static get id () { return 'sharedb' }
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
bindStart (ctx) {
|
|
9
|
+
const { actionName, request } = ctx
|
|
10
|
+
|
|
9
11
|
const span = this.startSpan('sharedb.request', {
|
|
10
12
|
service: this.config.service,
|
|
11
13
|
resource: getReadableResourceName(actionName, request.c, request.q),
|
|
@@ -13,19 +15,25 @@ class SharedbPlugin extends ServerPlugin {
|
|
|
13
15
|
meta: {
|
|
14
16
|
'sharedb.action': actionName
|
|
15
17
|
}
|
|
16
|
-
})
|
|
18
|
+
}, ctx)
|
|
17
19
|
|
|
18
20
|
if (this.config.hooks && this.config.hooks.receive) {
|
|
19
21
|
this.config.hooks.receive(span, request)
|
|
20
22
|
}
|
|
23
|
+
|
|
24
|
+
return ctx.currentStore
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
const
|
|
27
|
+
bindFinish (ctx) {
|
|
28
|
+
const { request, res } = ctx
|
|
29
|
+
|
|
30
|
+
const span = ctx.currentStore.span
|
|
25
31
|
if (this.config.hooks && this.config.hooks.reply) {
|
|
26
32
|
this.config.hooks.reply(span, request, res)
|
|
27
33
|
}
|
|
28
|
-
super.finish()
|
|
34
|
+
super.finish(ctx)
|
|
35
|
+
|
|
36
|
+
return ctx.parentStore
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const StructuredLogPlugin = require('../../dd-trace/src/plugins/structured_log_plugin')
|
|
4
4
|
|
|
5
|
-
class WinstonPlugin extends
|
|
5
|
+
class WinstonPlugin extends StructuredLogPlugin {
|
|
6
6
|
static get id () {
|
|
7
7
|
return 'winston'
|
|
8
8
|
}
|
|
@@ -4,34 +4,39 @@ const dc = require('dc-polyfill')
|
|
|
4
4
|
|
|
5
5
|
// TODO: use TBD naming convention
|
|
6
6
|
module.exports = {
|
|
7
|
+
apolloChannel: dc.tracingChannel('datadog:apollo:request'),
|
|
8
|
+
apolloServerCoreChannel: dc.tracingChannel('datadog:apollo-server-core:request'),
|
|
7
9
|
bodyParser: dc.channel('datadog:body-parser:read:finish'),
|
|
10
|
+
childProcessExecutionTracingChannel: dc.tracingChannel('datadog:child_process:execution'),
|
|
8
11
|
cookieParser: dc.channel('datadog:cookie-parser:read:finish'),
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
expressMiddlewareError: dc.channel('apm:express:middleware:error'),
|
|
13
|
+
expressProcessParams: dc.channel('datadog:express:process_params:start'),
|
|
14
|
+
expressSession: dc.channel('datadog:express-session:middleware:finish'),
|
|
15
|
+
fastifyBodyParser: dc.channel('datadog:fastify:body-parser:finish'),
|
|
16
|
+
fastifyResponseChannel: dc.channel('datadog:fastify:response:finish'),
|
|
17
|
+
fastifyQueryParams: dc.channel('datadog:fastify:query-params:finish'),
|
|
18
|
+
fastifyCookieParser: dc.channel('datadog:fastify-cookie:read:finish'),
|
|
19
|
+
fastifyPathParams: dc.channel('datadog:fastify:path-params:finish'),
|
|
20
|
+
fsOperationStart: dc.channel('apm:fs:operation:start'),
|
|
11
21
|
graphqlMiddlewareChannel: dc.tracingChannel('datadog:apollo:middleware'),
|
|
12
|
-
|
|
13
|
-
apolloServerCoreChannel: dc.tracingChannel('datadog:apollo-server-core:request'),
|
|
14
|
-
incomingHttpRequestStart: dc.channel('dd-trace:incomingHttpRequestStart'),
|
|
22
|
+
httpClientRequestStart: dc.channel('apm:http:client:request:start'),
|
|
15
23
|
incomingHttpRequestEnd: dc.channel('dd-trace:incomingHttpRequestEnd'),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
queryParser: dc.channel('datadog:query:read:finish'),
|
|
20
|
-
setCookieChannel: dc.channel('datadog:iast:set-cookie'),
|
|
24
|
+
incomingHttpRequestStart: dc.channel('dd-trace:incomingHttpRequestStart'),
|
|
25
|
+
multerParser: dc.channel('datadog:multer:read:finish'),
|
|
26
|
+
mysql2OuterQueryStart: dc.channel('datadog:mysql2:outerquery:start'),
|
|
21
27
|
nextBodyParsed: dc.channel('apm:next:body-parsed'),
|
|
22
28
|
nextQueryParsed: dc.channel('apm:next:query-parsed'),
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
passportUser: dc.channel('datadog:passport:deserializeUser:finish'),
|
|
30
|
+
passportVerify: dc.channel('datadog:passport:verify:finish'),
|
|
31
|
+
pgPoolQueryStart: dc.channel('datadog:pg:pool:query:start'),
|
|
32
|
+
pgQueryStart: dc.channel('apm:pg:query:start'),
|
|
33
|
+
queryParser: dc.channel('datadog:query:read:finish'),
|
|
25
34
|
responseBody: dc.channel('datadog:express:response:json:start'),
|
|
26
|
-
responseWriteHead: dc.channel('apm:http:server:response:writeHead:start'),
|
|
27
|
-
httpClientRequestStart: dc.channel('apm:http:client:request:start'),
|
|
28
35
|
responseSetHeader: dc.channel('datadog:http:server:response:set-header:start'),
|
|
36
|
+
responseWriteHead: dc.channel('apm:http:server:response:writeHead:start'),
|
|
37
|
+
routerParam: dc.channel('datadog:router:param:start'),
|
|
38
|
+
setCookieChannel: dc.channel('datadog:iast:set-cookie'),
|
|
29
39
|
setUncaughtExceptionCaptureCallbackStart: dc.channel('datadog:process:setUncaughtExceptionCaptureCallback:start'),
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
mysql2OuterQueryStart: dc.channel('datadog:mysql2:outerquery:start'),
|
|
33
|
-
wafRunFinished: dc.channel('datadog:waf:run:finish'),
|
|
34
|
-
fsOperationStart: dc.channel('apm:fs:operation:start'),
|
|
35
|
-
expressMiddlewareError: dc.channel('apm:express:middleware:error'),
|
|
36
|
-
childProcessExecutionTracingChannel: dc.tracingChannel('datadog:child_process:execution')
|
|
40
|
+
startGraphqlResolve: dc.channel('datadog:graphql:resolver:start'),
|
|
41
|
+
wafRunFinished: dc.channel('datadog:waf:run:finish')
|
|
37
42
|
}
|
|
@@ -5,13 +5,17 @@ const { UNVALIDATED_REDIRECT } = require('../vulnerabilities')
|
|
|
5
5
|
const { getNodeModulesPaths } = require('../path-line')
|
|
6
6
|
const { getRanges } = require('../taint-tracking/operations')
|
|
7
7
|
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
HTTP_REQUEST_URI
|
|
8
|
+
HTTP_REQUEST_BODY,
|
|
9
|
+
HTTP_REQUEST_PARAMETER
|
|
11
10
|
} = require('../taint-tracking/source-types')
|
|
12
11
|
|
|
13
12
|
const EXCLUDED_PATHS = getNodeModulesPaths('express/lib/response.js')
|
|
14
13
|
|
|
14
|
+
const VULNERABLE_SOURCE_TYPES = new Set([
|
|
15
|
+
HTTP_REQUEST_BODY,
|
|
16
|
+
HTTP_REQUEST_PARAMETER
|
|
17
|
+
])
|
|
18
|
+
|
|
15
19
|
class UnvalidatedRedirectAnalyzer extends InjectionAnalyzer {
|
|
16
20
|
constructor () {
|
|
17
21
|
super(UNVALIDATED_REDIRECT)
|
|
@@ -35,28 +39,17 @@ class UnvalidatedRedirectAnalyzer extends InjectionAnalyzer {
|
|
|
35
39
|
if (!value) return false
|
|
36
40
|
|
|
37
41
|
const ranges = getRanges(iastContext, value)
|
|
38
|
-
return ranges
|
|
42
|
+
return ranges?.length > 0 && this._hasUnsafeRange(ranges)
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return ranges && ranges.every(
|
|
45
|
-
range => this._isPathParam(range) || this._isUrl(range) || this._isRefererHeader(range)
|
|
45
|
+
_hasUnsafeRange (ranges) {
|
|
46
|
+
return ranges.some(
|
|
47
|
+
range => this._isVulnerableRange(range)
|
|
46
48
|
)
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
return range.iinfo.type
|
|
51
|
-
range.iinfo.parameterName && range.iinfo.parameterName.toLowerCase() === 'referer'
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
_isPathParam (range) {
|
|
55
|
-
return range.iinfo.type === HTTP_REQUEST_PATH_PARAM
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
_isUrl (range) {
|
|
59
|
-
return range.iinfo.type === HTTP_REQUEST_URI
|
|
51
|
+
_isVulnerableRange (range) {
|
|
52
|
+
return VULNERABLE_SOURCE_TYPES.has(range.iinfo.type)
|
|
60
53
|
}
|
|
61
54
|
|
|
62
55
|
_getExcludedPaths () {
|
|
@@ -7,7 +7,6 @@ module.exports = {
|
|
|
7
7
|
HTTP_REQUEST_HEADER_NAME: 'http.request.header.name',
|
|
8
8
|
HTTP_REQUEST_HEADER_VALUE: 'http.request.header',
|
|
9
9
|
HTTP_REQUEST_PARAMETER: 'http.request.parameter',
|
|
10
|
-
HTTP_REQUEST_PATH: 'http.request.path',
|
|
11
10
|
HTTP_REQUEST_PATH_PARAM: 'http.request.path.parameter',
|
|
12
11
|
HTTP_REQUEST_URI: 'http.request.uri',
|
|
13
12
|
KAFKA_MESSAGE_KEY: 'kafka.message.key',
|
|
@@ -7,6 +7,8 @@ const {
|
|
|
7
7
|
bodyParser,
|
|
8
8
|
cookieParser,
|
|
9
9
|
multerParser,
|
|
10
|
+
fastifyBodyParser,
|
|
11
|
+
fastifyCookieParser,
|
|
10
12
|
incomingHttpRequestStart,
|
|
11
13
|
incomingHttpRequestEnd,
|
|
12
14
|
passportVerify,
|
|
@@ -16,10 +18,13 @@ const {
|
|
|
16
18
|
nextBodyParsed,
|
|
17
19
|
nextQueryParsed,
|
|
18
20
|
expressProcessParams,
|
|
21
|
+
fastifyQueryParams,
|
|
19
22
|
responseBody,
|
|
20
23
|
responseWriteHead,
|
|
21
24
|
responseSetHeader,
|
|
22
|
-
routerParam
|
|
25
|
+
routerParam,
|
|
26
|
+
fastifyResponseChannel,
|
|
27
|
+
fastifyPathParams
|
|
23
28
|
} = require('./channels')
|
|
24
29
|
const waf = require('./waf')
|
|
25
30
|
const addresses = require('./addresses')
|
|
@@ -77,8 +82,13 @@ function enable (_config) {
|
|
|
77
82
|
nextBodyParsed.subscribe(onRequestBodyParsed)
|
|
78
83
|
nextQueryParsed.subscribe(onRequestQueryParsed)
|
|
79
84
|
expressProcessParams.subscribe(onRequestProcessParams)
|
|
85
|
+
fastifyBodyParser.subscribe(onRequestBodyParsed)
|
|
86
|
+
fastifyQueryParams.subscribe(onRequestQueryParsed)
|
|
87
|
+
fastifyCookieParser.subscribe(onRequestCookieParser)
|
|
88
|
+
fastifyPathParams.subscribe(onRequestProcessParams)
|
|
80
89
|
routerParam.subscribe(onRequestProcessParams)
|
|
81
90
|
responseBody.subscribe(onResponseBody)
|
|
91
|
+
fastifyResponseChannel.subscribe(onResponseBody)
|
|
82
92
|
responseWriteHead.subscribe(onResponseWriteHead)
|
|
83
93
|
responseSetHeader.subscribe(onResponseSetHeader)
|
|
84
94
|
|
|
@@ -367,8 +377,13 @@ function disable () {
|
|
|
367
377
|
if (nextBodyParsed.hasSubscribers) nextBodyParsed.unsubscribe(onRequestBodyParsed)
|
|
368
378
|
if (nextQueryParsed.hasSubscribers) nextQueryParsed.unsubscribe(onRequestQueryParsed)
|
|
369
379
|
if (expressProcessParams.hasSubscribers) expressProcessParams.unsubscribe(onRequestProcessParams)
|
|
380
|
+
if (fastifyBodyParser.hasSubscribers) fastifyBodyParser.unsubscribe(onRequestBodyParsed)
|
|
381
|
+
if (fastifyQueryParams.hasSubscribers) fastifyQueryParams.unsubscribe(onRequestQueryParsed)
|
|
382
|
+
if (fastifyCookieParser.hasSubscribers) fastifyCookieParser.unsubscribe(onRequestCookieParser)
|
|
383
|
+
if (fastifyPathParams.hasSubscribers) fastifyPathParams.unsubscribe(onRequestProcessParams)
|
|
370
384
|
if (routerParam.hasSubscribers) routerParam.unsubscribe(onRequestProcessParams)
|
|
371
385
|
if (responseBody.hasSubscribers) responseBody.unsubscribe(onResponseBody)
|
|
386
|
+
if (fastifyResponseChannel.hasSubscribers) fastifyResponseChannel.unsubscribe(onResponseBody)
|
|
372
387
|
if (responseWriteHead.hasSubscribers) responseWriteHead.unsubscribe(onResponseWriteHead)
|
|
373
388
|
if (responseSetHeader.hasSubscribers) responseSetHeader.unsubscribe(onResponseSetHeader)
|
|
374
389
|
}
|
|
@@ -58,11 +58,6 @@ function handleResult (result, req, res, abortController, config, raspRule) {
|
|
|
58
58
|
const abortError = new DatadogRaspAbortError(req, res, blockingAction, raspRule, ruleTriggered)
|
|
59
59
|
abortController.abort(abortError)
|
|
60
60
|
|
|
61
|
-
// TODO Delete this when support for node 16 is removed
|
|
62
|
-
if (!abortController.signal.reason) {
|
|
63
|
-
abortController.signal.reason = abortError
|
|
64
|
-
}
|
|
65
|
-
|
|
66
61
|
return
|
|
67
62
|
}
|
|
68
63
|
}
|
|
@@ -30,7 +30,7 @@ const probeIdToBreakpointId = new Map()
|
|
|
30
30
|
session.on('Debugger.paused', async ({ params: { hitBreakpoints: [hitBreakpoint], callFrames } }) => {
|
|
31
31
|
const probe = breakpointIdToProbe.get(hitBreakpoint)
|
|
32
32
|
if (!probe) {
|
|
33
|
-
log.warn(
|
|
33
|
+
log.warn('No probe found for breakpoint', hitBreakpoint)
|
|
34
34
|
return session.post('Debugger.resume')
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -95,13 +95,13 @@ async function addBreakpoint (probe) {
|
|
|
95
95
|
|
|
96
96
|
const script = findScriptFromPartialPath(file)
|
|
97
97
|
if (!script) {
|
|
98
|
-
log.error(
|
|
98
|
+
log.error('No loaded script found for', file)
|
|
99
99
|
throw new Error(`No loaded script found for ${file}`)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const { url, scriptId, sourceMapURL, source } = script
|
|
103
103
|
|
|
104
|
-
log.warn(
|
|
104
|
+
log.warn('Adding breakpoint at %s:%s', url, line)
|
|
105
105
|
|
|
106
106
|
let lineNumber = line
|
|
107
107
|
let columnNumber = 0
|
|
@@ -96,7 +96,7 @@ function getKnownTests ({
|
|
|
96
96
|
incrementCountMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_TESTS, {}, numTests)
|
|
97
97
|
distributionMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_BYTES, {}, res.length)
|
|
98
98
|
|
|
99
|
-
log.debug(
|
|
99
|
+
log.debug('Number of received known tests:', numTests)
|
|
100
100
|
|
|
101
101
|
done(null, knownTests)
|
|
102
102
|
} catch (err) {
|
|
@@ -48,7 +48,7 @@ class Writer extends BaseWriter {
|
|
|
48
48
|
const startRequestTime = Date.now()
|
|
49
49
|
|
|
50
50
|
incrementCountMetric(TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS, { endpoint: 'test_cycle' })
|
|
51
|
-
distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_BYTES, { endpoint: 'test_cycle' }, data
|
|
51
|
+
distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_BYTES, { endpoint: 'test_cycle' }, Buffer.byteLength(data))
|
|
52
52
|
|
|
53
53
|
request(data, options, (err, res, statusCode) => {
|
|
54
54
|
distributionMetric(
|
|
@@ -69,7 +69,7 @@ class Writer extends BaseWriter {
|
|
|
69
69
|
done()
|
|
70
70
|
return
|
|
71
71
|
}
|
|
72
|
-
log.debug(
|
|
72
|
+
log.debug('Response from the intake:', res)
|
|
73
73
|
done()
|
|
74
74
|
})
|
|
75
75
|
}
|
|
@@ -105,9 +105,9 @@ function getCommitsToUpload ({ url, repositoryUrl, latestCommits, isEvpProxy, ev
|
|
|
105
105
|
incrementCountMetric(TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_ERRORS, { errorType: 'network' })
|
|
106
106
|
return callback(new Error(`Can't parse commits to exclude response: ${e.message}`))
|
|
107
107
|
}
|
|
108
|
-
log.debug(
|
|
108
|
+
log.debug('There are %s commits to exclude.', alreadySeenCommits.length)
|
|
109
109
|
const commitsToInclude = latestCommits.filter((commit) => !alreadySeenCommits.includes(commit))
|
|
110
|
-
log.debug(
|
|
110
|
+
log.debug('There are %s commits to include.', commitsToInclude.length)
|
|
111
111
|
|
|
112
112
|
if (!commitsToInclude.length) {
|
|
113
113
|
return callback(null, [])
|
|
@@ -195,11 +195,11 @@ function generateAndUploadPackFiles ({
|
|
|
195
195
|
repositoryUrl,
|
|
196
196
|
headCommit
|
|
197
197
|
}, callback) {
|
|
198
|
-
log.debug(
|
|
198
|
+
log.debug('There are %s commits to upload', commitsToUpload.length)
|
|
199
199
|
|
|
200
200
|
const packFilesToUpload = generatePackFilesForCommits(commitsToUpload)
|
|
201
201
|
|
|
202
|
-
log.debug(
|
|
202
|
+
log.debug('Uploading %s packfiles.', packFilesToUpload.length)
|
|
203
203
|
|
|
204
204
|
if (!packFilesToUpload.length) {
|
|
205
205
|
return callback(new Error('Failed to generate packfiles'))
|
|
@@ -253,14 +253,14 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
|
|
|
253
253
|
repositoryUrl = getRepositoryUrl()
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
log.debug(
|
|
256
|
+
log.debug('Uploading git history for repository', repositoryUrl)
|
|
257
257
|
|
|
258
258
|
if (!repositoryUrl) {
|
|
259
259
|
return callback(new Error('Repository URL is empty'))
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
let latestCommits = getLatestCommits()
|
|
263
|
-
log.debug(
|
|
263
|
+
log.debug('There were %s commits since last month.', latestCommits.length)
|
|
264
264
|
|
|
265
265
|
const getOnFinishGetCommitsToUpload = (hasCheckedShallow) => (err, commitsToUpload) => {
|
|
266
266
|
if (err) {
|
|
@@ -86,10 +86,9 @@ function getSkippableSuites ({
|
|
|
86
86
|
incrementCountMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_ERRORS, { statusCode })
|
|
87
87
|
done(err)
|
|
88
88
|
} else {
|
|
89
|
-
let skippableSuites = []
|
|
90
89
|
try {
|
|
91
90
|
const parsedResponse = JSON.parse(res)
|
|
92
|
-
skippableSuites = parsedResponse
|
|
91
|
+
const skippableSuites = parsedResponse
|
|
93
92
|
.data
|
|
94
93
|
.filter(({ type }) => type === testLevel)
|
|
95
94
|
.map(({ attributes: { suite, name } }) => {
|
|
@@ -107,7 +106,7 @@ function getSkippableSuites ({
|
|
|
107
106
|
skippableSuites.length
|
|
108
107
|
)
|
|
109
108
|
distributionMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES, {}, res.length)
|
|
110
|
-
log.debug(
|
|
109
|
+
log.debug('Number of received skippable %ss:', testLevel, skippableSuites.length)
|
|
111
110
|
done(null, skippableSuites, correlationId)
|
|
112
111
|
} catch (err) {
|
|
113
112
|
done(err)
|
|
@@ -122,15 +122,15 @@ function getLibraryConfiguration ({
|
|
|
122
122
|
isImpactedTestsEnabled
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
log.debug(
|
|
125
|
+
log.debug('Remote settings: %j', settings)
|
|
126
126
|
|
|
127
127
|
if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
|
|
128
128
|
settings.isCodeCoverageEnabled = true
|
|
129
|
-
log.debug(
|
|
129
|
+
log.debug('Dangerously set code coverage to true')
|
|
130
130
|
}
|
|
131
131
|
if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
|
|
132
132
|
settings.isSuitesSkippingEnabled = true
|
|
133
|
-
log.debug(
|
|
133
|
+
log.debug('Dangerously set test skipping to true')
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE, settings)
|