dd-trace 3.12.0 → 3.13.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 (46) hide show
  1. package/ci/init.js +1 -0
  2. package/index.d.ts +50 -0
  3. package/package.json +1 -1
  4. package/packages/datadog-instrumentations/src/fs.js +357 -0
  5. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
  6. package/packages/datadog-instrumentations/src/helpers/register.js +0 -2
  7. package/packages/datadog-instrumentations/src/jest.js +11 -1
  8. package/packages/datadog-instrumentations/src/mocha.js +3 -2
  9. package/packages/datadog-instrumentations/src/mysql.js +7 -1
  10. package/packages/datadog-instrumentations/src/mysql2.js +7 -1
  11. package/packages/datadog-instrumentations/src/playwright.js +236 -0
  12. package/packages/datadog-plugin-fs/src/index.js +45 -0
  13. package/packages/datadog-plugin-jest/src/index.js +45 -23
  14. package/packages/datadog-plugin-mocha/src/index.js +34 -6
  15. package/packages/datadog-plugin-mysql/src/index.js +8 -7
  16. package/packages/datadog-plugin-playwright/src/index.js +171 -0
  17. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +1 -1
  18. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  19. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +60 -0
  20. package/packages/dd-trace/src/appsec/index.js +1 -1
  21. package/packages/dd-trace/src/appsec/recommended.json +247 -112
  22. package/packages/dd-trace/src/appsec/sdk/index.js +23 -0
  23. package/packages/dd-trace/src/appsec/sdk/noop.js +11 -0
  24. package/packages/dd-trace/src/appsec/sdk/track_event.js +74 -0
  25. package/packages/dd-trace/src/appsec/sdk/utils.js +10 -0
  26. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -1
  27. package/packages/dd-trace/src/config.js +7 -0
  28. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -4
  29. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +52 -37
  30. package/packages/dd-trace/src/lambda/runtime/patch.js +1 -1
  31. package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -11
  32. package/packages/dd-trace/src/log/channels.js +47 -0
  33. package/packages/dd-trace/src/log/index.js +79 -0
  34. package/packages/dd-trace/src/log/writer.js +108 -0
  35. package/packages/dd-trace/src/noop/proxy.js +3 -0
  36. package/packages/dd-trace/src/plugins/index.js +1 -0
  37. package/packages/dd-trace/src/plugins/util/ci.js +13 -21
  38. package/packages/dd-trace/src/{appsec → plugins/util}/ip_blocklist.js +0 -0
  39. package/packages/dd-trace/src/{appsec → plugins/util}/ip_extractor.js +1 -1
  40. package/packages/dd-trace/src/plugins/util/test.js +27 -10
  41. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -7
  42. package/packages/dd-trace/src/plugins/util/web.js +11 -0
  43. package/packages/dd-trace/src/proxy.js +2 -0
  44. package/packages/dd-trace/src/startup-log.js +1 -1
  45. package/scripts/check-proposal-labels.js +71 -0
  46. package/packages/dd-trace/src/log.js +0 -143
