dd-trace 3.12.1 → 3.15.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 (101) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/README.md +5 -5
  3. package/ci/init.js +3 -1
  4. package/index.d.ts +100 -1
  5. package/package.json +5 -4
  6. package/packages/datadog-instrumentations/src/aws-sdk.js +86 -0
  7. package/packages/datadog-instrumentations/src/cucumber.js +74 -15
  8. package/packages/datadog-instrumentations/src/cypress.js +1 -1
  9. package/packages/datadog-instrumentations/src/fs.js +358 -0
  10. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  11. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  12. package/packages/datadog-instrumentations/src/jest.js +24 -23
  13. package/packages/datadog-instrumentations/src/ldapjs.js +12 -2
  14. package/packages/datadog-instrumentations/src/mocha.js +10 -7
  15. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  16. package/packages/datadog-instrumentations/src/mysql.js +7 -1
  17. package/packages/datadog-instrumentations/src/mysql2.js +7 -1
  18. package/packages/datadog-instrumentations/src/next.js +2 -1
  19. package/packages/datadog-instrumentations/src/playwright.js +263 -0
  20. package/packages/datadog-plugin-aws-sdk/src/base.js +12 -5
  21. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -2
  22. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +29 -24
  23. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +31 -16
  24. package/packages/datadog-plugin-cucumber/src/index.js +42 -11
  25. package/packages/datadog-plugin-cypress/src/plugin.js +129 -4
  26. package/packages/datadog-plugin-cypress/src/support.js +5 -0
  27. package/packages/datadog-plugin-fs/src/index.js +45 -0
  28. package/packages/datadog-plugin-hapi/src/index.js +5 -1
  29. package/packages/datadog-plugin-http/src/server.js +1 -1
  30. package/packages/datadog-plugin-http2/src/server.js +1 -1
  31. package/packages/datadog-plugin-jest/src/index.js +40 -70
  32. package/packages/datadog-plugin-mocha/src/index.js +44 -64
  33. package/packages/datadog-plugin-mysql/src/index.js +8 -7
  34. package/packages/datadog-plugin-playwright/src/index.js +112 -0
  35. package/packages/datadog-shimmer/src/shimmer.js +28 -11
  36. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  37. package/packages/dd-trace/src/appsec/blocking.js +35 -9
  38. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +1 -1
  39. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  40. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +60 -0
  41. package/packages/dd-trace/src/appsec/iast/iast-context.js +6 -2
  42. package/packages/dd-trace/src/appsec/iast/index.js +3 -2
  43. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -2
  44. package/packages/dd-trace/src/appsec/index.js +5 -5
  45. package/packages/dd-trace/src/appsec/recommended.json +320 -184
  46. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
  47. package/packages/dd-trace/src/appsec/remote_config/index.js +3 -0
  48. package/packages/dd-trace/src/appsec/reporter.js +14 -14
  49. package/packages/dd-trace/src/appsec/sdk/index.js +41 -0
  50. package/packages/dd-trace/src/appsec/sdk/noop.js +17 -0
  51. package/packages/dd-trace/src/appsec/sdk/set_user.js +30 -0
  52. package/packages/dd-trace/src/appsec/sdk/track_event.js +74 -0
  53. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +73 -0
  54. package/packages/dd-trace/src/appsec/sdk/utils.js +10 -0
  55. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +1 -5
  56. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -5
  57. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +48 -11
  58. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -1
  59. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +4 -2
  60. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +5 -3
  61. package/packages/dd-trace/src/config.js +63 -7
  62. package/packages/dd-trace/src/encode/0.4.js +1 -1
  63. package/packages/dd-trace/src/encode/0.5.js +1 -1
  64. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -4
  65. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +52 -37
  66. package/packages/dd-trace/src/encode/tags-processors.js +3 -2
  67. package/packages/dd-trace/src/exporters/common/request.js +10 -3
  68. package/packages/dd-trace/src/lambda/handler.js +5 -6
  69. package/packages/dd-trace/src/log/channels.js +47 -0
  70. package/packages/dd-trace/src/log/index.js +79 -0
  71. package/packages/dd-trace/src/log/writer.js +124 -0
  72. package/packages/dd-trace/src/metrics.js +18 -0
  73. package/packages/dd-trace/src/noop/proxy.js +5 -2
  74. package/packages/dd-trace/src/opentracing/propagation/text_map.js +188 -36
  75. package/packages/dd-trace/src/opentracing/propagation/tracestate.js +99 -0
  76. package/packages/dd-trace/src/opentracing/span.js +2 -1
  77. package/packages/dd-trace/src/opentracing/span_context.js +6 -3
  78. package/packages/dd-trace/src/plugins/ci_plugin.js +72 -12
  79. package/packages/dd-trace/src/plugins/index.js +2 -0
  80. package/packages/dd-trace/src/plugins/util/ci.js +13 -21
  81. package/packages/dd-trace/src/plugins/util/exec.js +2 -2
  82. package/packages/dd-trace/src/plugins/util/git.js +16 -1
  83. package/packages/dd-trace/src/{appsec → plugins/util}/ip_extractor.js +1 -1
  84. package/packages/dd-trace/src/plugins/util/test.js +53 -10
  85. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -7
  86. package/packages/dd-trace/src/plugins/util/web.js +11 -0
  87. package/packages/dd-trace/src/profiler.js +3 -0
  88. package/packages/dd-trace/src/profiling/config.js +8 -3
  89. package/packages/dd-trace/src/profiling/exporters/file.js +13 -2
  90. package/packages/dd-trace/src/profiling/profiler.js +23 -6
  91. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -0
  92. package/packages/dd-trace/src/proxy.js +2 -0
  93. package/packages/dd-trace/src/span_processor.js +1 -1
  94. package/packages/dd-trace/src/span_sampler.js +68 -52
  95. package/packages/dd-trace/src/startup-log.js +3 -6
  96. package/packages/dd-trace/src/telemetry/index.js +23 -2
  97. package/packages/dd-trace/src/telemetry/send-data.js +4 -1
  98. package/packages/dd-trace/src/tracer.js +0 -16
  99. package/scripts/check-proposal-labels.js +71 -0
  100. package/packages/dd-trace/src/log.js +0 -143
  101. /package/packages/dd-trace/src/{appsec → plugins/util}/ip_blocklist.js +0 -0
