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.
Files changed (134) hide show
  1. package/index.d.ts +44 -2
  2. package/init.js +4 -1
  3. package/package.json +20 -20
  4. package/packages/datadog-esbuild/index.js +22 -0
  5. package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
  6. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
  7. package/packages/datadog-instrumentations/src/cucumber.js +4 -6
  8. package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
  9. package/packages/datadog-instrumentations/src/fastify.js +91 -9
  10. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
  11. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  13. package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
  14. package/packages/datadog-instrumentations/src/ioredis.js +8 -13
  15. package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
  16. package/packages/datadog-instrumentations/src/jest.js +28 -6
  17. package/packages/datadog-instrumentations/src/memcached.js +17 -24
  18. package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
  19. package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
  20. package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
  21. package/packages/datadog-instrumentations/src/openai.js +30 -2
  22. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  23. package/packages/datadog-instrumentations/src/prisma.js +116 -0
  24. package/packages/datadog-instrumentations/src/redis.js +32 -43
  25. package/packages/datadog-instrumentations/src/router.js +1 -1
  26. package/packages/datadog-instrumentations/src/sharedb.js +10 -16
  27. package/packages/datadog-instrumentations/src/vitest.js +4 -4
  28. package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
  29. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
  31. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
  32. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
  33. package/packages/datadog-plugin-bunyan/src/index.js +2 -2
  34. package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
  35. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
  36. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
  37. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  38. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
  39. package/packages/datadog-plugin-cucumber/src/index.js +4 -2
  40. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
  41. package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
  42. package/packages/datadog-plugin-http/src/client.js +1 -0
  43. package/packages/datadog-plugin-http/src/server.js +2 -1
  44. package/packages/datadog-plugin-http2/src/client.js +1 -0
  45. package/packages/datadog-plugin-http2/src/server.js +1 -0
  46. package/packages/datadog-plugin-jest/src/index.js +4 -3
  47. package/packages/datadog-plugin-memcached/src/index.js +6 -2
  48. package/packages/datadog-plugin-mocha/src/index.js +3 -2
  49. package/packages/datadog-plugin-moleculer/src/client.js +15 -9
  50. package/packages/datadog-plugin-moleculer/src/server.js +9 -5
  51. package/packages/datadog-plugin-next/src/index.js +2 -1
  52. package/packages/datadog-plugin-openai/src/tracing.js +127 -80
  53. package/packages/datadog-plugin-pino/src/index.js +2 -2
  54. package/packages/datadog-plugin-prisma/src/client.js +62 -0
  55. package/packages/datadog-plugin-prisma/src/engine.js +81 -0
  56. package/packages/datadog-plugin-prisma/src/index.js +22 -0
  57. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  58. package/packages/datadog-plugin-redis/src/index.js +9 -3
  59. package/packages/datadog-plugin-router/src/index.js +1 -0
  60. package/packages/datadog-plugin-sharedb/src/index.js +13 -5
  61. package/packages/datadog-plugin-winston/src/index.js +2 -2
  62. package/packages/dd-trace/src/appsec/channels.js +26 -21
  63. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
  64. package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
  65. package/packages/dd-trace/src/appsec/index.js +16 -1
  66. package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
  67. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
  68. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  69. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  70. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  71. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  72. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
  73. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
  74. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
  75. package/packages/dd-trace/src/config.js +286 -270
  76. package/packages/dd-trace/src/constants.js +2 -1
  77. package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
  78. package/packages/dd-trace/src/datastreams/context.js +1 -1
  79. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  80. package/packages/dd-trace/src/datastreams/writer.js +3 -3
  81. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
  82. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  83. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
  84. package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
  85. package/packages/dd-trace/src/dogstatsd.js +3 -3
  86. package/packages/dd-trace/src/exporters/agent/index.js +10 -5
  87. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  88. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
  89. package/packages/dd-trace/src/exporters/log/index.js +1 -1
  90. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
  91. package/packages/dd-trace/src/guardrails/index.js +3 -1
  92. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  93. package/packages/dd-trace/src/llmobs/index.js +11 -5
  94. package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
  95. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  96. package/packages/dd-trace/src/llmobs/tagger.js +13 -13
  97. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  98. package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
  99. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  100. package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
  101. package/packages/dd-trace/src/opentracing/span.js +1 -0
  102. package/packages/dd-trace/src/plugin_manager.js +3 -3
  103. package/packages/dd-trace/src/plugins/cache.js +2 -2
  104. package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
  105. package/packages/dd-trace/src/plugins/database.js +3 -1
  106. package/packages/dd-trace/src/plugins/index.js +1 -0
  107. package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
  108. package/packages/dd-trace/src/plugins/outbound.js +8 -6
  109. package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
  110. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  111. package/packages/dd-trace/src/plugins/util/ci.js +83 -30
  112. package/packages/dd-trace/src/plugins/util/git.js +1 -0
  113. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
  114. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
  115. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  116. package/packages/dd-trace/src/plugins/util/test.js +80 -10
  117. package/packages/dd-trace/src/plugins/util/web.js +1 -0
  118. package/packages/dd-trace/src/profiler.js +0 -2
  119. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
  120. package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
  121. package/packages/dd-trace/src/proxy.js +12 -27
  122. package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
  123. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
  124. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
  125. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
  126. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
  127. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  128. package/packages/dd-trace/src/supported-configurations.json +12 -3
  129. package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
  130. package/packages/dd-trace/src/tracer.js +11 -0
  131. package/packages/dd-trace/src/tracer_metadata.js +25 -0
  132. package/packages/dd-trace/src/util.js +11 -4
  133. package/version.js +3 -1
  134. 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(`DSM: Unable to extract field with name: ${field.name} from Avro schema with name: ${schemaName}`)
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
- start ({ db, command, args, connectionOptions = {}, connectionName }) {
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)) return this.skip()
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
- start ({ actionName, request }) {
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
- finish ({ request, res }) {
24
- const span = this.activeSpan
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 LogPlugin = require('../../dd-trace/src/plugins/log_plugin')
3
+ const StructuredLogPlugin = require('../../dd-trace/src/plugins/structured_log_plugin')
4
4
 
5
- class WinstonPlugin extends LogPlugin {
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
- multerParser: dc.channel('datadog:multer:read:finish'),
10
- startGraphqlResolve: dc.channel('datadog:graphql:resolver:start'),
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
- apolloChannel: dc.tracingChannel('datadog:apollo:request'),
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
- passportVerify: dc.channel('datadog:passport:verify:finish'),
17
- passportUser: dc.channel('datadog:passport:deserializeUser:finish'),
18
- expressSession: dc.channel('datadog:express-session:middleware:finish'),
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
- expressProcessParams: dc.channel('datadog:express:process_params:start'),
24
- routerParam: dc.channel('datadog:router:param:start'),
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
- pgQueryStart: dc.channel('apm:pg:query:start'),
31
- pgPoolQueryStart: dc.channel('datadog:pg:pool:query:start'),
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
- HTTP_REQUEST_HEADER_VALUE,
9
- HTTP_REQUEST_PATH_PARAM,
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 && ranges.length > 0 && !this._areSafeRanges(ranges)
42
+ return ranges?.length > 0 && this._hasUnsafeRange(ranges)
39
43
  }
40
44
 
41
- // Do not report vulnerability if ranges sources are exclusively url,
42
- // path params or referer header to avoid false positives.
43
- _areSafeRanges (ranges) {
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
- _isRefererHeader (range) {
50
- return range.iinfo.type === HTTP_REQUEST_HEADER_VALUE &&
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(`No probe found for breakpoint ${hitBreakpoint}`)
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(`No loaded script found for ${file}`)
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(`Adding breakpoint at ${url}:${line}`)
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(() => `Number of received known tests: ${numTests}`)
99
+ log.debug('Number of received known tests:', numTests)
100
100
 
101
101
  done(null, knownTests)
102
102
  } catch (err) {
@@ -68,7 +68,7 @@ class Writer extends BaseWriter {
68
68
  done()
69
69
  return
70
70
  }
71
- log.debug(`Response from the intake: ${res}`)
71
+ log.debug('Response from the intake:', res)
72
72
  done()
73
73
  })
74
74
  }
@@ -45,7 +45,7 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
45
45
  done()
46
46
  return
47
47
  }