@@ -0,0 +1,171 @@
1
+ 'use strict'
2
+
3
+ const { storage } = require('../../datadog-core')
4
+ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
5
+
6
+ const {
7
+ TEST_STATUS,
8
+ finishAllTraceSpans,
9
+ getTestParentSpan,
10
+ getTestSessionCommonTags,
11
+ getTestSuitePath,
12
+ TEST_SESSION_ID,
13
+ TEST_COMMAND,
14
+ TEST_SUITE_ID,
15
+ getTestSuiteCommonTags,
16
+ getTestModuleCommonTags,
17
+ TEST_MODULE_ID,
18
+ TEST_BUNDLE
19
+ } = require('../../dd-trace/src/plugins/util/test')
20
+ const { RESOURCE_NAME } = require('../../../ext/tags')
21
+ const { COMPONENT } = require('../../dd-trace/src/constants')
22
+
23
+ class PlaywrightPlugin extends CiPlugin {
24
+ static get name () {
25
+ return 'playwright'
26
+ }
27
+
28
+ constructor (...args) {
29
+ super(...args)
30
+
31
+ this._testSuites = new Map()
32
+
33
+ this.addSub('ci:playwright:session:start', ({ command, frameworkVersion, rootDir }) => {
34
+ const childOf = getTestParentSpan(this.tracer)
35
+ this.command = command
36
+ this.frameworkVersion = frameworkVersion
37
+ this.rootDir = rootDir
38
+
39
+ const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion)
40
+ this.testSessionSpan = this.tracer.startSpan('playwright.test_session', {
41
+ childOf,
42
+ tags: {
43
+ [COMPONENT]: this.constructor.name,
44
+ ...this.testEnvironmentMetadata,
45
+ ...testSessionSpanMetadata
46
+ }
47
+ })
48
+ const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion)
49
+ this.testModuleSpan = this.tracer.startSpan('playwright.test_module', {
50
+ childOf: this.testSessionSpan,
51
+ tags: {
52
+ [COMPONENT]: this.constructor.name,
53
+ ...this.testEnvironmentMetadata,
54
+ ...testModuleSpanMetadata
55
+ }
56
+ })
57
+ })
58
+
59
+ this.addSub('ci:playwright:session:finish', ({ status, onDone }) => {
60
+ this.testModuleSpan.setTag(TEST_STATUS, status)
61
+ this.testSessionSpan.setTag(TEST_STATUS, status)
62
+
63
+ this.testModuleSpan.finish()
64
+ this.testSessionSpan.finish()
65
+ finishAllTraceSpans(this.testSessionSpan)
66
+ this.tracer._exporter.flush(onDone)
67
+ })
68
+
69
+ this.addSub('ci:playwright:test-suite:start', (testSuiteAbsolutePath) => {
70
+ const store = storage.getStore()
71
+ const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
72
+
73
+ const testSuiteMetadata = getTestSuiteCommonTags(
74
+ this.command,
75
+ this.frameworkVersion,
76
+ testSuite
77
+ )
78
+
79
+ const testSuiteSpan = this.tracer.startSpan('playwright.test_suite', {
80
+ childOf: this.testModuleSpan,
81
+ tags: {
82
+ [COMPONENT]: this.constructor.name,
83
+ ...this.testEnvironmentMetadata,
84
+ ...testSuiteMetadata
85
+ }
86
+ })
87
+ this.enter(testSuiteSpan, store)
88
+
89
+ this._testSuites.set(testSuite, testSuiteSpan)
90
+ })
91
+
92
+ this.addSub('ci:playwright:test-suite:finish', (status) => {
93
+ const store = storage.getStore()
94
+ const span = store && store.span
95
+ if (!span) return
96
+ span.setTag(TEST_STATUS, status)
97
+ span.finish()
98
+ })
99
+
100
+ this.addSub('ci:playwright:test:start', ({ testName, testSuiteAbsolutePath }) => {
101
+ const store = storage.getStore()
102
+ const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
103
+ const span = this.startTestSpan(testName, testSuite)
104
+
105
+ this.enter(span, store)
106
+ })
107
+ this.addSub('ci:playwright:test:finish', ({ testStatus, steps, error }) => {
108
+ const store = storage.getStore()
109
+ const span = store && store.span
110
+ if (!span) return
111
+
112
+ span.setTag(TEST_STATUS, testStatus)
113
+
114
+ if (error) {
115
+ span.setTag('error', error)
116
+ }
117
+
118
+ steps.forEach(step => {
119
+ const stepStartTime = step.startTime.getTime()
120
+ const stepSpan = this.tracer.startSpan('playwright.step', {
121
+ childOf: span,
122
+ startTime: stepStartTime,
123
+ tags: {
124
+ [COMPONENT]: this.constructor.name,
125
+ 'playwright.step': step.title,
126
+ [RESOURCE_NAME]: step.title
127
+ }
128
+ })
129
+ if (step.error) {
130
+ stepSpan.setTag('error', step.error)
131
+ }
132
+ stepSpan.finish(stepStartTime + step.duration)
133
+ })
134
+
135
+ span.finish()
136
+ finishAllTraceSpans(span)
137
+ })
138
+ }
139
+
140
+ startTestSpan (testName, testSuite) {
141
+ const childOf = getTestParentSpan(this.tracer)
142
+ // This is a hack to get good time resolution on test events, while keeping
143
+ // the test event as the root span of its trace.
144
+ childOf._trace.startTime = this.testSessionSpan.context()._trace.startTime
145
+ childOf._trace.ticks = this.testSessionSpan.context()._trace.ticks
146
+
147
+ const testSuiteTags = {}
148
+ const testSuiteSpan = this._testSuites.get(testSuite)
149
+ if (testSuiteSpan) {
150
+ const testSuiteId = testSuiteSpan.context().toSpanId()
151
+ testSuiteTags[TEST_SUITE_ID] = testSuiteId
152
+ }
153
+
154
+ if (this.testSessionSpan) {
155
+ const testSessionId = this.testSessionSpan.context().toTraceId()
156
+ testSuiteTags[TEST_SESSION_ID] = testSessionId
157
+ testSuiteTags[TEST_COMMAND] = this.command
158
+ }
159
+
160
+ if (this.testModuleSpan) {
161
+ const testModuleId = this.testModuleSpan.context().toSpanId()
162
+ testSuiteTags[TEST_MODULE_ID] = testModuleId
163
+ testSuiteTags[TEST_COMMAND] = this.command
164
+ testSuiteTags[TEST_BUNDLE] = this.command
165
+ }
166
+
167
+ return super.startTestSpan(testName, testSuite, testSuiteTags, childOf)
168
+ }
169
+ }
170
+
171
+ module.exports = PlaywrightPlugin
@@ -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()
@@ -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