dd-trace 5.54.0 → 5.56.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.
Files changed (191) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/ci/cypress/plugin.js +8 -0
  3. package/ci/cypress/polyfills.js +23 -0
  4. package/ci/init.js +8 -7
  5. package/initialize.mjs +2 -2
  6. package/package.json +10 -9
  7. package/packages/datadog-code-origin/index.js +22 -4
  8. package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
  9. package/packages/datadog-core/src/utils/src/set.js +8 -10
  10. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
  11. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
  12. package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
  13. package/packages/datadog-instrumentations/src/couchbase.js +3 -6
  14. package/packages/datadog-instrumentations/src/cucumber.js +21 -28
  15. package/packages/datadog-instrumentations/src/dns.js +4 -4
  16. package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
  17. package/packages/datadog-instrumentations/src/fastify.js +7 -9
  18. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
  19. package/packages/datadog-instrumentations/src/hapi.js +10 -11
  20. package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
  21. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
  22. package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
  23. package/packages/datadog-instrumentations/src/jest.js +421 -376
  24. package/packages/datadog-instrumentations/src/koa.js +2 -3
  25. package/packages/datadog-instrumentations/src/mariadb.js +11 -4
  26. package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
  27. package/packages/datadog-instrumentations/src/mocha.js +3 -1
  28. package/packages/datadog-instrumentations/src/mysql.js +11 -2
  29. package/packages/datadog-instrumentations/src/nyc.js +2 -1
  30. package/packages/datadog-instrumentations/src/openai.js +2 -2
  31. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
  32. package/packages/datadog-instrumentations/src/pg.js +2 -3
  33. package/packages/datadog-instrumentations/src/playwright.js +19 -22
  34. package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
  35. package/packages/datadog-instrumentations/src/redis.js +1 -1
  36. package/packages/datadog-instrumentations/src/restify.js +9 -13
  37. package/packages/datadog-instrumentations/src/router.js +12 -11
  38. package/packages/datadog-instrumentations/src/tedious.js +1 -2
  39. package/packages/datadog-instrumentations/src/vitest.js +15 -29
  40. package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
  41. package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
  42. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
  43. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
  44. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
  45. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
  46. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
  47. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
  48. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
  49. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
  50. package/packages/datadog-plugin-azure-functions/src/index.js +5 -4
  51. package/packages/datadog-plugin-cucumber/src/index.js +3 -2
  52. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
  53. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
  54. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  55. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
  56. package/packages/datadog-plugin-graphql/src/index.js +3 -2
  57. package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
  58. package/packages/datadog-plugin-http/src/client.js +5 -6
  59. package/packages/datadog-plugin-http2/src/client.js +7 -8
  60. package/packages/datadog-plugin-jest/src/index.js +3 -2
  61. package/packages/datadog-plugin-mocha/src/index.js +6 -1
  62. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
  63. package/packages/datadog-plugin-mysql/src/index.js +11 -0
  64. package/packages/datadog-plugin-next/src/index.js +1 -1
  65. package/packages/datadog-plugin-openai/src/tracing.js +2 -4
  66. package/packages/datadog-plugin-oracledb/src/index.js +2 -1
  67. package/packages/datadog-plugin-playwright/src/index.js +3 -2
  68. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
  69. package/packages/datadog-plugin-redis/src/index.js +1 -3
  70. package/packages/datadog-plugin-vitest/src/index.js +5 -4
  71. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
  72. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
  73. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
  74. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
  75. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
  76. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  77. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +12 -13
  78. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +44 -1
  79. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -1
  80. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -3
  81. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
  82. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
  83. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
  84. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
  85. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
  86. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
  87. package/packages/dd-trace/src/appsec/index.js +16 -5
  88. package/packages/dd-trace/src/appsec/reporter.js +11 -11
  89. package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
  90. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
  91. package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
  92. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
  93. package/packages/dd-trace/src/azure_metadata.js +8 -3
  94. package/packages/dd-trace/src/baggage.js +2 -2
  95. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
  96. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
  97. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
  98. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
  99. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
  100. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
  101. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
  102. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
  103. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
  104. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
  105. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
  106. package/packages/dd-trace/src/config-helper.js +89 -0
  107. package/packages/dd-trace/src/config.js +120 -115
  108. package/packages/dd-trace/src/config_stable.js +7 -4
  109. package/packages/dd-trace/src/datastreams/fnv.js +1 -1
  110. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
  111. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
  112. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
  113. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
  114. package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -3
  115. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
  116. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
  117. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
  118. package/packages/dd-trace/src/debugger/devtools_client/status.js +5 -1
  119. package/packages/dd-trace/src/debugger/index.js +1 -0
  120. package/packages/dd-trace/src/dogstatsd.js +2 -2
  121. package/packages/dd-trace/src/encode/0.4.js +5 -2
  122. package/packages/dd-trace/src/encode/0.5.js +3 -5
  123. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
  124. package/packages/dd-trace/src/exporter.js +2 -1
  125. package/packages/dd-trace/src/exporters/agent/writer.js +3 -1
  126. package/packages/dd-trace/src/exporters/common/docker.js +3 -2
  127. package/packages/dd-trace/src/exporters/common/request.js +4 -1
  128. package/packages/dd-trace/src/exporters/common/util.js +3 -1
  129. package/packages/dd-trace/src/id.js +3 -3
  130. package/packages/dd-trace/src/index.js +4 -3
  131. package/packages/dd-trace/src/lambda/handler.js +2 -1
  132. package/packages/dd-trace/src/lambda/index.js +2 -1
  133. package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
  134. package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
  135. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  136. package/packages/dd-trace/src/llmobs/index.js +21 -5
  137. package/packages/dd-trace/src/llmobs/noop.js +18 -20
  138. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
  139. package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
  140. package/packages/dd-trace/src/llmobs/sdk.js +2 -1
  141. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  142. package/packages/dd-trace/src/llmobs/tagger.js +19 -6
  143. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  144. package/packages/dd-trace/src/log/index.js +5 -4
  145. package/packages/dd-trace/src/log/writer.js +1 -2
  146. package/packages/dd-trace/src/msgpack/encoder.js +3 -3
  147. package/packages/dd-trace/src/noop/span.js +1 -1
  148. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  149. package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
  150. package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -42
  151. package/packages/dd-trace/src/opentracing/span.js +7 -6
  152. package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
  153. package/packages/dd-trace/src/plugin_manager.js +4 -3
  154. package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
  155. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  156. package/packages/dd-trace/src/plugins/util/ci.js +7 -7
  157. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  158. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  159. package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
  160. package/packages/dd-trace/src/plugins/util/test.js +4 -3
  161. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
  162. package/packages/dd-trace/src/plugins/util/web.js +3 -4
  163. package/packages/dd-trace/src/priority_sampler.js +46 -35
  164. package/packages/dd-trace/src/profiling/config.js +12 -32
  165. package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
  166. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  167. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
  168. package/packages/dd-trace/src/profiling/index.js +2 -1
  169. package/packages/dd-trace/src/profiling/profiler.js +7 -4
  170. package/packages/dd-trace/src/profiling/profilers/events.js +10 -2
  171. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
  172. package/packages/dd-trace/src/profiling/tagger.js +22 -12
  173. package/packages/dd-trace/src/proxy.js +2 -1
  174. package/packages/dd-trace/src/ritm.js +4 -4
  175. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
  176. package/packages/dd-trace/src/sampler.js +10 -2
  177. package/packages/dd-trace/src/serverless.js +11 -4
  178. package/packages/dd-trace/src/span_processor.js +2 -1
  179. package/packages/dd-trace/src/standalone/tracesource.js +1 -2
  180. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
  181. package/packages/dd-trace/src/startup-log.js +5 -17
  182. package/packages/dd-trace/src/supported-configurations.json +440 -0
  183. package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
  184. package/packages/dd-trace/src/telemetry/send-data.js +7 -6
  185. package/packages/dd-trace/src/telemetry/telemetry.js +16 -26
  186. package/packages/dd-trace/src/tracer.js +3 -7
  187. package/packages/dd-trace/src/util.js +0 -5
  188. package/packages/datadog-core/src/utils/src/get.js +0 -11
  189. package/packages/datadog-core/src/utils/src/has.js +0 -14
  190. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
  191. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