@@ -1,8 +1,19 @@
1
1
  'use strict'
2
2
 
3
+ const log = require('../log')
3
4
  const fs = require('fs')
4
- let templateHtml, templateJson
5
- function block (req, res, topSpan, abortController) {
5
+
6
+ // TODO: move template loading to a proper spot.
7
+ let templateLoaded = false
8
+ let templateHtml = ''
9
+ let templateJson = ''
10
+
11
+ function block (req, res, rootSpan, abortController) {
12
+ if (res.headersSent) {
13
+ log.warn('Cannot send blocking response when headers have already been sent')
14
+ return
15
+ }
16
+
6
17
  let type
7
18
  let body
8
19
 
@@ -17,7 +28,7 @@ function block (req, res, topSpan, abortController) {
17
28
  body = templateJson
18
29
  }
19
30
 
20
- topSpan.addTags({
31
+ rootSpan.addTags({
21
32
  'appsec.blocked': 'true'
22
33
  })
23
34
 
@@ -26,19 +37,34 @@ function block (req, res, topSpan, abortController) {
26
37
  res.setHeader('Content-Length', Buffer.byteLength(body))
27
38
  res.end(body)
28
39
 
29
- abortController.abort()
40
+ if (abortController) {
41
+ abortController.abort()
42
+ }
30
43
  }
31
44
 
32
45
  function loadTemplates (config) {
33
- templateHtml = fs.readFileSync(config.appsec.blockedTemplateHtml)
34
- templateJson = fs.readFileSync(config.appsec.blockedTemplateJson)
46
+ if (!templateLoaded) {
47
+ templateHtml = fs.readFileSync(config.appsec.blockedTemplateHtml)
48
+ templateJson = fs.readFileSync(config.appsec.blockedTemplateJson)
49
+ templateLoaded = true
50
+ }
35
51
  }
36
52
 
37
53
  async function loadTemplatesAsync (config) {
38
- templateHtml = await fs.promises.readFile(config.appsec.blockedTemplateHtml)
39
- templateJson = await fs.promises.readFile(config.appsec.blockedTemplateJson)
54
+ if (!templateLoaded) {
55
+ templateHtml = await fs.promises.readFile(config.appsec.blockedTemplateHtml)
56
+ templateJson = await fs.promises.readFile(config.appsec.blockedTemplateJson)
57
+ templateLoaded = true
58
+ }
59
+ }
60
+
61
+ function resetTemplates () {
62
+ templateLoaded = false
40
63
  }
41
64
 
42
65
  module.exports = {
43
- block, loadTemplates, loadTemplatesAsync
66
+ block,
67
+ loadTemplates,
68
+ loadTemplatesAsync,
69
+ resetTemplates
44
70
  }
@@ -37,7 +37,7 @@ class WAFCallback {
37
37
  Reporter.metricsQueue.set('_dd.appsec.event_rules.error_count', failed)
38
38
  if (failed) Reporter.metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(errors))
39
39
 
40
- Reporter.metricsQueue.set('manual.keep', true)
40
+ Reporter.metricsQueue.set('manual.keep', 'true')
41
41
 
42
42
  this.wafContextCache = new WeakMap()
43
43
 
@@ -2,6 +2,7 @@ module.exports = {
2
2
  'WEAK_CIPHER_ANALYZER': require('./weak-cipher-analyzer'),
3
3
  'WEAK_HASH_ANALYZER': require('./weak-hash-analyzer'),
4
4
  'SQL_INJECTION_ANALYZER': require('./sql-injection-analyzer'),
5
+ 'PATH_TRAVERSAL_ANALYZER': require('./path-traversal-analyzer'),
5
6
  'COMMAND_INJECTION_ANALYZER': require('./command-injection-analyzer'),
6
7
  'LDAP_ANALYZER': require('./ldap-injection-analyzer')
7
8
  }
@@ -0,0 +1,60 @@
1
+ 'use strict'
2
+ const { getIastContext } = require('../iast-context')
3
+ const { storage } = require('../../../../../datadog-core')
4
+ const InjectionAnalyzer = require('./injection-analyzer')
5
+
6
+ class PathTraversalAnalyzer extends InjectionAnalyzer {
7
+ constructor () {
8
+ super('PATH_TRAVERSAL')
9
+ this.addSub('apm:fs:operation:start', obj => {
10
+ const pathArguments = []
11
+ if (obj.dest) {
12
+ pathArguments.push(obj.dest)
13
+ }
14
+ if (obj.existingPath) {
15
+ pathArguments.push(obj.existingPath)
16
+ }
17
+ if (obj.file) {
18
+ pathArguments.push(obj.file)
19
+ }
20
+ if (obj.newPath) {
21
+ pathArguments.push(obj.newPath)
22
+ }
23
+ if (obj.oldPath) {
24
+ pathArguments.push(obj.oldPath)
25
+ }
26
+ if (obj.path) {
27
+ pathArguments.push(obj.path)
28
+ }
29
+ if (obj.prefix) {
30
+ pathArguments.push(obj.prefix)
31
+ }
32
+ if (obj.src) {
33
+ pathArguments.push(obj.src)
34
+ }
35
+ if (obj.target) {
36
+ pathArguments.push(obj.target)
37
+ }
38
+ this.analyze(pathArguments)
39
+ })
40
+ }
41
+
42
+ analyze (value) {
43
+ const iastContext = getIastContext(storage.getStore())
44
+ if (!iastContext) {
45
+ return
46
+ }
47
+
48
+ if (value && value.constructor === Array) {
49
+ for (const val of value) {
50
+ if (this._isVulnerable(val, iastContext)) {
51
+ this._report(val, iastContext)
52
+ // no support several evidences in the same vulnerability, just report the 1st one
53
+ break
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ module.exports = new PathTraversalAnalyzer()
@@ -1,8 +1,12 @@
1
1
  const IAST_CONTEXT_KEY = Symbol('_dd.iast.context')
2
2
  const IAST_TRANSACTION_ID = Symbol('_dd.iast.transactionId')
3
3
 
4
- function getIastContext (store) {
5
- return store && store[IAST_CONTEXT_KEY]
4
+ function getIastContext (store, topContext) {
5
+ let iastContext = store && store[IAST_CONTEXT_KEY]
6
+ if (!iastContext) {
7
+ iastContext = topContext && topContext[IAST_CONTEXT_KEY]
8
+ }
9
+ return iastContext
6
10
  }
7
11
 
8
12
  /* TODO Fix storage problem when the close event is called without
@@ -58,7 +58,8 @@ function onIncomingHttpRequestStart (data) {
58
58
  function onIncomingHttpRequestEnd (data) {
59
59
  if (data && data.req) {
60
60
  const store = storage.getStore()
61
- const iastContext = iastContextFunctions.getIastContext(storage.getStore())
61
+ const topContext = web.getContext(data.req)
62
+ const iastContext = iastContextFunctions.getIastContext(store, topContext)
62
63
  if (iastContext && iastContext.rootSpan) {
63
64
  const vulnerabilities = iastContext.vulnerabilities
64
65
  const rootSpan = iastContext.rootSpan
@@ -66,7 +67,7 @@ function onIncomingHttpRequestEnd (data) {
66
67
  removeTransaction(iastContext)
67
68
  }
68
69
  // TODO web.getContext(data.req) is required when the request is aborted
69
- if (iastContextFunctions.cleanIastContext(store, web.getContext(data.req), iastContext)) {
70
+ if (iastContextFunctions.cleanIastContext(store, topContext, iastContext)) {
70
71
  overheadController.releaseRequest()
71
72
  }
72
73
  }
@@ -40,10 +40,13 @@ function getCompileMethodFn (compileMethod) {
40
40
  return function (content, filename) {
41
41
  try {
42
42
  if (isPrivateModule(filename) && isNotLibraryFile(filename)) {
43
- content = rewriter.rewrite(content, filename)
43
+ const rewritten = rewriter.rewrite(content, filename)
44
+ if (rewritten && rewritten.content) {
45
+ return compileMethod.apply(this, [rewritten.content, filename])
46
+ }
44
47
  }
45
48
  } catch (e) {
46
- log.debug(e)
49
+ log.error(e)
47
50
  }
48
51
  return compileMethod.apply(this, [content, filename])
49
52
  }
@@ -10,7 +10,7 @@ const Gateway = require('./gateway/engine')
10
10
  const addresses = require('./addresses')
11
11
  const Reporter = require('./reporter')
12
12
  const web = require('../plugins/util/web')
13
- const { extractIp } = require('./ip_extractor')
13
+ const { extractIp } = require('../plugins/util/ip_extractor')
14
14
  const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
15
15
  const { block, loadTemplates, loadTemplatesAsync } = require('./blocking')
16
16
 
@@ -70,12 +70,12 @@ function abortEnable (err) {
70
70
  }
71
71
 
72
72
  function incomingHttpStartTranslator ({ req, res, abortController }) {
73
- const topSpan = web.root(req)
74
- if (!topSpan) return
73
+ const rootSpan = web.root(req)
74
+ if (!rootSpan) return
75
75
 
76
76
  const clientIp = extractIp(config, req)
77
77
 
78
- topSpan.addTags({
78
+ rootSpan.addTags({
79
79
  '_dd.appsec.enabled': 1,
80
80
  '_dd.runtime_family': 'nodejs',
81
81
  [HTTP_CLIENT_IP]: clientIp
@@ -97,7 +97,7 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
97
97
 
98
98
  for (const entry of results) {
99
99
  if (entry && entry.includes('block')) {
100
- block(req, res, topSpan, abortController)
100
+ block(req, res, rootSpan, abortController)
101
101
  break
102
102
  }
103
103
  }