48
- log.debug(`Response from the logs intake: ${res}`)
48
+ log.debug('Response from the logs intake:', res)
49
49
  done()
50
50
  })
51
51
  }
@@ -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.length)
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(`Response from the intake: ${res}`)
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(`There are ${alreadySeenCommits.length} commits to exclude.`)
108
+ log.debug('There are %s commits to exclude.', alreadySeenCommits.length)
109
109
  const commitsToInclude = latestCommits.filter((commit) => !alreadySeenCommits.includes(commit))
110
- log.debug(`There are ${commitsToInclude.length} commits to include.`)
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(`There are ${commitsToUpload.length} commits to upload`)
198
+ log.debug('There are %s commits to upload', commitsToUpload.length)
199
199
 
200
200
  const packFilesToUpload = generatePackFilesForCommits(commitsToUpload)
201
201
 
202
- log.debug(`Uploading ${packFilesToUpload.length} packfiles.`)
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(`Uploading git history for repository ${repositoryUrl}`)
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(`There were ${latestCommits.length} commits since last month.`)
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(() => `Number of received skippable ${testLevel}s: ${skippableSuites.length}`)
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(() => `Remote settings: ${JSON.stringify(settings)}`)
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(() => 'Dangerously set code coverage to true')
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(() => 'Dangerously set test skipping to true')
133
+ log.debug('Dangerously set test skipping to true')
134
134
  }
135
135
 
136
136
  incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE, settings)