dd-trace 3.11.0 → 3.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +1 -0
- package/index.d.ts +16 -0
- package/package.json +6 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +5 -0
- package/packages/datadog-instrumentations/src/mocha.js +33 -8
- package/packages/datadog-instrumentations/src/pg.js +6 -1
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +6 -6
- package/packages/dd-trace/src/appsec/iast/index.js +8 -3
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +6 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +24 -6
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +63 -41
- package/packages/dd-trace/src/appsec/recommended.json +75 -8
- package/packages/dd-trace/src/appsec/remote_config/manager.js +2 -2
- package/packages/dd-trace/src/config.js +24 -5
- package/packages/dd-trace/src/exporters/common/request.js +33 -1
- package/packages/dd-trace/src/format.js +5 -1
- package/packages/dd-trace/src/lambda/handler.js +72 -0
- package/packages/dd-trace/src/lambda/index.js +5 -0
- package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
- package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
- package/packages/dd-trace/src/lambda/runtime/ritm.js +138 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -0
- package/packages/dd-trace/src/plugins/database.js +4 -4
- package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
- package/packages/dd-trace/src/plugins/util/ci.js +5 -2
- package/packages/dd-trace/src/plugins/util/test.js +2 -2
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
- package/packages/dd-trace/src/priority_sampler.js +6 -2
- package/packages/dd-trace/src/proxy.js +4 -3
- package/packages/dd-trace/src/ritm.js +7 -1
- package/packages/dd-trace/src/span_processor.js +13 -0
- package/packages/dd-trace/src/span_sampler.js +1 -4
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -63,4 +63,5 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
|
|
|
63
63
|
dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
|
|
64
64
|
dev,tape,MIT,Copyright James Halliday
|
|
65
65
|
dev,wait-on,MIT,Copyright 2015 Jeff Barczewski
|
|
66
|
+
file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
66
67
|
file,profile.proto,Apache license 2.0,Copyright 2016 Google Inc.
|
package/index.d.ts
CHANGED
|
@@ -242,6 +242,11 @@ export declare interface TracerOptions {
|
|
|
242
242
|
*/
|
|
243
243
|
service?: string;
|
|
244
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Provide service name mappings for each plugin.
|
|
247
|
+
*/
|
|
248
|
+
serviceMapping?: { [key: string]: string };
|
|
249
|
+
|
|
245
250
|
/**
|
|
246
251
|
* The url of the trace agent that the tracer will submit to.
|
|
247
252
|
* Takes priority over hostname and port, if set.
|
|
@@ -521,6 +526,17 @@ export declare interface TracerOptions {
|
|
|
521
526
|
*/
|
|
522
527
|
blockedTemplateJson?: string,
|
|
523
528
|
};
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Configuration of ASM Remote Configuration
|
|
532
|
+
*/
|
|
533
|
+
remoteConfig?: {
|
|
534
|
+
/**
|
|
535
|
+
* Specifies the remote configuration polling interval in seconds
|
|
536
|
+
* @default 5
|
|
537
|
+
*/
|
|
538
|
+
pollInterval?: number,
|
|
539
|
+
}
|
|
524
540
|
}
|
|
525
541
|
|
|
526
542
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.1",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
17
17
|
"tdd": "node scripts/tdd.js",
|
|
18
18
|
"test": "SERVICES=* yarn services && mocha --colors --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
|
|
19
|
-
"test:trace:core": "mocha --colors --exit --expose-gc --file packages/dd-trace/test/setup/core.js --exclude \"packages/dd-trace/test/profiling/**/*.spec.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" \"packages/dd-trace/test/**/*.spec.js\"",
|
|
20
|
-
"test:trace:core:ci": "nyc --no-clean --include \"packages/dd-trace/src/**/*.js\" --exclude \"packages/dd-trace/src/profiling/**/*.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" -- npm run test:trace:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter.json",
|
|
19
|
+
"test:trace:core": "mocha --colors --exit --expose-gc --file packages/dd-trace/test/setup/core.js --exclude \"packages/dd-trace/test/lambda/**/*.spec.js\" --exclude \"packages/dd-trace/test/profiling/**/*.spec.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" \"packages/dd-trace/test/**/*.spec.js\"",
|
|
20
|
+
"test:trace:core:ci": "nyc --no-clean --include \"packages/dd-trace/src/**/*.js\" --exclude \"packages/dd-trace/src/lambda/**/*.spec.js\" --exclude \"packages/dd-trace/src/profiling/**/*.js\" --exclude \"packages/dd-trace/test/appsec/iast/**/*.plugin.spec.js\" -- npm run test:trace:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter.json",
|
|
21
21
|
"test:instrumentations": "mocha --colors --file 'packages/dd-trace/test/setup/core.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
|
|
22
22
|
"test:instrumentations:ci": "nyc --no-clean --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations",
|
|
23
23
|
"test:core": "mocha --colors --file packages/datadog-core/test/setup.js 'packages/datadog-core/test/**/*.spec.js'",
|
|
24
24
|
"test:core:ci": "nyc --no-clean --include 'packages/datadog-core/src/**/*.js' -- npm run test:core",
|
|
25
|
+
"test:lambda": "mocha --colors --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/dd-trace/test/lambda/**/*.spec.js\"",
|
|
26
|
+
"test:lambda:ci": "nyc --no-clean --include \"packages/dd-trace/src/lambda/**/*.js\" -- npm run test:lambda",
|
|
25
27
|
"test:plugins": "mocha --colors --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\" \"packages/dd-trace/test/appsec/iast/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
|
|
26
28
|
"test:plugins:ci": "yarn services && nyc --no-clean --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS)).js\" --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS))/**/*.js\" --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" --include \"packages/dd-trace/test/appsec/iast/**/*.@($(echo $PLUGINS)).plugin.spec.js\" -- npm run test:plugins",
|
|
27
29
|
"test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
|
|
@@ -60,7 +62,7 @@
|
|
|
60
62
|
"dependencies": {
|
|
61
63
|
"@datadog/native-appsec": "2.0.0",
|
|
62
64
|
"@datadog/native-iast-rewriter": "1.1.2",
|
|
63
|
-
"@datadog/native-iast-taint-tracking": "1.
|
|
65
|
+
"@datadog/native-iast-taint-tracking": "1.1.0",
|
|
64
66
|
"@datadog/native-metrics": "^1.5.0",
|
|
65
67
|
"@datadog/pprof": "^1.1.1",
|
|
66
68
|
"@datadog/sketches-js": "^2.1.0",
|
|
@@ -89,6 +89,12 @@ function getTestAsyncResource (test) {
|
|
|
89
89
|
return testToAr.get(originalFn)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
function getSuitesToRun (originalSuites) {
|
|
93
|
+
return originalSuites.filter(suite =>
|
|
94
|
+
!suitesToSkip.includes(getTestSuitePath(suite.file, process.cwd()))
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
function mochaHook (Runner) {
|
|
93
99
|
if (patched.has(Runner)) return Runner
|
|
94
100
|
|
|
@@ -279,11 +285,6 @@ function mochaHook (Runner) {
|
|
|
279
285
|
}
|
|
280
286
|
})
|
|
281
287
|
|
|
282
|
-
// We remove the suites that we skip through ITR
|
|
283
|
-
this.suite.suites = this.suite.suites.filter(suite =>
|
|
284
|
-
!suitesToSkip.includes(getTestSuitePath(suite.file, process.cwd()))
|
|
285
|
-
)
|
|
286
|
-
|
|
287
288
|
return run.apply(this, arguments)
|
|
288
289
|
})
|
|
289
290
|
|
|
@@ -323,6 +324,10 @@ addHook({
|
|
|
323
324
|
if (!itrConfigurationCh.hasSubscribers) {
|
|
324
325
|
return run.apply(this, arguments)
|
|
325
326
|
}
|
|
327
|
+
this.options.delay = true
|
|
328
|
+
|
|
329
|
+
const runner = run.apply(this, arguments)
|
|
330
|
+
|
|
326
331
|
const onReceivedSkippableSuites = ({ err, skippableSuites }) => {
|
|
327
332
|
if (err) {
|
|
328
333
|
log.error(err)
|
|
@@ -330,16 +335,18 @@ addHook({
|
|
|
330
335
|
} else {
|
|
331
336
|
suitesToSkip = skippableSuites
|
|
332
337
|
}
|
|
333
|
-
|
|
338
|
+
// We remove the suites that we skip through ITR
|
|
339
|
+
runner.suite.suites = getSuitesToRun(runner.suite.suites)
|
|
340
|
+
global.run()
|
|
334
341
|
}
|
|
335
342
|
|
|
336
343
|
const onReceivedConfiguration = ({ err }) => {
|
|
337
344
|
if (err) {
|
|
338
345
|
log.error(err)
|
|
339
|
-
return run
|
|
346
|
+
return global.run()
|
|
340
347
|
}
|
|
341
348
|
if (!skippableSuitesCh.hasSubscribers) {
|
|
342
|
-
return run
|
|
349
|
+
return global.run()
|
|
343
350
|
}
|
|
344
351
|
|
|
345
352
|
skippableSuitesCh.publish({
|
|
@@ -352,6 +359,7 @@ addHook({
|
|
|
352
359
|
onDone: mochaRunAsyncResource.bind(onReceivedConfiguration)
|
|
353
360
|
})
|
|
354
361
|
})
|
|
362
|
+
return runner
|
|
355
363
|
})
|
|
356
364
|
return Mocha
|
|
357
365
|
})
|
|
@@ -362,6 +370,23 @@ addHook({
|
|
|
362
370
|
file: 'lib/runner.js'
|
|
363
371
|
}, mochaHook)
|
|
364
372
|
|
|
373
|
+
addHook({
|
|
374
|
+
name: 'mocha',
|
|
375
|
+
versions: ['>=5.2.0'],
|
|
376
|
+
file: 'lib/cli/run-helpers.js'
|
|
377
|
+
}, (run) => {
|
|
378
|
+
shimmer.wrap(run, 'runMocha', runMocha => async function () {
|
|
379
|
+
const mocha = arguments[0]
|
|
380
|
+
/**
|
|
381
|
+
* This attaches `run` to the global context, which we'll call after
|
|
382
|
+
* our configuration and skippable suites requests
|
|
383
|
+
*/
|
|
384
|
+
mocha.options.delay = true
|
|
385
|
+
return runMocha.apply(this, arguments)
|
|
386
|
+
})
|
|
387
|
+
return run
|
|
388
|
+
})
|
|
389
|
+
|
|
365
390
|
addHook({
|
|
366
391
|
name: 'mocha',
|
|
367
392
|
versions: ['>=5.2.0'],
|
|
@@ -41,7 +41,12 @@ function wrapQuery (query) {
|
|
|
41
41
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
42
42
|
const processId = this.processID
|
|
43
43
|
return asyncResource.runInAsyncScope(() => {
|
|
44
|
-
startCh.publish({
|
|
44
|
+
startCh.publish({
|
|
45
|
+
params: this.connectionParameters,
|
|
46
|
+
originalQuery: pgQuery.text,
|
|
47
|
+
query: pgQuery,
|
|
48
|
+
processId
|
|
49
|
+
})
|
|
45
50
|
|
|
46
51
|
const finish = asyncResource.bind(function (error) {
|
|
47
52
|
if (error) {
|
|
@@ -117,7 +117,7 @@ function addRequestHeaders (req, span, config) {
|
|
|
117
117
|
const value = req.getHeader(key)
|
|
118
118
|
|
|
119
119
|
if (value) {
|
|
120
|
-
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, value)
|
|
120
|
+
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, Array.isArray(value) ? value.toString() : value)
|
|
121
121
|
}
|
|
122
122
|
})
|
|
123
123
|
}
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
TEST_SUITE_ID,
|
|
16
16
|
TEST_COMMAND,
|
|
17
17
|
TEST_ITR_TESTS_SKIPPED,
|
|
18
|
-
|
|
18
|
+
TEST_SESSION_CODE_COVERAGE_ENABLED,
|
|
19
19
|
TEST_SESSION_ITR_SKIPPING_ENABLED,
|
|
20
20
|
TEST_CODE_COVERAGE_LINES_TOTAL
|
|
21
21
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
@@ -77,7 +77,7 @@ class JestPlugin extends CiPlugin {
|
|
|
77
77
|
testSessionSpan.setTag(TEST_STATUS, status)
|
|
78
78
|
testSessionSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
|
|
79
79
|
testSessionSpan.setTag(TEST_SESSION_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
|
|
80
|
-
testSessionSpan.setTag(
|
|
80
|
+
testSessionSpan.setTag(TEST_SESSION_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
|
|
81
81
|
|
|
82
82
|
if (testCodeCoverageLinesTotal !== undefined) {
|
|
83
83
|
testSessionSpan.setTag(TEST_CODE_COVERAGE_LINES_TOTAL, testCodeCoverageLinesTotal)
|
|
@@ -16,7 +16,7 @@ const {
|
|
|
16
16
|
TEST_SESSION_ID,
|
|
17
17
|
TEST_COMMAND,
|
|
18
18
|
TEST_ITR_TESTS_SKIPPED,
|
|
19
|
-
|
|
19
|
+
TEST_SESSION_CODE_COVERAGE_ENABLED,
|
|
20
20
|
TEST_SESSION_ITR_SKIPPING_ENABLED
|
|
21
21
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
22
22
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
@@ -145,7 +145,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
145
145
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
146
146
|
this.testSessionSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
|
|
147
147
|
this.testSessionSpan.setTag(TEST_SESSION_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
|
|
148
|
-
this.testSessionSpan.setTag(
|
|
148
|
+
this.testSessionSpan.setTag(TEST_SESSION_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
|
|
149
149
|
|
|
150
150
|
this.testSessionSpan.finish()
|
|
151
151
|
finishAllTraceSpans(this.testSessionSpan)
|
|
@@ -57,16 +57,16 @@ class Analyzer extends Plugin {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
analyze (value) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const store = storage.getStore()
|
|
61
|
+
const iastContext = getIastContext(store)
|
|
62
|
+
if (store && !iastContext) return
|
|
63
63
|
this._reportIfVulnerable(value, iastContext)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
analyzeAll (...values) {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const store = storage.getStore()
|
|
68
|
+
const iastContext = getIastContext(store)
|
|
69
|
+
if (store && !iastContext) return
|
|
70
70
|
for (let i = 0; i < values.length; i++) {
|
|
71
71
|
const value = values[i]
|
|
72
72
|
if (this._isVulnerable(value, iastContext)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { sendVulnerabilities } = require('./vulnerability-reporter')
|
|
1
|
+
const { sendVulnerabilities, setTracer } = require('./vulnerability-reporter')
|
|
2
2
|
const { enableAllAnalyzers, disableAllAnalyzers } = require('./analyzers')
|
|
3
3
|
const web = require('../../plugins/util/web')
|
|
4
4
|
const { storage } = require('../../../../datadog-core')
|
|
@@ -14,17 +14,20 @@ const IAST_ENABLED_TAG_KEY = '_dd.iast.enabled'
|
|
|
14
14
|
const requestStart = dc.channel('dd-trace:incomingHttpRequestStart')
|
|
15
15
|
const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
|
|
16
16
|
|
|
17
|
-
function enable (config) {
|
|
17
|
+
function enable (config, _tracer) {
|
|
18
18
|
enableAllAnalyzers()
|
|
19
19
|
enableTaintTracking()
|
|
20
20
|
requestStart.subscribe(onIncomingHttpRequestStart)
|
|
21
21
|
requestClose.subscribe(onIncomingHttpRequestEnd)
|
|
22
22
|
overheadController.configure(config.iast)
|
|
23
|
+
overheadController.startGlobalContext()
|
|
24
|
+
setTracer(_tracer)
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
function disable () {
|
|
26
28
|
disableAllAnalyzers()
|
|
27
29
|
disableTaintTracking()
|
|
30
|
+
overheadController.finishGlobalContext()
|
|
28
31
|
if (requestStart.hasSubscribers) requestStart.unsubscribe(onIncomingHttpRequestStart)
|
|
29
32
|
if (requestClose.hasSubscribers) requestClose.unsubscribe(onIncomingHttpRequestEnd)
|
|
30
33
|
}
|
|
@@ -57,7 +60,9 @@ function onIncomingHttpRequestEnd (data) {
|
|
|
57
60
|
const store = storage.getStore()
|
|
58
61
|
const iastContext = iastContextFunctions.getIastContext(storage.getStore())
|
|
59
62
|
if (iastContext && iastContext.rootSpan) {
|
|
60
|
-
|
|
63
|
+
const vulnerabilities = iastContext.vulnerabilities
|
|
64
|
+
const rootSpan = iastContext.rootSpan
|
|
65
|
+
sendVulnerabilities(vulnerabilities, rootSpan)
|
|
61
66
|
removeTransaction(iastContext)
|
|
62
67
|
}
|
|
63
68
|
// TODO web.getContext(data.req) is required when the request is aborted
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const OVERHEAD_CONTROLLER_CONTEXT_KEY = 'oce'
|
|
4
4
|
const REPORT_VULNERABILITY = 'REPORT_VULNERABILITY'
|
|
5
|
+
const INTERVAL_RESET_GLOBAL_CONTEXT = 60 * 1000
|
|
5
6
|
|
|
6
7
|
const GLOBAL_OCE_CONTEXT = {}
|
|
8
|
+
|
|
9
|
+
let resetGlobalContextInterval
|
|
7
10
|
let config = {}
|
|
8
11
|
let availableRequest = 0
|
|
9
12
|
const OPERATIONS = {
|
|
@@ -80,11 +83,27 @@ function configure (cfg) {
|
|
|
80
83
|
availableRequest = config.maxConcurrentRequests
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
function startGlobalContext () {
|
|
87
|
+
if (resetGlobalContextInterval) return
|
|
88
|
+
_resetGlobalContext()
|
|
89
|
+
resetGlobalContextInterval = setInterval(() => {
|
|
90
|
+
_resetGlobalContext()
|
|
91
|
+
}, INTERVAL_RESET_GLOBAL_CONTEXT)
|
|
92
|
+
resetGlobalContextInterval.unref && resetGlobalContextInterval.unref()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function finishGlobalContext () {
|
|
96
|
+
if (resetGlobalContextInterval) {
|
|
97
|
+
clearInterval(resetGlobalContextInterval)
|
|
98
|
+
resetGlobalContextInterval = null
|
|
99
|
+
}
|
|
100
|
+
}
|
|
84
101
|
|
|
85
102
|
module.exports = {
|
|
86
103
|
OVERHEAD_CONTROLLER_CONTEXT_KEY,
|
|
87
104
|
OPERATIONS,
|
|
105
|
+
startGlobalContext,
|
|
106
|
+
finishGlobalContext,
|
|
88
107
|
_resetGlobalContext,
|
|
89
108
|
initializeRequestContext,
|
|
90
109
|
hasQuota,
|
|
@@ -4,7 +4,12 @@ const csiMethods = [
|
|
|
4
4
|
{ src: 'plusOperator', operator: true },
|
|
5
5
|
{ src: 'trim' },
|
|
6
6
|
{ src: 'trimStart', dst: 'trim' },
|
|
7
|
-
{ src: 'trimEnd' }
|
|
7
|
+
{ src: 'trimEnd' },
|
|
8
|
+
{ src: 'concat' },
|
|
9
|
+
{ src: 'substring' },
|
|
10
|
+
{ src: 'substr' },
|
|
11
|
+
{ src: 'slice' },
|
|
12
|
+
{ src: 'replace' }
|
|
8
13
|
]
|
|
9
14
|
|
|
10
15
|
module.exports = {
|
|
@@ -9,7 +9,12 @@ function noop (res) { return res }
|
|
|
9
9
|
const TaintTrackingDummy = {
|
|
10
10
|
plusOperator: noop,
|
|
11
11
|
trim: noop,
|
|
12
|
-
trimEnd: noop
|
|
12
|
+
trimEnd: noop,
|
|
13
|
+
concat: noop,
|
|
14
|
+
substring: noop,
|
|
15
|
+
substr: noop,
|
|
16
|
+
slice: noop,
|
|
17
|
+
replace: noop
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
function getTransactionId () {
|
|
@@ -54,7 +59,19 @@ function getCsiFn (cb, ...protos) {
|
|
|
54
59
|
return getFilteredCsiFn(cb, filter)
|
|
55
60
|
}
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
function csiMethodsDefaults (names, excluded) {
|
|
63
|
+
const impl = {}
|
|
64
|
+
names.forEach(name => {
|
|
65
|
+
if (excluded.indexOf(name) !== -1) return
|
|
66
|
+
impl[name] = getCsiFn(
|
|
67
|
+
(transactionId, res, target, ...rest) => TaintedUtils[name](transactionId, res, target, ...rest),
|
|
68
|
+
String.prototype[name]
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
return impl
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const csiMethodsOverrides = {
|
|
58
75
|
plusOperator: function (res, op1, op2) {
|
|
59
76
|
try {
|
|
60
77
|
if (notString(res) || (notString(op1) && notString(op2))) { return res }
|
|
@@ -72,13 +89,14 @@ const TaintTracking = {
|
|
|
72
89
|
(transactionId, res, target) => TaintedUtils.trim(transactionId, res, target),
|
|
73
90
|
String.prototype.trim,
|
|
74
91
|
String.prototype.trimStart
|
|
75
|
-
),
|
|
76
|
-
trimEnd: getCsiFn(
|
|
77
|
-
(transactionId, res, target) => TaintedUtils.trimEnd(transactionId, res, target),
|
|
78
|
-
String.prototype.trimEnd
|
|
79
92
|
)
|
|
80
93
|
}
|
|
81
94
|
|
|
95
|
+
const TaintTracking = {
|
|
96
|
+
...csiMethodsDefaults(Object.keys(TaintTrackingDummy), Object.keys(csiMethodsOverrides)),
|
|
97
|
+
...csiMethodsOverrides
|
|
98
|
+
}
|
|
99
|
+
|
|
82
100
|
module.exports = {
|
|
83
101
|
TaintTracking,
|
|
84
102
|
TaintTrackingDummy
|
|
@@ -5,13 +5,16 @@ const IAST_JSON_TAG_KEY = '_dd.iast.json'
|
|
|
5
5
|
const VULNERABILITY_HASHES_MAX_SIZE = 1000
|
|
6
6
|
const VULNERABILITY_HASHES = new LRU({ max: VULNERABILITY_HASHES_MAX_SIZE })
|
|
7
7
|
|
|
8
|
+
let tracer
|
|
9
|
+
|
|
8
10
|
function createVulnerability (type, evidence, spanId, location) {
|
|
9
|
-
if (type && evidence
|
|
11
|
+
if (type && evidence) {
|
|
12
|
+
const _spanId = spanId || 0
|
|
10
13
|
return {
|
|
11
14
|
type,
|
|
12
15
|
evidence,
|
|
13
16
|
location: {
|
|
14
|
-
spanId,
|
|
17
|
+
spanId: _spanId,
|
|
15
18
|
...location
|
|
16
19
|
},
|
|
17
20
|
hash: createHash(type, location)
|
|
@@ -37,10 +40,14 @@ function createHash (type, location) {
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
function addVulnerability (iastContext, vulnerability) {
|
|
40
|
-
if (
|
|
41
|
-
vulnerability.location
|
|
42
|
-
iastContext
|
|
43
|
-
|
|
43
|
+
if (vulnerability && vulnerability.evidence && vulnerability.type &&
|
|
44
|
+
vulnerability.location) {
|
|
45
|
+
if (iastContext && iastContext.rootSpan) {
|
|
46
|
+
iastContext[VULNERABILITIES_KEY] = iastContext[VULNERABILITIES_KEY] || []
|
|
47
|
+
iastContext[VULNERABILITIES_KEY].push(vulnerability)
|
|
48
|
+
} else {
|
|
49
|
+
sendVulnerabilities([vulnerability])
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
}
|
|
46
53
|
|
|
@@ -101,43 +108,53 @@ function jsonVulnerabilityFromVulnerability (vulnerability, sourcesIndexes) {
|
|
|
101
108
|
return jsonVulnerability
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
function sendVulnerabilities (
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
vulnerabilities
|
|
111
|
+
function sendVulnerabilities (vulnerabilities, rootSpan) {
|
|
112
|
+
if (vulnerabilities && vulnerabilities.length) {
|
|
113
|
+
let span = rootSpan
|
|
114
|
+
if (!span && tracer) {
|
|
115
|
+
span = tracer.startSpan('vulnerability', {
|
|
116
|
+
type: 'vulnerability'
|
|
117
|
+
})
|
|
118
|
+
vulnerabilities.forEach((vulnerability) => {
|
|
119
|
+
vulnerability.location.spanId = span.context().toSpanId()
|
|
120
|
+
})
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
if (span && span.addTags) {
|
|
124
|
+
const jsonToSend = {
|
|
125
|
+
sources: [],
|
|
126
|
+
vulnerabilities: []
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
deduplicateVulnerabilities(vulnerabilities).forEach((vulnerability) => {
|
|
130
|
+
if (isValidVulnerability(vulnerability)) {
|
|
131
|
+
const sourcesIndexes = []
|
|
132
|
+
const vulnerabilitySources = extractSourcesFromVulnerability(vulnerability)
|
|
133
|
+
vulnerabilitySources.forEach((source) => {
|
|
134
|
+
let sourceIndex = jsonToSend.sources.findIndex(
|
|
135
|
+
existingSource =>
|
|
136
|
+
existingSource.origin === source.origin &&
|
|
137
|
+
existingSource.name === source.name &&
|
|
138
|
+
existingSource.value === source.value
|
|
139
|
+
)
|
|
140
|
+
if (sourceIndex === -1) {
|
|
141
|
+
sourceIndex = jsonToSend.sources.length
|
|
142
|
+
jsonToSend.sources.push(source)
|
|
143
|
+
}
|
|
144
|
+
sourcesIndexes.push(sourceIndex)
|
|
145
|
+
})
|
|
146
|
+
jsonToSend.vulnerabilities.push(jsonVulnerabilityFromVulnerability(vulnerability, sourcesIndexes))
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
if (jsonToSend.vulnerabilities.length > 0) {
|
|
151
|
+
const tags = {}
|
|
152
|
+
// TODO: Store this outside of the span and set the tag in the exporter.
|
|
153
|
+
tags[IAST_JSON_TAG_KEY] = JSON.stringify(jsonToSend)
|
|
154
|
+
tags[MANUAL_KEEP] = 'true'
|
|
155
|
+
span.addTags(tags)
|
|
156
|
+
if (!rootSpan) span.finish()
|
|
132
157
|
}
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
if (jsonToSend.vulnerabilities.length > 0) {
|
|
136
|
-
const tags = {}
|
|
137
|
-
// TODO: Store this outside of the span and set the tag in the exporter.
|
|
138
|
-
tags[IAST_JSON_TAG_KEY] = JSON.stringify(jsonToSend)
|
|
139
|
-
tags[MANUAL_KEEP] = 'true'
|
|
140
|
-
span.addTags(tags)
|
|
141
158
|
}
|
|
142
159
|
}
|
|
143
160
|
return IAST_JSON_TAG_KEY
|
|
@@ -159,9 +176,14 @@ function deduplicateVulnerabilities (vulnerabilities) {
|
|
|
159
176
|
return deduplicated
|
|
160
177
|
}
|
|
161
178
|
|
|
179
|
+
function setTracer (_tracer) {
|
|
180
|
+
tracer = _tracer
|
|
181
|
+
}
|
|
182
|
+
|
|
162
183
|
module.exports = {
|
|
163
184
|
createVulnerability,
|
|
164
185
|
addVulnerability,
|
|
165
186
|
sendVulnerabilities,
|
|
166
|
-
clearCache
|
|
187
|
+
clearCache,
|
|
188
|
+
setTracer
|
|
167
189
|
}
|