dd-trace 5.35.0 → 5.37.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.
- package/LICENSE-3rdparty.csv +2 -1
- package/index.d.ts +8 -7
- package/loader-hook.mjs +0 -4
- package/package.json +15 -14
- package/packages/datadog-core/index.js +1 -1
- package/packages/datadog-core/src/storage.js +76 -31
- package/packages/datadog-instrumentations/src/cucumber.js +54 -1
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
- package/packages/datadog-instrumentations/src/jest.js +105 -11
- package/packages/datadog-instrumentations/src/mocha/main.js +46 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +35 -2
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -0
- package/packages/datadog-instrumentations/src/mysql2.js +3 -3
- package/packages/datadog-instrumentations/src/openai.js +8 -0
- package/packages/datadog-instrumentations/src/playwright.js +70 -22
- package/packages/datadog-instrumentations/src/vitest.js +60 -6
- package/packages/datadog-plugin-aerospike/src/index.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/fetch.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
- package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -4
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -2
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +31 -14
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +72 -7
- package/packages/datadog-plugin-cypress/src/support.js +36 -29
- package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
- package/packages/datadog-plugin-graphql/src/utils.js +8 -1
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +1 -1
- package/packages/datadog-plugin-hapi/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +3 -3
- package/packages/datadog-plugin-http2/src/server.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +17 -12
- package/packages/datadog-plugin-langchain/src/tracing.js +1 -1
- package/packages/datadog-plugin-mariadb/src/index.js +3 -3
- package/packages/datadog-plugin-mocha/src/index.js +35 -16
- package/packages/datadog-plugin-mongodb-core/src/index.js +28 -2
- package/packages/datadog-plugin-next/src/index.js +4 -4
- package/packages/datadog-plugin-openai/src/tracing.js +2 -3
- package/packages/datadog-plugin-playwright/src/index.js +35 -9
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +2 -2
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +36 -12
- package/packages/dd-trace/src/appsec/graphql.js +6 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +3 -7
- package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +15 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +17 -30
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -11
- package/packages/dd-trace/src/appsec/iast/analyzers/stored-injection-analyzer.js +11 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +2 -6
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +24 -4
- package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/index.js +4 -2
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +187 -0
- package/packages/dd-trace/src/appsec/iast/security-controls/parser.js +96 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js +6 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -8
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +65 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +14 -5
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +80 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks-generator.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks.js +28 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +5 -0
- package/packages/dd-trace/src/appsec/iast/utils.js +24 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +8 -13
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +4 -4
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +5 -5
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +5 -5
- package/packages/dd-trace/src/appsec/rasp/lfi.js +3 -3
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +4 -4
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +3 -3
- package/packages/dd-trace/src/appsec/reporter.js +3 -3
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +2 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +31 -56
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +20 -2
- package/packages/dd-trace/src/ci-visibility/quarantined-tests/get-quarantined-tests.js +62 -0
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +5 -2
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +3 -3
- package/packages/dd-trace/src/config.js +18 -3
- package/packages/dd-trace/src/data_streams_context.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +14 -7
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +50 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +38 -10
- package/packages/dd-trace/src/exporters/common/agents.js +1 -1
- package/packages/dd-trace/src/exporters/common/request.js +3 -3
- package/packages/dd-trace/src/iitm.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +12 -2
- package/packages/dd-trace/src/log/writer.js +3 -3
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +5 -4
- package/packages/dd-trace/src/opentracing/span.js +3 -3
- package/packages/dd-trace/src/plugin_manager.js +3 -1
- package/packages/dd-trace/src/plugins/apollo.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +51 -4
- package/packages/dd-trace/src/plugins/database.js +14 -4
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +8 -8
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- package/packages/dd-trace/src/plugins/util/git.js +3 -3
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -3
- package/packages/dd-trace/src/plugins/util/test.js +10 -4
- package/packages/dd-trace/src/profiling/exporters/agent.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
- package/packages/dd-trace/src/proxy.js +5 -1
- package/packages/dd-trace/src/ritm.js +2 -1
- package/packages/dd-trace/src/scope.js +5 -5
- package/packages/dd-trace/src/spanleak.js +0 -1
- package/packages/dd-trace/src/tracer.js +0 -14
- package/packages/memwatch/package.json +0 -9
|
@@ -11,12 +11,15 @@ const {
|
|
|
11
11
|
TEST_SOURCE_START,
|
|
12
12
|
TEST_CODE_OWNERS,
|
|
13
13
|
TEST_SOURCE_FILE,
|
|
14
|
-
|
|
14
|
+
TEST_PARAMETERS,
|
|
15
15
|
TEST_IS_NEW,
|
|
16
16
|
TEST_IS_RETRY,
|
|
17
17
|
TEST_EARLY_FLAKE_ENABLED,
|
|
18
18
|
TELEMETRY_TEST_SESSION,
|
|
19
|
-
TEST_RETRY_REASON
|
|
19
|
+
TEST_RETRY_REASON,
|
|
20
|
+
TEST_MANAGEMENT_IS_QUARANTINED,
|
|
21
|
+
TEST_MANAGEMENT_ENABLED,
|
|
22
|
+
TEST_BROWSER_NAME
|
|
20
23
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
21
24
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
22
25
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
@@ -38,7 +41,12 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
38
41
|
this.numFailedTests = 0
|
|
39
42
|
this.numFailedSuites = 0
|
|
40
43
|
|
|
41
|
-
this.addSub('ci:playwright:session:finish', ({
|
|
44
|
+
this.addSub('ci:playwright:session:finish', ({
|
|
45
|
+
status,
|
|
46
|
+
isEarlyFlakeDetectionEnabled,
|
|
47
|
+
isQuarantinedTestsEnabled,
|
|
48
|
+
onDone
|
|
49
|
+
}) => {
|
|
42
50
|
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
43
51
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
44
52
|
|
|
@@ -56,6 +64,10 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
56
64
|
this.testSessionSpan.setTag('error', error)
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
if (isQuarantinedTestsEnabled) {
|
|
68
|
+
this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
this.testModuleSpan.finish()
|
|
60
72
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
61
73
|
this.testSessionSpan.finish()
|
|
@@ -68,7 +80,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
68
80
|
})
|
|
69
81
|
|
|
70
82
|
this.addSub('ci:playwright:test-suite:start', (testSuiteAbsolutePath) => {
|
|
71
|
-
const store = storage.getStore()
|
|
83
|
+
const store = storage('legacy').getStore()
|
|
72
84
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
|
|
73
85
|
const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
74
86
|
|
|
@@ -102,7 +114,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
102
114
|
})
|
|
103
115
|
|
|
104
116
|
this.addSub('ci:playwright:test-suite:finish', ({ status, error }) => {
|
|
105
|
-
const store = storage.getStore()
|
|
117
|
+
const store = storage('legacy').getStore()
|
|
106
118
|
const span = store && store.span
|
|
107
119
|
if (!span) return
|
|
108
120
|
if (error) {
|
|
@@ -121,15 +133,24 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
121
133
|
})
|
|
122
134
|
|
|
123
135
|
this.addSub('ci:playwright:test:start', ({ testName, testSuiteAbsolutePath, testSourceLine, browserName }) => {
|
|
124
|
-
const store = storage.getStore()
|
|
136
|
+
const store = storage('legacy').getStore()
|
|
125
137
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir)
|
|
126
138
|
const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
127
139
|
const span = this.startTestSpan(testName, testSuite, testSourceFile, testSourceLine, browserName)
|
|
128
140
|
|
|
129
141
|
this.enter(span, store)
|
|
130
142
|
})
|
|
131
|
-
this.addSub('ci:playwright:test:finish', ({
|
|
132
|
-
|
|
143
|
+
this.addSub('ci:playwright:test:finish', ({
|
|
144
|
+
testStatus,
|
|
145
|
+
steps,
|
|
146
|
+
error,
|
|
147
|
+
extraTags,
|
|
148
|
+
isNew,
|
|
149
|
+
isEfdRetry,
|
|
150
|
+
isRetry,
|
|
151
|
+
isQuarantined
|
|
152
|
+
}) => {
|
|
153
|
+
const store = storage('legacy').getStore()
|
|
133
154
|
const span = store && store.span
|
|
134
155
|
if (!span) return
|
|
135
156
|
|
|
@@ -151,6 +172,9 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
151
172
|
if (isRetry) {
|
|
152
173
|
span.setTag(TEST_IS_RETRY, 'true')
|
|
153
174
|
}
|
|
175
|
+
if (isQuarantined) {
|
|
176
|
+
span.setTag(TEST_MANAGEMENT_IS_QUARANTINED, 'true')
|
|
177
|
+
}
|
|
154
178
|
|
|
155
179
|
steps.forEach(step => {
|
|
156
180
|
const stepStartTime = step.startTime.getTime()
|
|
@@ -202,7 +226,9 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
202
226
|
extraTags[TEST_SOURCE_FILE] = testSourceFile || testSuite
|
|
203
227
|
}
|
|
204
228
|
if (browserName) {
|
|
205
|
-
|
|
229
|
+
// Added as parameter too because it should affect the test fingerprint
|
|
230
|
+
extraTags[TEST_PARAMETERS] = JSON.stringify({ arguments: { browser: browserName }, metadata: {} })
|
|
231
|
+
extraTags[TEST_BROWSER_NAME] = browserName
|
|
206
232
|
}
|
|
207
233
|
|
|
208
234
|
return super.startTestSpan(testName, testSuite, testSuiteSpan, extraTags)
|
|
@@ -11,7 +11,7 @@ class RheaConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
super(...args)
|
|
12
12
|
|
|
13
13
|
this.addTraceSub('dispatch', ({ state }) => {
|
|
14
|
-
const span = storage.getStore().span
|
|
14
|
+
const span = storage('legacy').getStore().span
|
|
15
15
|
span.setTag('amqp.delivery.state', state)
|
|
16
16
|
})
|
|
17
17
|
}
|
|
@@ -29,7 +29,7 @@ class RouterPlugin extends WebPlugin {
|
|
|
29
29
|
context.middleware.push(span)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const store = storage.getStore()
|
|
32
|
+
const store = storage('legacy').getStore()
|
|
33
33
|
this._storeStack.push(store)
|
|
34
34
|
this.enter(span, store)
|
|
35
35
|
|
|
@@ -94,7 +94,7 @@ class RouterPlugin extends WebPlugin {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
_getStoreSpan () {
|
|
97
|
-
const store = storage.getStore()
|
|
97
|
+
const store = storage('legacy').getStore()
|
|
98
98
|
|
|
99
99
|
return store && store.span
|
|
100
100
|
}
|
|
@@ -18,7 +18,9 @@ const {
|
|
|
18
18
|
TEST_IS_NEW,
|
|
19
19
|
TEST_EARLY_FLAKE_ENABLED,
|
|
20
20
|
TEST_EARLY_FLAKE_ABORT_REASON,
|
|
21
|
-
TEST_RETRY_REASON
|
|
21
|
+
TEST_RETRY_REASON,
|
|
22
|
+
TEST_MANAGEMENT_ENABLED,
|
|
23
|
+
TEST_MANAGEMENT_IS_QUARANTINED
|
|
22
24
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
23
25
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
24
26
|
const {
|
|
@@ -48,6 +50,20 @@ class VitestPlugin extends CiPlugin {
|
|
|
48
50
|
onDone(!testsForThisTestSuite.includes(testName))
|
|
49
51
|
})
|
|
50
52
|
|
|
53
|
+
this.addSub('ci:vitest:test:is-quarantined', ({ quarantinedTests, testSuiteAbsolutePath, testName, onDone }) => {
|
|
54
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
55
|
+
const isQuarantined = quarantinedTests
|
|
56
|
+
?.vitest
|
|
57
|
+
?.suites
|
|
58
|
+
?.[testSuite]
|
|
59
|
+
?.tests
|
|
60
|
+
?.[testName]
|
|
61
|
+
?.properties
|
|
62
|
+
?.quarantined
|
|
63
|
+
|
|
64
|
+
onDone(isQuarantined ?? false)
|
|
65
|
+
})
|
|
66
|
+
|
|
51
67
|
this.addSub('ci:vitest:is-early-flake-detection-faulty', ({
|
|
52
68
|
knownTests,
|
|
53
69
|
testFilepaths,
|
|
@@ -66,11 +82,12 @@ class VitestPlugin extends CiPlugin {
|
|
|
66
82
|
testSuiteAbsolutePath,
|
|
67
83
|
isRetry,
|
|
68
84
|
isNew,
|
|
85
|
+
isQuarantined,
|
|
69
86
|
mightHitProbe,
|
|
70
87
|
isRetryReasonEfd
|
|
71
88
|
}) => {
|
|
72
89
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
|
|
73
|
-
const store = storage.getStore()
|
|
90
|
+
const store = storage('legacy').getStore()
|
|
74
91
|
|
|
75
92
|
const extraTags = {
|
|
76
93
|
[TEST_SOURCE_FILE]: testSuite
|
|
@@ -84,6 +101,9 @@ class VitestPlugin extends CiPlugin {
|
|
|
84
101
|
if (isRetryReasonEfd) {
|
|
85
102
|
extraTags[TEST_RETRY_REASON] = 'efd'
|
|
86
103
|
}
|
|
104
|
+
if (isQuarantined) {
|
|
105
|
+
extraTags[TEST_MANAGEMENT_IS_QUARANTINED] = 'true'
|
|
106
|
+
}
|
|
87
107
|
|
|
88
108
|
const span = this.startTestSpan(
|
|
89
109
|
testName,
|
|
@@ -102,7 +122,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
102
122
|
})
|
|
103
123
|
|
|
104
124
|
this.addSub('ci:vitest:test:finish-time', ({ status, task }) => {
|
|
105
|
-
const store = storage.getStore()
|
|
125
|
+
const store = storage('legacy').getStore()
|
|
106
126
|
const span = store?.span
|
|
107
127
|
|
|
108
128
|
// we store the finish time to finish at a later hook
|
|
@@ -114,7 +134,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
114
134
|
})
|
|
115
135
|
|
|
116
136
|
this.addSub('ci:vitest:test:pass', ({ task }) => {
|
|
117
|
-
const store = storage.getStore()
|
|
137
|
+
const store = storage('legacy').getStore()
|
|
118
138
|
const span = store?.span
|
|
119
139
|
|
|
120
140
|
if (span) {
|
|
@@ -128,15 +148,15 @@ class VitestPlugin extends CiPlugin {
|
|
|
128
148
|
})
|
|
129
149
|
|
|
130
150
|
this.addSub('ci:vitest:test:error', ({ duration, error, shouldSetProbe, promises }) => {
|
|
131
|
-
const store = storage.getStore()
|
|
151
|
+
const store = storage('legacy').getStore()
|
|
132
152
|
const span = store?.span
|
|
133
153
|
|
|
134
154
|
if (span) {
|
|
135
155
|
if (shouldSetProbe && this.di) {
|
|
136
156
|
const probeInformation = this.addDiProbe(error)
|
|
137
157
|
if (probeInformation) {
|
|
138
|
-
const {
|
|
139
|
-
this.
|
|
158
|
+
const { file, line, stackIndex, setProbePromise } = probeInformation
|
|
159
|
+
this.runningTestProbe = { file, line }
|
|
140
160
|
this.testErrorStackIndex = stackIndex
|
|
141
161
|
promises.setProbePromise = setProbePromise
|
|
142
162
|
}
|
|
@@ -221,13 +241,13 @@ class VitestPlugin extends CiPlugin {
|
|
|
221
241
|
}
|
|
222
242
|
})
|
|
223
243
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
224
|
-
const store = storage.getStore()
|
|
244
|
+
const store = storage('legacy').getStore()
|
|
225
245
|
this.enter(testSuiteSpan, store)
|
|
226
246
|
this.testSuiteSpan = testSuiteSpan
|
|
227
247
|
})
|
|
228
248
|
|
|
229
249
|
this.addSub('ci:vitest:test-suite:finish', ({ status, onFinish }) => {
|
|
230
|
-
const store = storage.getStore()
|
|
250
|
+
const store = storage('legacy').getStore()
|
|
231
251
|
const span = store?.span
|
|
232
252
|
if (span) {
|
|
233
253
|
span.setTag(TEST_STATUS, status)
|
|
@@ -237,13 +257,13 @@ class VitestPlugin extends CiPlugin {
|
|
|
237
257
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
238
258
|
// TODO: too frequent flush - find for method in worker to decrease frequency
|
|
239
259
|
this.tracer._exporter.flush(onFinish)
|
|
240
|
-
if (this.
|
|
241
|
-
this.removeDiProbe(this.
|
|
260
|
+
if (this.runningTestProbe) {
|
|
261
|
+
this.removeDiProbe(this.runningTestProbe)
|
|
242
262
|
}
|
|
243
263
|
})
|
|
244
264
|
|
|
245
265
|
this.addSub('ci:vitest:test-suite:error', ({ error }) => {
|
|
246
|
-
const store = storage.getStore()
|
|
266
|
+
const store = storage('legacy').getStore()
|
|
247
267
|
const span = store?.span
|
|
248
268
|
if (span && error) {
|
|
249
269
|
span.setTag('error', error)
|
|
@@ -257,6 +277,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
257
277
|
testCodeCoverageLinesTotal,
|
|
258
278
|
isEarlyFlakeDetectionEnabled,
|
|
259
279
|
isEarlyFlakeDetectionFaulty,
|
|
280
|
+
isQuarantinedTestsEnabled,
|
|
260
281
|
onFinish
|
|
261
282
|
}) => {
|
|
262
283
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
@@ -275,6 +296,9 @@ class VitestPlugin extends CiPlugin {
|
|
|
275
296
|
if (isEarlyFlakeDetectionFaulty) {
|
|
276
297
|
this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
|
|
277
298
|
}
|
|
299
|
+
if (isQuarantinedTestsEnabled) {
|
|
300
|
+
this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
|
|
301
|
+
}
|
|
278
302
|
this.testModuleSpan.finish()
|
|
279
303
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
280
304
|
this.testSessionSpan.finish()
|
|
@@ -30,7 +30,7 @@ function disable () {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function onGraphqlStartResolve ({ context, resolverInfo }) {
|
|
33
|
-
const req = storage.getStore()?.req
|
|
33
|
+
const req = storage('legacy').getStore()?.req
|
|
34
34
|
|
|
35
35
|
if (!req) return
|
|
36
36
|
|
|
@@ -49,7 +49,7 @@ function onGraphqlStartResolve ({ context, resolverInfo }) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function enterInApolloMiddleware (data) {
|
|
52
|
-
const req = data?.req || storage.getStore()?.req
|
|
52
|
+
const req = data?.req || storage('legacy').getStore()?.req
|
|
53
53
|
if (!req) return
|
|
54
54
|
|
|
55
55
|
graphqlRequestData.set(req, {
|
|
@@ -59,7 +59,7 @@ function enterInApolloMiddleware (data) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function enterInApolloServerCoreRequest () {
|
|
62
|
-
const req = storage.getStore()?.req
|
|
62
|
+
const req = storage('legacy').getStore()?.req
|
|
63
63
|
if (!req) return
|
|
64
64
|
|
|
65
65
|
graphqlRequestData.set(req, {
|
|
@@ -69,13 +69,13 @@ function enterInApolloServerCoreRequest () {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function exitFromApolloMiddleware (data) {
|
|
72
|
-
const req = data?.req || storage.getStore()?.req
|
|
72
|
+
const req = data?.req || storage('legacy').getStore()?.req
|
|
73
73
|
const requestData = graphqlRequestData.get(req)
|
|
74
74
|
if (requestData) requestData.inApolloMiddleware = false
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function enterInApolloRequest () {
|
|
78
|
-
const req = storage.getStore()?.req
|
|
78
|
+
const req = storage('legacy').getStore()?.req
|
|
79
79
|
|
|
80
80
|
const requestData = graphqlRequestData.get(req)
|
|
81
81
|
if (requestData?.inApolloMiddleware) {
|
|
@@ -85,7 +85,7 @@ function enterInApolloRequest () {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function beforeWriteApolloGraphqlResponse ({ abortController, abortData }) {
|
|
88
|
-
const req = storage.getStore()?.req
|
|
88
|
+
const req = storage('legacy').getStore()?.req
|
|
89
89
|
if (!req) return
|
|
90
90
|
|
|
91
91
|
const requestData = graphqlRequestData.get(req)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const InjectionAnalyzer = require('./injection-analyzer')
|
|
4
3
|
const { CODE_INJECTION } = require('../vulnerabilities')
|
|
4
|
+
const StoredInjectionAnalyzer = require('./stored-injection-analyzer')
|
|
5
5
|
const { INSTRUMENTED_SINK } = require('../telemetry/iast-metric')
|
|
6
6
|
const { storage } = require('../../../../../datadog-core')
|
|
7
7
|
const { getIastContext } = require('../iast-context')
|
|
8
8
|
|
|
9
|
-
class CodeInjectionAnalyzer extends
|
|
9
|
+
class CodeInjectionAnalyzer extends StoredInjectionAnalyzer {
|
|
10
10
|
constructor () {
|
|
11
11
|
super(CODE_INJECTION)
|
|
12
12
|
this.evalInstrumentedInc = false
|
|
@@ -15,7 +15,7 @@ class CodeInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
15
15
|
onConfigure () {
|
|
16
16
|
this.addSub('datadog:eval:call', ({ script }) => {
|
|
17
17
|
if (!this.evalInstrumentedInc) {
|
|
18
|
-
const store = storage.getStore()
|
|
18
|
+
const store = storage('legacy').getStore()
|
|
19
19
|
const iastContext = getIastContext(store)
|
|
20
20
|
const tags = INSTRUMENTED_SINK.formatTags(CODE_INJECTION)
|
|
21
21
|
|
|
@@ -31,10 +31,6 @@ class CodeInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
31
31
|
this.addSub('datadog:vm:run-script:start', ({ code }) => this.analyze(code))
|
|
32
32
|
this.addSub('datadog:vm:source-text-module:start', ({ code }) => this.analyze(code))
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
_areRangesVulnerable () {
|
|
36
|
-
return true
|
|
37
|
-
}
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
module.exports = new CodeInjectionAnalyzer()
|
|
@@ -5,8 +5,13 @@ const { SQL_ROW_VALUE } = require('../taint-tracking/source-types')
|
|
|
5
5
|
|
|
6
6
|
class InjectionAnalyzer extends Analyzer {
|
|
7
7
|
_isVulnerable (value, iastContext) {
|
|
8
|
-
|
|
8
|
+
let ranges = value && getRanges(iastContext, value)
|
|
9
9
|
if (ranges?.length > 0) {
|
|
10
|
+
ranges = this._filterSecureRanges(ranges)
|
|
11
|
+
if (!ranges?.length) {
|
|
12
|
+
this._incrementSuppressedMetric(iastContext)
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
return this._areRangesVulnerable(ranges)
|
|
11
16
|
}
|
|
12
17
|
|
|
@@ -21,6 +26,15 @@ class InjectionAnalyzer extends Analyzer {
|
|
|
21
26
|
_areRangesVulnerable (ranges) {
|
|
22
27
|
return ranges?.some(range => range.iinfo.type !== SQL_ROW_VALUE)
|
|
23
28
|
}
|
|
29
|
+
|
|
30
|
+
_filterSecureRanges (ranges) {
|
|
31
|
+
return ranges?.filter(range => !this._isRangeSecure(range))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_isRangeSecure (range) {
|
|
35
|
+
const { secureMarks } = range
|
|
36
|
+
return (secureMarks & this._secureMark) === this._secureMark
|
|
37
|
+
}
|
|
24
38
|
}
|
|
25
39
|
|
|
26
40
|
module.exports = InjectionAnalyzer
|
|
@@ -4,29 +4,13 @@ const InjectionAnalyzer = require('./injection-analyzer')
|
|
|
4
4
|
const { NOSQL_MONGODB_INJECTION } = require('../vulnerabilities')
|
|
5
5
|
const { getRanges, addSecureMark } = require('../taint-tracking/operations')
|
|
6
6
|
const { getNodeModulesPaths } = require('../path-line')
|
|
7
|
-
const { getNextSecureMark } = require('../taint-tracking/secure-marks-generator')
|
|
8
7
|
const { storage } = require('../../../../../datadog-core')
|
|
9
8
|
const { getIastContext } = require('../iast-context')
|
|
10
9
|
const { HTTP_REQUEST_PARAMETER, HTTP_REQUEST_BODY } = require('../taint-tracking/source-types')
|
|
11
10
|
|
|
12
11
|
const EXCLUDED_PATHS_FROM_STACK = getNodeModulesPaths('mongodb', 'mongoose', 'mquery')
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
function iterateObjectStrings (target, fn, levelKeys = [], depth = 20, visited = new Set()) {
|
|
16
|
-
if (target !== null && typeof target === 'object') {
|
|
17
|
-
Object.keys(target).forEach((key) => {
|
|
18
|
-
const nextLevelKeys = [...levelKeys, key]
|
|
19
|
-
const val = target[key]
|
|
20
|
-
|
|
21
|
-
if (typeof val === 'string') {
|
|
22
|
-
fn(val, nextLevelKeys, target, key)
|
|
23
|
-
} else if (depth > 0 && !visited.has(val)) {
|
|
24
|
-
iterateObjectStrings(val, fn, nextLevelKeys, depth - 1, visited)
|
|
25
|
-
visited.add(val)
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
}
|
|
12
|
+
const { NOSQL_MONGODB_INJECTION_MARK } = require('../taint-tracking/secure-marks')
|
|
13
|
+
const { iterateObjectStrings } = require('../utils')
|
|
30
14
|
|
|
31
15
|
class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
32
16
|
constructor () {
|
|
@@ -38,7 +22,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
38
22
|
this.configureSanitizers()
|
|
39
23
|
|
|
40
24
|
const onStart = ({ filters }) => {
|
|
41
|
-
const store = storage.getStore()
|
|
25
|
+
const store = storage('legacy').getStore()
|
|
42
26
|
if (store && !store.nosqlAnalyzed && filters?.length) {
|
|
43
27
|
filters.forEach(filter => {
|
|
44
28
|
this.analyze({ filter }, store)
|
|
@@ -51,14 +35,14 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
51
35
|
const onStartAndEnterWithStore = (message) => {
|
|
52
36
|
const store = onStart(message || {})
|
|
53
37
|
if (store) {
|
|
54
|
-
storage.enterWith({ ...store, nosqlAnalyzed: true, nosqlParentStore: store })
|
|
38
|
+
storage('legacy').enterWith({ ...store, nosqlAnalyzed: true, nosqlParentStore: store })
|
|
55
39
|
}
|
|
56
40
|
}
|
|
57
41
|
|
|
58
42
|
const onFinish = () => {
|
|
59
|
-
const store = storage.getStore()
|
|
43
|
+
const store = storage('legacy').getStore()
|
|
60
44
|
if (store?.nosqlParentStore) {
|
|
61
|
-
storage.enterWith(store.nosqlParentStore)
|
|
45
|
+
storage('legacy').enterWith(store.nosqlParentStore)
|
|
62
46
|
}
|
|
63
47
|
}
|
|
64
48
|
|
|
@@ -74,7 +58,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
74
58
|
|
|
75
59
|
configureSanitizers () {
|
|
76
60
|
this.addNotSinkSub('datadog:express-mongo-sanitize:filter:finish', ({ sanitizedProperties, req }) => {
|
|
77
|
-
const store = storage.getStore()
|
|
61
|
+
const store = storage('legacy').getStore()
|
|
78
62
|
const iastContext = getIastContext(store)
|
|
79
63
|
|
|
80
64
|
if (iastContext) { // do nothing if we are not in an iast request
|
|
@@ -88,7 +72,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
88
72
|
const currentLevelKey = levelKeys[i]
|
|
89
73
|
|
|
90
74
|
if (i === levelsLength - 1) {
|
|
91
|
-
parentObj[currentLevelKey] = addSecureMark(iastContext, value,
|
|
75
|
+
parentObj[currentLevelKey] = addSecureMark(iastContext, value, NOSQL_MONGODB_INJECTION_MARK)
|
|
92
76
|
} else {
|
|
93
77
|
parentObj = parentObj[currentLevelKey]
|
|
94
78
|
}
|
|
@@ -100,13 +84,13 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
100
84
|
})
|
|
101
85
|
|
|
102
86
|
this.addNotSinkSub('datadog:express-mongo-sanitize:sanitize:finish', ({ sanitizedObject }) => {
|
|
103
|
-
const store = storage.getStore()
|
|
87
|
+
const store = storage('legacy').getStore()
|
|
104
88
|
const iastContext = getIastContext(store)
|
|
105
89
|
|
|
106
90
|
if (iastContext) { // do nothing if we are not in an iast request
|
|
107
91
|
iterateObjectStrings(sanitizedObject, function (value, levelKeys, parent, lastKey) {
|
|
108
92
|
try {
|
|
109
|
-
parent[lastKey] = addSecureMark(iastContext, value,
|
|
93
|
+
parent[lastKey] = addSecureMark(iastContext, value, NOSQL_MONGODB_INJECTION_MARK)
|
|
110
94
|
} catch {
|
|
111
95
|
// if it is a readonly property, do nothing
|
|
112
96
|
}
|
|
@@ -121,8 +105,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
121
105
|
|
|
122
106
|
_isVulnerableRange (range) {
|
|
123
107
|
const rangeType = range?.iinfo?.type
|
|
124
|
-
|
|
125
|
-
return isVulnerableType && (range.secureMarks & MONGODB_NOSQL_SECURE_MARK) !== MONGODB_NOSQL_SECURE_MARK
|
|
108
|
+
return rangeType === HTTP_REQUEST_PARAMETER || rangeType === HTTP_REQUEST_BODY
|
|
126
109
|
}
|
|
127
110
|
|
|
128
111
|
_isVulnerable (value, iastContext) {
|
|
@@ -137,10 +120,15 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
137
120
|
const allRanges = []
|
|
138
121
|
|
|
139
122
|
iterateObjectStrings(value.filter, (val, nextLevelKeys) => {
|
|
140
|
-
|
|
123
|
+
let ranges = getRanges(iastContext, val)
|
|
141
124
|
if (ranges?.length) {
|
|
142
125
|
const filteredRanges = []
|
|
143
126
|
|
|
127
|
+
ranges = this._filterSecureRanges(ranges)
|
|
128
|
+
if (!ranges.length) {
|
|
129
|
+
this._incrementSuppressedMetric(iastContext)
|
|
130
|
+
}
|
|
131
|
+
|
|
144
132
|
for (const range of ranges) {
|
|
145
133
|
if (this._isVulnerableRange(range)) {
|
|
146
134
|
isVulnerable = true
|
|
@@ -175,4 +163,3 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer {
|
|
|
175
163
|
}
|
|
176
164
|
|
|
177
165
|
module.exports = new NosqlInjectionMongodbAnalyzer()
|
|
178
|
-
module.exports.MONGODB_NOSQL_SECURE_MARK = MONGODB_NOSQL_SECURE_MARK
|
|
@@ -29,7 +29,7 @@ class PathTraversalAnalyzer extends InjectionAnalyzer {
|
|
|
29
29
|
|
|
30
30
|
onConfigure () {
|
|
31
31
|
this.addSub('apm:fs:operation:start', (obj) => {
|
|
32
|
-
const store = storage.getStore()
|
|
32
|
+
const store = storage('legacy').getStore()
|
|
33
33
|
const outOfReqOrChild = !store?.fs?.root
|
|
34
34
|
|
|
35
35
|
// we could filter out all the nested fs.operations based on store.fs.root
|
|
@@ -84,7 +84,7 @@ class PathTraversalAnalyzer extends InjectionAnalyzer {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
analyze (value) {
|
|
87
|
-
const iastContext = getIastContext(storage.getStore())
|
|
87
|
+
const iastContext = getIastContext(storage('legacy').getStore())
|
|
88
88
|
if (!iastContext) {
|
|
89
89
|
return
|
|
90
90
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const InjectionAnalyzer = require('./injection-analyzer')
|
|
4
3
|
const { SQL_INJECTION } = require('../vulnerabilities')
|
|
5
4
|
const { getRanges } = require('../taint-tracking/operations')
|
|
6
5
|
const { storage } = require('../../../../../datadog-core')
|
|
7
6
|
const { getNodeModulesPaths } = require('../path-line')
|
|
7
|
+
const StoredInjectionAnalyzer = require('./stored-injection-analyzer')
|
|
8
8
|
|
|
9
9
|
const EXCLUDED_PATHS = getNodeModulesPaths('mysql', 'mysql2', 'sequelize', 'pg-pool', 'knex')
|
|
10
10
|
|
|
11
|
-
class SqlInjectionAnalyzer extends
|
|
11
|
+
class SqlInjectionAnalyzer extends StoredInjectionAnalyzer {
|
|
12
12
|
constructor () {
|
|
13
13
|
super(SQL_INJECTION)
|
|
14
14
|
}
|
|
@@ -38,18 +38,18 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
getStoreAndAnalyze (query, dialect) {
|
|
41
|
-
const parentStore = storage.getStore()
|
|
41
|
+
const parentStore = storage('legacy').getStore()
|
|
42
42
|
if (parentStore) {
|
|
43
43
|
this.analyze(query, parentStore, dialect)
|
|
44
44
|
|
|
45
|
-
storage.enterWith({ ...parentStore, sqlAnalyzed: true, sqlParentStore: parentStore })
|
|
45
|
+
storage('legacy').enterWith({ ...parentStore, sqlAnalyzed: true, sqlParentStore: parentStore })
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
returnToParentStore () {
|
|
50
|
-
const store = storage.getStore()
|
|
50
|
+
const store = storage('legacy').getStore()
|
|
51
51
|
if (store && store.sqlParentStore) {
|
|
52
|
-
storage.enterWith(store.sqlParentStore)
|
|
52
|
+
storage('legacy').enterWith(store.sqlParentStore)
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -59,7 +59,7 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
analyze (value, store, dialect) {
|
|
62
|
-
store = store || storage.getStore()
|
|
62
|
+
store = store || storage('legacy').getStore()
|
|
63
63
|
if (!(store && store.sqlAnalyzed)) {
|
|
64
64
|
super.analyze(value, store, dialect)
|
|
65
65
|
}
|
|
@@ -82,10 +82,6 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
82
82
|
return knexDialect.toUpperCase()
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
_areRangesVulnerable () {
|
|
87
|
-
return true
|
|
88
|
-
}
|
|
89
85
|
}
|
|
90
86
|
|
|
91
87
|
module.exports = new SqlInjectionAnalyzer()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const InjectionAnalyzer = require('./injection-analyzer')
|
|
4
3
|
const { TEMPLATE_INJECTION } = require('../vulnerabilities')
|
|
4
|
+
const StoredInjectionAnalyzer = require('./stored-injection-analyzer')
|
|
5
5
|
|
|
6
|
-
class TemplateInjectionAnalyzer extends
|
|
6
|
+
class TemplateInjectionAnalyzer extends StoredInjectionAnalyzer {
|
|
7
7
|
constructor () {
|
|
8
8
|
super(TEMPLATE_INJECTION)
|
|
9
9
|
}
|
|
@@ -13,10 +13,6 @@ class TemplateInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
13
13
|
this.addSub('datadog:handlebars:register-partial:start', ({ partial }) => this.analyze(partial))
|
|
14
14
|
this.addSub('datadog:pug:compile:start', ({ source }) => this.analyze(source))
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
_areRangesVulnerable () {
|
|
18
|
-
return true
|
|
19
|
-
}
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
module.exports = new TemplateInjectionAnalyzer()
|