@@ -124,9 +124,9 @@ function extractSessionDetails (authority, options) {
124
124
  }
125
125
 
126
126
  const protocol = authority.protocol || options.protocol || 'https:'
127
- let port = '' + (authority.port === ''
128
- ? (authority.protocol === 'http:' ? 80 : 443)
129
- : authority.port)
127
+ let port = authority.port === ''
128
+ ? authority.protocol === 'http:' ? '80' : '443'
129
+ : String(authority.port)
130
130
  let host = authority.hostname || authority.host || 'localhost'
131
131
 
132
132
  if (protocol === 'https:' && options) {
@@ -174,17 +174,16 @@ function normalizeConfig (config) {
174
174
  const filter = getFilter(config)
175
175
  const headers = getHeaders(config)
176
176
 
177
- return Object.assign({}, config, {
177
+ return {
178
+ ...config,
178
179
  validateStatus,
179
180
  filter,
180
181
  headers
181
- })
182
+ }
182
183
  }
183
184
 
184
185
  function getFilter (config) {
185
- config = Object.assign({}, config, {
186
- blocklist: config.blocklist || []
187
- })
186
+ config = { ...config, blocklist: config.blocklist || [] }
188
187
 
189
188
  return urlFilter.getFilter(config)
190
189
  }
@@ -1,5 +1,6 @@
1
1
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
2
  const { storage } = require('../../datadog-core')
3
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
3
4
 
4
5
  const {
5
6
  TEST_STATUS,
@@ -48,7 +49,7 @@ const {
48
49
  TELEMETRY_TEST_SESSION
49
50
  } = require('../../dd-trace/src/ci-visibility/telemetry')
50
51
 
51
- const isJestWorker = !!process.env.JEST_WORKER_ID
52
+ const isJestWorker = !!getEnvironmentVariable('JEST_WORKER_ID')
52
53
 
53
54
  // https://github.com/facebook/jest/blob/d6ad15b0f88a05816c2fe034dd6900d28315d570/packages/jest-worker/src/types.ts#L38
54
55
  const CHILD_MESSAGE_END = 2
@@ -158,7 +159,7 @@ class JestPlugin extends CiPlugin {
158
159
 
159
160
  this.telemetry.count(TELEMETRY_TEST_SESSION, {
160
161
  provider: this.ciProviderName,
161
- autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
162
+ autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
162
163
  })
163
164
 
164
165
  this.tracer._exporter.flush(() => {
@@ -2,6 +2,7 @@
2
2
 
3
3
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
4
4
  const { storage } = require('../../datadog-core')
5
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
5
6
 
6
7
  const {
7
8
  TEST_STATUS,
@@ -429,7 +430,7 @@ class MochaPlugin extends CiPlugin {
429
430
  finishAllTraceSpans(this.testSessionSpan)
430
431
  this.telemetry.count(TELEMETRY_TEST_SESSION, {
431
432
  provider: this.ciProviderName,
432
- autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
433
+ autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
433
434
  })
434
435
  }
435
436
  this.libraryConfig = null
@@ -466,6 +467,10 @@ class MochaPlugin extends CiPlugin {
466
467
  this.tracer._exporter.export(trace)
467
468
  })
468
469
  })
470
+
471
+ this.addBind('ci:mocha:global:run', (ctx) => {
472
+ return ctx.currentStore
473
+ })
469
474
  }
470
475
 
471
476
  startTestSpan (testInfo) {
@@ -3,6 +3,7 @@
3
3
  const { isTrue } = require('../../dd-trace/src/util')
4
4
  const DatabasePlugin = require('../../dd-trace/src/plugins/database')
5
5
  const coalesce = require('koalas')
6
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
6
7
 
7
8
  class MongodbCorePlugin extends DatabasePlugin {
8
9
  static get id () { return 'mongodb-core' }
@@ -14,7 +15,7 @@ class MongodbCorePlugin extends DatabasePlugin {
14
15
  configure (config) {
15
16
  super.configure(config)
16
17
 
17
- const heartbeatFromEnv = process.env.DD_TRACE_MONGODB_HEARTBEAT_ENABLED
18
+ const heartbeatFromEnv = getEnvironmentVariable('DD_TRACE_MONGODB_HEARTBEAT_ENABLED')
18
19
 
19
20
  this.config.heartbeatEnabled = coalesce(
20
21
  config.heartbeatEnabled,
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { storage } = require('../../datadog-core')
3
4
  const CLIENT_PORT_KEY = require('../../dd-trace/src/constants')
4
5
  const DatabasePlugin = require('../../dd-trace/src/plugins/database')
5
6
 
@@ -7,6 +8,16 @@ class MySQLPlugin extends DatabasePlugin {
7
8
  static get id () { return 'mysql' }
8
9
  static get system () { return 'mysql' }
9
10
 
11
+ constructor () {
12
+ super(...arguments)
13
+
14
+ this.addSub(`apm:${this.component}:connection:start`, ctx => {
15
+ ctx.parentStore = storage('legacy').getStore()
16
+ })
17
+
18
+ this.addBind(`apm:${this.component}:connection:finish`, ctx => ctx.parentStore)
19
+ }
20
+
10
21
  bindStart (ctx) {
11
22
  const service = this.serviceName({ pluginConfig: this.config, dbConfig: ctx.conf, system: this.system })
12
23
  const span = this.startSpan(this.operationName(), {
@@ -134,7 +134,7 @@ function normalizeConfig (config) {
134
134
  ? config.validateStatus
135
135
  : code => code < 500
136
136
 
137
- return Object.assign({}, config, { hooks, validateStatus })
137
+ return { ...config, hooks, validateStatus }
138
138
  }
139
139
 
140
140
  const noop = () => {}
@@ -766,19 +766,17 @@ function usageExtraction (tags, body, methodName, openaiStore) {
766
766
  } else if (body.model && ['chat.completions.create', 'completions.create'].includes(methodName)) {
767
767
  // estimate tokens based on method name for completions and chat completions
768
768
  const { model } = body
769
- let promptEstimated = false
770
- let completionEstimated = false
771
769
 
772
770
  // prompt tokens
773
771
  const payload = openaiStore
774
772
  const promptTokensCount = countPromptTokens(methodName, payload, model)
775
773
  promptTokens = promptTokensCount.promptTokens
776
- promptEstimated = promptTokensCount.promptEstimated
774
+ const promptEstimated = promptTokensCount.promptEstimated
777
775
 
778
776
  // completion tokens
779
777
  const completionTokensCount = countCompletionTokens(body, model)
780
778
  completionTokens = completionTokensCount.completionTokens
781
- completionEstimated = completionTokensCount.completionEstimated
779
+ const completionEstimated = completionTokensCount.completionEstimated
782
780
 
783
781
  // total tokens
784
782
  totalTokens = promptTokens + completionTokens
@@ -11,7 +11,8 @@ class OracledbPlugin extends DatabasePlugin {
11
11
 
12
12
  start ({ query, connAttrs }) {
13
13
  const service = this.serviceName({ pluginConfig: this.config, params: connAttrs })
14
- const url = getUrl(connAttrs.connectString)
14
+ // Users can pass either connectString or connectionString
15
+ const url = getUrl(connAttrs.connectString || connAttrs.connectionString)
15
16
 
16
17
  this.startSpan(this.operationName(), {
17
18
  service,
@@ -3,6 +3,7 @@
3
3
  const { storage } = require('../../datadog-core')
4
4
  const id = require('../../dd-trace/src/id')
5
5
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
6
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
6
7
 
7
8
  const {
8
9
  TEST_STATUS,
@@ -102,7 +103,7 @@ class PlaywrightPlugin extends CiPlugin {
102
103
  finishAllTraceSpans(this.testSessionSpan)
103
104
  this.telemetry.count(TELEMETRY_TEST_SESSION, {
104
105
  provider: this.ciProviderName,
105
- autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
106
+ autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
106
107
  })
107
108
  appClosingTelemetry()
108
109
  this.tracer._exporter.flush(onDone)
@@ -384,7 +385,7 @@ class PlaywrightPlugin extends CiPlugin {
384
385
  span.finish()
385
386
 
386
387
  finishAllTraceSpans(span)
387
- if (process.env.DD_PLAYWRIGHT_WORKER) {
388
+ if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) {
388
389
  this.tracer._exporter.flush(onDone)
389
390
  }
390
391
  })
@@ -102,17 +102,16 @@ class SchemaExtractor {
102
102
  }
103
103
  }
104
104
  return true
105
- } else {
106
- if (!builder.shouldExtractSchema(schemaName, depth)) {
107
- return false
108
- }
109
- for (const field of schema.fieldsArray) {
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}`)
112
- }
105
+ }
106
+ if (!builder.shouldExtractSchema(schemaName, depth)) {
107
+ return false
108
+ }
109
+ for (const field of schema.fieldsArray) {
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}`)
113
112
  }
114
- return true
115
113
  }
114
+ return true
116
115
  }
117
116
 
118
117
  static extractSchemas (descriptor, dataStreamsProcessor) {
@@ -77,9 +77,7 @@ function normalizeConfig (config) {
77
77
 
78
78
  const filter = urlFilter.getFilter(config)
79
79
 
80
- return Object.assign({}, config, {
81
- filter
82
- })
80
+ return { ...config, filter }
83
81
  }
84
82
 
85
83
  function uppercaseAllEntries (entries) {
@@ -1,5 +1,6 @@
1
1
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
2
  const { storage } = require('../../datadog-core')
3
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
3
4
 
4
5
  const {
5
6
  TEST_STATUS,
@@ -275,11 +276,11 @@ class VitestPlugin extends CiPlugin {
275
276
  this.addBind('ci:vitest:test-suite:start', (ctx) => {
276
277
  const { testSuiteAbsolutePath, frameworkVersion } = ctx
277
278
 
278
- this.command = process.env.DD_CIVISIBILITY_TEST_COMMAND
279
+ this.command = getEnvironmentVariable('DD_CIVISIBILITY_TEST_COMMAND')
279
280
  this.frameworkVersion = frameworkVersion
280
281
  const testSessionSpanContext = this.tracer.extract('text_map', {
281
- 'x-datadog-trace-id': process.env.DD_CIVISIBILITY_TEST_SESSION_ID,
282
- 'x-datadog-parent-id': process.env.DD_CIVISIBILITY_TEST_MODULE_ID
282
+ 'x-datadog-trace-id': getEnvironmentVariable('DD_CIVISIBILITY_TEST_SESSION_ID'),
283
+ 'x-datadog-parent-id': getEnvironmentVariable('DD_CIVISIBILITY_TEST_MODULE_ID')
283
284
  })
284
285
 
285
286
  const trimmedCommand = DD_MAJOR < 6 ? this.command : 'vitest run'
@@ -396,7 +397,7 @@ class VitestPlugin extends CiPlugin {
396
397
  finishAllTraceSpans(this.testSessionSpan)
397
398
  this.telemetry.count(TELEMETRY_TEST_SESSION, {
398
399
  provider: this.ciProviderName,
399
- autoInjected: !!process.env.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER
400
+ autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
400
401
  })
401
402
  this.tracer._exporter.flush(onFinish)
402
403
  })
@@ -5,7 +5,6 @@ module.exports = {
5
5
  COMMAND_INJECTION_ANALYZER: require('./command-injection-analyzer'),
6
6
  HARCODED_PASSWORD_ANALYZER: require('./hardcoded-password-analyzer'),
7
7
  HARCODED_SECRET_ANALYZER: require('./hardcoded-secret-analyzer'),
8
- HEADER_INJECTION_ANALYZER: require('./header-injection-analyzer'),
9
8
  HSTS_HEADER_MISSING_ANALYZER: require('./hsts-header-missing-analyzer'),
10
9
  INSECURE_COOKIE_ANALYZER: require('./insecure-cookie-analyzer'),
11
10
  LDAP_ANALYZER: require('./ldap-injection-analyzer'),
@@ -1,4 +1,3 @@
1
- /* eslint-disable @stylistic/max-len */
2
1
  'use strict'
3
2
 
4
3
  const { NameAndValue } = require('./hardcoded-rule-type')
@@ -1,4 +1,3 @@
1
- /* eslint-disable @stylistic/max-len */
2
1
  'use strict'
3
2
 
4
3
  const { ValueOnly, NameAndValue } = require('./hardcoded-rule-type')
@@ -1,4 +1,3 @@
1
- /* eslint-disable @stylistic/max-len */
2
1
  'use strict'
3
2
 
4
3
  const { ValueOnly, NameAndValue } = require('./hardcoded-rule-type')
@@ -32,9 +32,8 @@ class MissingHeaderAnalyzer extends Analyzer {
32
32
  const headerValue = res.getHeader(headerName)
33
33
  if (Array.isArray(headerValue)) {
34
34
  return headerValue
35
- } else {
36
- return headerValue ? [headerValue.toString()] : []
37
35
  }
36
+ return headerValue ? [headerValue.toString()] : []
38
37
  }
39
38
 
40
39
  _getLocation () {}
@@ -15,7 +15,7 @@ class SqlInjectionAnalyzer extends StoredInjectionAnalyzer {
15
15
 
16
16
  onConfigure () {
17
17
  this.addSub('apm:mysql:query:start', ({ sql }) => this.analyze(sql, undefined, 'MYSQL'))
18
- this.addSub('apm:mysql2:query:start', ({ sql }) => this.analyze(sql, undefined, 'MYSQL'))
18
+ this.addSub('datadog:mysql2:outerquery:start', ({ sql }) => this.analyze(sql, undefined, 'MYSQL'))
19
19
  this.addSub('apm:pg:query:start', ({ query }) => this.analyze(query.text, undefined, 'POSTGRES'))
20
20
 
21
21
  this.addSub(
@@ -85,7 +85,7 @@ function hookModule (filename, module, controlsByFile) {
85
85
  }
86
86
  })
87
87
  } catch (e) {
88
- log.error('[ASM] Error initializing IAST security control for %', filename, e)
88
+ log.error('[ASM] Error initializing IAST security control for %s', filename, e)
89
89
  }
90
90
 
91
91
  return module
@@ -150,19 +150,18 @@ function addSecureMarks (value, secureMarks, createNewTainted = true) {
150
150
 
151
151
  if (typeof value === 'string') {
152
152
  return TaintTrackingOperations.addSecureMark(iastContext, value, secureMarks, createNewTainted)
153
- } else {
154
- iterateObjectStrings(value, (value, levelKeys, parent, lastKey) => {
155
- try {
156
- const securedTainted = TaintTrackingOperations.addSecureMark(iastContext, value, secureMarks, createNewTainted)
157
- if (createNewTainted) {
158
- parent[lastKey] = securedTainted
159
- }
160
- } catch {
161
- // if it is a readonly property, do nothing
162
- }
163
- })
164
- return value
165
153
  }
154
+ iterateObjectStrings(value, (value, levelKeys, parent, lastKey) => {
155
+ try {
156
+ const securedTainted = TaintTrackingOperations.addSecureMark(iastContext, value, secureMarks, createNewTainted)
157
+ if (createNewTainted) {
158
+ parent[lastKey] = securedTainted
159
+ }
160
+ } catch {
161
+ // if it is a readonly property, do nothing
162
+ }
163
+ })
164
+ return value
166
165
  }
167
166
 
168
167
  function disable () {
@@ -2,8 +2,11 @@
2
2
 
3
3
  const TaintedUtils = require('@datadog/native-iast-taint-tracking')
4
4
  const { IAST_TRANSACTION_ID } = require('../iast-context')
5
+ const { HTTP_REQUEST_PARAMETER } = require('./source-types')
5
6
  const log = require('../../../log')
6
7
 
8
+ const SEPARATOR = '\u0000' // Unit Separator (cannot be in URL keys)
9
+
7
10
  function taintObject (iastContext, object, type) {
8
11
  let result = object
9
12
  const transactionId = iastContext?.[IAST_TRANSACTION_ID]
@@ -40,6 +43,46 @@ function taintObject (iastContext, object, type) {
40
43
  return result
41
44
  }
42
45
 
46
+ function taintQueryWithCache (iastContext, query) {
47
+ const transactionId = iastContext?.[IAST_TRANSACTION_ID]
48
+ if (!transactionId || !query) return query
49
+
50
+ iastContext.queryCache ??= new Map() // key: "a.b.c", value: tainted string
51
+
52
+ traverseAndTaint(query, '', iastContext.queryCache, transactionId)
53
+ return query
54
+ }
55
+
56
+ function traverseAndTaint (node, path, cache, transactionId) {
57
+ if (node == null) return node
58
+
59
+ if (typeof node === 'string') {
60
+ const cachedValue = cache.get(path)
61
+
62
+ if (cachedValue === node) {
63
+ return cachedValue
64
+ }
65
+
66
+ const tainted = TaintedUtils.newTaintedString(transactionId, node, path, HTTP_REQUEST_PARAMETER)
67
+ cache.set(path, tainted)
68
+
69
+ return tainted
70
+ }
71
+
72
+ if (typeof node === 'object') {
73
+ const keys = Array.isArray(node) ? node.keys() : Object.keys(node)
74
+
75
+ for (const key of keys) {
76
+ const childPath = path ? `${path}${SEPARATOR}${key}` : String(key)
77
+ const tainted = traverseAndTaint(node[key], childPath, cache, transactionId)
78
+ node[key] = tainted
79
+ }
80
+ }
81
+
82
+ return node
83
+ }
84
+
43
85
  module.exports = {
44
- taintObject
86
+ taintObject,
87
+ taintQueryWithCache
45
88
  }
@@ -11,7 +11,7 @@ const {
11
11
  getTaintTrackingNoop,
12
12
  lodashTaintTrackingHandler
13
13
  } = require('./taint-tracking-impl')
14
- const { taintObject } = require('./operations-taint-object')
14
+ const { taintObject, taintQueryWithCache } = require('./operations-taint-object')
15
15
 
16
16
  const lodashOperationCh = dc.channel('datadog:lodash:operation')
17
17
 
@@ -98,6 +98,7 @@ module.exports = {
98
98
  newTaintedString,
99
99
  newTaintedObject,
100
100
  taintObject,
101
+ taintQueryWithCache,
101
102
  isTainted,
102
103
  getRanges,
103
104
  enableTaintOperations,
@@ -3,7 +3,7 @@
3
3
  const { SourceIastPlugin } = require('../iast-plugin')
4
4
  const { getIastContext } = require('../iast-context')
5
5
  const { storage } = require('../../../../../datadog-core')
6
- const { taintObject, newTaintedString, getRanges } = require('./operations')
6
+ const { taintObject, newTaintedString, getRanges, taintQueryWithCache } = require('./operations')
7
7
  const {
8
8
  HTTP_REQUEST_BODY,
9
9
  HTTP_REQUEST_COOKIE_VALUE,
@@ -63,7 +63,12 @@ class TaintTrackingPlugin extends SourceIastPlugin {
63
63
 
64
64
  this.addSub(
65
65
  { channelName: 'datadog:express:query:finish', tag: HTTP_REQUEST_PARAMETER },
66
- ({ query }) => this._taintTrackingHandler(HTTP_REQUEST_PARAMETER, query)
66
+ ({ query }) => {
67
+ const iastContext = getIastContext(storage('legacy').getStore())
68
+ if (!iastContext || !query) return
69
+
70
+ taintQueryWithCache(iastContext, query)
71
+ }
67
72
  )
68
73
 
69
74
  this.addSub(
@@ -207,7 +212,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
207
212
 
208
213
  if (Array.isArray(result)) {
209
214
  for (let i = 0; i < result.length && i < this._rowsToTaint; i++) {
210
- const nextName = name ? `${name}.${i}` : '' + i
215
+ const nextName = name ? `${name}.${i}` : String(i)
211
216
  result[i] = this._taintDatabaseResult(result[i], dbOrigin, iastContext, nextName)
212
217
  }
213
218
  } else if (result && typeof result === 'object') {
@@ -14,6 +14,7 @@ const log = require('../../../log')
14
14
  const { isMainThread } = require('worker_threads')
15
15
  const { LOG_MESSAGE, REWRITTEN_MESSAGE } = require('./constants')
16
16
  const orchestrionConfig = require('../../../../../datadog-instrumentations/src/orchestrion-config')
17
+ const { getEnvironmentVariable } = require('../../../config-helper')
17
18
 
18
19
  let config
19
20
  const hardcodedSecretCh = dc.channel('datadog:secrets:result')
@@ -26,7 +27,7 @@ let kSymbolPrepareStackTrace
26
27
  function noop () {}
27
28
 
28
29
  function isFlagPresent (flag) {
29
- return process.env.NODE_OPTIONS?.includes(flag) ||
30
+ return getEnvironmentVariable('NODE_OPTIONS')?.includes(flag) ||
30
31
  process.execArgv?.some(arg => arg.includes(flag))
31
32
  }
32
33
 
@@ -45,7 +45,7 @@ function filterTags (tags) {
45
45
 
46
46
  function processTagValue (tags) {
47
47
  return tags.map(tag => tag.includes(':') ? tag.split(':')[1] : tag)
48
- .join('_').replace(/\./g, '_')
48
+ .join('_').replaceAll('.', '_')
49
49
  }
50
50
 
51
51
  module.exports = {
@@ -19,9 +19,8 @@ function getVerbosity (verbosity) {
19
19
  if (verbosity) {
20
20
  verbosity = verbosity.toUpperCase()
21
21
  return Verbosity[verbosity] === undefined ? Verbosity.INFORMATION : Verbosity[verbosity]
22
- } else {
23
- return Verbosity.INFORMATION
24
22
  }
23
+ return Verbosity.INFORMATION
25
24
  }
26
25
 
27
26
  function getName (verbosityValue) {
@@ -16,18 +16,17 @@ function remove (range, rangeToRemove) {
16
16
  return [range]
17
17
  } else if (contains(rangeToRemove, range)) {
18
18
  return []
19
- } else {
20
- const result = []
21
- if (rangeToRemove.start > range.start) {
22
- const offset = rangeToRemove.start - range.start
23
- result.push({ start: range.start, end: range.start + offset })
24
- }
25
- if (rangeToRemove.end < range.end) {
26
- const offset = range.end - rangeToRemove.end
27
- result.push({ start: rangeToRemove.end, end: rangeToRemove.end + offset })
28
- }
29
- return result
30
19
  }
20
+ const result = []
21
+ if (rangeToRemove.start > range.start) {
22
+ const offset = rangeToRemove.start - range.start
23
+ result.push({ start: range.start, end: range.start + offset })
24
+ }
25
+ if (rangeToRemove.end < range.end) {
26
+ const offset = range.end - rangeToRemove.end
27
+ result.push({ start: rangeToRemove.end, end: rangeToRemove.end + offset })
28
+ }
29
+ return result
31
30
  }
32
31
 
33
32
  module.exports = {
@@ -8,7 +8,6 @@ const { contains, intersects, remove } = require('./range-utils')
8
8
 
9
9
  const commandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
10
10
  const hardcodedPasswordAnalyzer = require('./sensitive-analyzers/hardcoded-password-analyzer')
11
- const headerSensitiveAnalyzer = require('./sensitive-analyzers/header-sensitive-analyzer')
12
11
  const jsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
13
12
  const ldapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
14
13
  const sqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
@@ -30,9 +29,6 @@ class SensitiveHandler {
30
29
  this._sensitiveAnalyzers.set(vulnerabilities.HARDCODED_PASSWORD, (evidence) => {
31
30
  return hardcodedPasswordAnalyzer(evidence, this._valuePattern)
32
31
  })
33
- this._sensitiveAnalyzers.set(vulnerabilities.HEADER_INJECTION, (evidence) => {
34
- return headerSensitiveAnalyzer(evidence, this._namePattern, this._valuePattern)
35
- })
36
32
  this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, ldapSensitiveAnalyzer)
37
33
  this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, jsonSensitiveAnalyzer)
38
34
  this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION, sqlSensitiveAnalyzer)
@@ -3,7 +3,6 @@ module.exports = {
3
3
  CODE_INJECTION: 'CODE_INJECTION',
4
4
  HARDCODED_PASSWORD: 'HARDCODED_PASSWORD',
5
5
  HARDCODED_SECRET: 'HARDCODED_SECRET',
6
- HEADER_INJECTION: 'HEADER_INJECTION',
7
6
  HSTS_HEADER_MISSING: 'HSTS_HEADER_MISSING',
8
7
  INSECURE_COOKIE: 'INSECURE_COOKIE',
9
8
  LDAP_INJECTION: 'LDAP_INJECTION',
@@ -37,6 +37,7 @@ const rasp = require('./rasp')
37
37
  const { isInServerlessEnvironment } = require('../serverless')
38
38
 
39
39
  const responseAnalyzedSet = new WeakSet()
40
+ const storedResponseHeaders = new WeakMap()
40
41
 
41
42
  let isEnabled = false
42
43
  let config
@@ -45,7 +46,7 @@ function enable (_config) {
45
46
  if (isEnabled) return
46
47
 
47
48
  try {
48
- appsecTelemetry.enable(_config.telemetry)
49
+ appsecTelemetry.enable(_config)
49
50
  graphql.enable()
50
51
 
51
52
  if (_config.appsec.rasp.enabled) {
@@ -139,7 +140,7 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
139
140
  [HTTP_CLIENT_IP]: clientIp
140
141
  })
141
142
 
142
- const requestHeaders = Object.assign({}, req.headers)
143
+ const requestHeaders = { ...req.headers }
143
144
  delete requestHeaders.cookie
144
145
 
145
146
  const persistent = {
@@ -187,7 +188,13 @@ function incomingHttpEndTranslator ({ req, res }) {
187
188
 
188
189
  waf.disposeContext(req)
189
190
 
190
- Reporter.finishRequest(req, res)
191
+ const storedHeaders = storedResponseHeaders.get(req) || {}
192
+
193
+ Reporter.finishRequest(req, res, storedHeaders)
194
+
195
+ if (storedHeaders) {
196
+ storedResponseHeaders.delete(req)
197
+ }
191
198
  }
192
199
 
193
200
  function onPassportVerify ({ framework, login, user, success, abortController }) {
@@ -285,6 +292,10 @@ function onResponseBody ({ req, res, body }) {
285
292
  }
286
293
 
287
294
  function onResponseWriteHead ({ req, res, abortController, statusCode, responseHeaders }) {
295
+ if (Object.keys(responseHeaders).length) {
296
+ storedResponseHeaders.set(req, responseHeaders)
297
+ }
298
+
288
299
  // avoid "write after end" error
289
300
  if (isBlocked(res)) {
290
301
  abortController?.abort()
@@ -299,12 +310,12 @@ function onResponseWriteHead ({ req, res, abortController, statusCode, responseH
299
310
  const rootSpan = web.root(req)
300
311
  if (!rootSpan) return
301
312
 
302
- responseHeaders = Object.assign({}, responseHeaders)
313
+ responseHeaders = { ...responseHeaders }
303
314
  delete responseHeaders['set-cookie']
304
315
 
305
316
  const results = waf.run({
306
317
  persistent: {
307
- [addresses.HTTP_INCOMING_RESPONSE_CODE]: '' + statusCode,
318
+ [addresses.HTTP_INCOMING_RESPONSE_CODE]: String(statusCode),
308
319
  [addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders
309
320
  }
310
321
  }, req)