dd-trace 3.41.0 → 3.42.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 +1 -0
- package/index.d.ts +24 -0
- package/package.json +6 -5
- package/packages/datadog-instrumentations/src/aerospike.js +47 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/http/client.js +22 -0
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
- package/packages/datadog-instrumentations/src/next.js +3 -1
- package/packages/datadog-instrumentations/src/restify.js +1 -1
- package/packages/datadog-plugin-aerospike/src/index.js +113 -0
- package/packages/datadog-plugin-http/src/client.js +19 -2
- package/packages/datadog-plugin-kafkajs/src/consumer.js +51 -0
- package/packages/datadog-plugin-kafkajs/src/producer.js +55 -0
- package/packages/datadog-plugin-next/src/index.js +7 -7
- package/packages/dd-trace/src/appsec/addresses.js +2 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +13 -1
- package/packages/dd-trace/src/appsec/recommended.json +1395 -2
- package/packages/dd-trace/src/appsec/reporter.js +19 -0
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +17 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +75 -56
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +15 -9
- package/packages/dd-trace/src/config.js +31 -2
- package/packages/dd-trace/src/datastreams/processor.js +107 -12
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/opentracing/span.js +2 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/git.js +2 -2
- package/packages/dd-trace/src/plugins/util/test.js +3 -2
- package/packages/dd-trace/src/profiler.js +5 -3
- package/packages/dd-trace/src/profiling/config.js +8 -0
- package/packages/dd-trace/src/profiling/profiler.js +10 -4
- package/packages/dd-trace/src/profiling/profilers/events.js +166 -73
- package/packages/dd-trace/src/proxy.js +21 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/spanleak.js +98 -0
- package/packages/dd-trace/src/startup-log.js +7 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +55 -9
- package/packages/dd-trace/src/telemetry/index.js +135 -43
- package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/telemetry/send-data.js +47 -5
- package/packages/dd-trace/src/tracer.js +4 -0
- package/scripts/install_plugin_modules.js +11 -3
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const InjectionAnalyzer = require('./injection-analyzer')
|
|
4
|
+
const { HEADER_INJECTION } = require('../vulnerabilities')
|
|
5
|
+
const { getNodeModulesPaths } = require('../path-line')
|
|
6
|
+
const { HEADER_NAME_VALUE_SEPARATOR } = require('../vulnerabilities-formatter/constants')
|
|
7
|
+
const { getRanges } = require('../taint-tracking/operations')
|
|
8
|
+
const {
|
|
9
|
+
HTTP_REQUEST_COOKIE_NAME,
|
|
10
|
+
HTTP_REQUEST_COOKIE_VALUE,
|
|
11
|
+
HTTP_REQUEST_HEADER_VALUE
|
|
12
|
+
} = require('../taint-tracking/source-types')
|
|
13
|
+
|
|
14
|
+
const EXCLUDED_PATHS = getNodeModulesPaths('express')
|
|
15
|
+
const EXCLUDED_HEADER_NAMES = [
|
|
16
|
+
'location',
|
|
17
|
+
'sec-websocket-location',
|
|
18
|
+
'sec-websocket-accept',
|
|
19
|
+
'upgrade',
|
|
20
|
+
'connection'
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
class HeaderInjectionAnalyzer extends InjectionAnalyzer {
|
|
24
|
+
constructor () {
|
|
25
|
+
super(HEADER_INJECTION)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
onConfigure () {
|
|
29
|
+
this.addSub('datadog:http:server:response:set-header:finish', ({ name, value }) => {
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
for (let i = 0; i < value.length; i++) {
|
|
32
|
+
const headerValue = value[i]
|
|
33
|
+
|
|
34
|
+
this.analyze({ name, value: headerValue })
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
this.analyze({ name, value })
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_isVulnerable ({ name, value }, iastContext) {
|
|
43
|
+
const lowerCasedHeaderName = name?.trim().toLowerCase()
|
|
44
|
+
|
|
45
|
+
if (this.isExcludedHeaderName(lowerCasedHeaderName) || typeof value !== 'string') return
|
|
46
|
+
|
|
47
|
+
const ranges = getRanges(iastContext, value)
|
|
48
|
+
if (ranges?.length > 0) {
|
|
49
|
+
return !(this.isCookieExclusion(lowerCasedHeaderName, ranges) ||
|
|
50
|
+
this.isSameHeaderExclusion(lowerCasedHeaderName, ranges) ||
|
|
51
|
+
this.isAccessControlAllowOriginExclusion(lowerCasedHeaderName, ranges))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_getEvidence (headerInfo, iastContext) {
|
|
58
|
+
const prefix = headerInfo.name + HEADER_NAME_VALUE_SEPARATOR
|
|
59
|
+
const prefixLength = prefix.length
|
|
60
|
+
|
|
61
|
+
const evidence = super._getEvidence(headerInfo.value, iastContext)
|
|
62
|
+
evidence.value = prefix + evidence.value
|
|
63
|
+
evidence.ranges = evidence.ranges.map(range => {
|
|
64
|
+
return {
|
|
65
|
+
...range,
|
|
66
|
+
start: range.start + prefixLength,
|
|
67
|
+
end: range.end + prefixLength
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return evidence
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
isExcludedHeaderName (name) {
|
|
75
|
+
return EXCLUDED_HEADER_NAMES.includes(name)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
isCookieExclusion (name, ranges) {
|
|
79
|
+
if (name === 'set-cookie') {
|
|
80
|
+
return ranges
|
|
81
|
+
.every(range => range.iinfo.type === HTTP_REQUEST_COOKIE_VALUE || range.iinfo.type === HTTP_REQUEST_COOKIE_NAME)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
isAccessControlAllowOriginExclusion (name, ranges) {
|
|
88
|
+
if (name === 'access-control-allow-origin') {
|
|
89
|
+
return ranges
|
|
90
|
+
.every(range => range.iinfo.type === HTTP_REQUEST_HEADER_VALUE)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
isSameHeaderExclusion (name, ranges) {
|
|
97
|
+
return ranges.length === 1 && name === ranges[0].iinfo.parameterName?.toLowerCase()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_getExcludedPaths () {
|
|
101
|
+
return EXCLUDED_PATHS
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = new HeaderInjectionAnalyzer()
|
|
@@ -3,27 +3,20 @@
|
|
|
3
3
|
const iastLog = require('../../../iast-log')
|
|
4
4
|
|
|
5
5
|
const COMMAND_PATTERN = '^(?:\\s*(?:sudo|doas)\\s+)?\\b\\S+\\b\\s(.*)'
|
|
6
|
+
const pattern = new RegExp(COMMAND_PATTERN, 'gmi')
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
extractSensitiveRanges (evidence) {
|
|
13
|
-
try {
|
|
14
|
-
this._pattern.lastIndex = 0
|
|
8
|
+
module.exports = function extractSensitiveRanges (evidence) {
|
|
9
|
+
try {
|
|
10
|
+
pattern.lastIndex = 0
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
} catch (e) {
|
|
23
|
-
iastLog.debug(e)
|
|
12
|
+
const regexResult = pattern.exec(evidence.value)
|
|
13
|
+
if (regexResult && regexResult.length > 1) {
|
|
14
|
+
const start = regexResult.index + (regexResult[0].length - regexResult[1].length)
|
|
15
|
+
const end = start + regexResult[1].length
|
|
16
|
+
return [{ start, end }]
|
|
24
17
|
}
|
|
25
|
-
|
|
18
|
+
} catch (e) {
|
|
19
|
+
iastLog.debug(e)
|
|
26
20
|
}
|
|
21
|
+
return []
|
|
27
22
|
}
|
|
28
|
-
|
|
29
|
-
module.exports = CommandSensitiveAnalyzer
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { HEADER_NAME_VALUE_SEPARATOR } = require('../../constants')
|
|
4
|
+
|
|
5
|
+
module.exports = function extractSensitiveRanges (evidence, namePattern, valuePattern) {
|
|
6
|
+
const evidenceValue = evidence.value
|
|
7
|
+
const sections = evidenceValue.split(HEADER_NAME_VALUE_SEPARATOR)
|
|
8
|
+
const headerName = sections[0]
|
|
9
|
+
const headerValue = sections.slice(1).join(HEADER_NAME_VALUE_SEPARATOR)
|
|
10
|
+
namePattern.lastIndex = 0
|
|
11
|
+
valuePattern.lastIndex = 0
|
|
12
|
+
if (namePattern.test(headerName) || valuePattern.test(headerValue)) {
|
|
13
|
+
return [{
|
|
14
|
+
start: headerName.length + HEADER_NAME_VALUE_SEPARATOR.length,
|
|
15
|
+
end: evidenceValue.length
|
|
16
|
+
}]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return []
|
|
20
|
+
}
|
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const { stringifyWithRanges } = require('../../utils')
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
evidence.ranges = ranges
|
|
5
|
+
module.exports = function extractSensitiveRanges (evidence) {
|
|
6
|
+
// expect object evidence
|
|
7
|
+
const { value, ranges, sensitiveRanges } = stringifyWithRanges(evidence.value, evidence.rangesToApply, true)
|
|
8
|
+
evidence.value = value
|
|
9
|
+
evidence.ranges = ranges
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
}
|
|
11
|
+
return sensitiveRanges
|
|
14
12
|
}
|
|
15
|
-
|
|
16
|
-
module.exports = JsonSensitiveAnalyzer
|
|
@@ -3,33 +3,26 @@
|
|
|
3
3
|
const iastLog = require('../../../iast-log')
|
|
4
4
|
|
|
5
5
|
const LDAP_PATTERN = '\\(.*?(?:~=|=|<=|>=)(?<LITERAL>[^)]+)\\)'
|
|
6
|
+
const pattern = new RegExp(LDAP_PATTERN, 'gmi')
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
extractSensitiveRanges (evidence) {
|
|
13
|
-
try {
|
|
14
|
-
this._pattern.lastIndex = 0
|
|
15
|
-
const tokens = []
|
|
8
|
+
module.exports = function extractSensitiveRanges (evidence) {
|
|
9
|
+
try {
|
|
10
|
+
pattern.lastIndex = 0
|
|
11
|
+
const tokens = []
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
return tokens
|
|
28
|
-
} catch (e) {
|
|
29
|
-
iastLog.debug(e)
|
|
13
|
+
let regexResult = pattern.exec(evidence.value)
|
|
14
|
+
while (regexResult != null) {
|
|
15
|
+
if (!regexResult.groups.LITERAL) continue
|
|
16
|
+
// Computing indices manually since NodeJs 12 does not support d flag on regular expressions
|
|
17
|
+
// TODO Get indices from group by adding d flag in regular expression
|
|
18
|
+
const start = regexResult.index + (regexResult[0].length - regexResult.groups.LITERAL.length - 1)
|
|
19
|
+
const end = start + regexResult.groups.LITERAL.length
|
|
20
|
+
tokens.push({ start, end })
|
|
21
|
+
regexResult = pattern.exec(evidence.value)
|
|
30
22
|
}
|
|
31
|
-
return
|
|
23
|
+
return tokens
|
|
24
|
+
} catch (e) {
|
|
25
|
+
iastLog.debug(e)
|
|
32
26
|
}
|
|
27
|
+
return []
|
|
33
28
|
}
|
|
34
|
-
|
|
35
|
-
module.exports = LdapSensitiveAnalyzer
|
|
@@ -23,96 +23,90 @@ const NUMERIC_LITERAL =
|
|
|
23
23
|
})`
|
|
24
24
|
const ORACLE_ESCAPED_LITERAL = 'q\'<.*?>\'|q\'\\(.*?\\)\'|q\'\\{.*?\\}\'|q\'\\[.*?\\]\'|q\'(?<ESCAPE>.).*?\\k<ESCAPE>\''
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this._patterns.SQLITE = this._patterns.MYSQL
|
|
67
|
-
this._patterns.MARIADB = this._patterns.MYSQL
|
|
68
|
-
}
|
|
26
|
+
const patterns = {
|
|
27
|
+
ANSI: new RegExp( // Default
|
|
28
|
+
[
|
|
29
|
+
NUMERIC_LITERAL,
|
|
30
|
+
STRING_LITERAL,
|
|
31
|
+
LINE_COMMENT,
|
|
32
|
+
BLOCK_COMMENT
|
|
33
|
+
].join('|'),
|
|
34
|
+
'gmi'
|
|
35
|
+
),
|
|
36
|
+
MYSQL: new RegExp(
|
|
37
|
+
[
|
|
38
|
+
NUMERIC_LITERAL,
|
|
39
|
+
MYSQL_STRING_LITERAL,
|
|
40
|
+
LINE_COMMENT,
|
|
41
|
+
BLOCK_COMMENT
|
|
42
|
+
].join('|'),
|
|
43
|
+
'gmi'
|
|
44
|
+
),
|
|
45
|
+
POSTGRES: new RegExp(
|
|
46
|
+
[
|
|
47
|
+
NUMERIC_LITERAL,
|
|
48
|
+
POSTGRESQL_ESCAPED_LITERAL,
|
|
49
|
+
STRING_LITERAL,
|
|
50
|
+
LINE_COMMENT,
|
|
51
|
+
BLOCK_COMMENT
|
|
52
|
+
].join('|'),
|
|
53
|
+
'gmi'
|
|
54
|
+
),
|
|
55
|
+
ORACLE: new RegExp([
|
|
56
|
+
NUMERIC_LITERAL,
|
|
57
|
+
ORACLE_ESCAPED_LITERAL,
|
|
58
|
+
STRING_LITERAL,
|
|
59
|
+
LINE_COMMENT,
|
|
60
|
+
BLOCK_COMMENT
|
|
61
|
+
].join('|'),
|
|
62
|
+
'gmi')
|
|
63
|
+
}
|
|
64
|
+
patterns.SQLITE = patterns.MYSQL
|
|
65
|
+
patterns.MARIADB = patterns.MYSQL
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
module.exports = function extractSensitiveRanges (evidence) {
|
|
68
|
+
try {
|
|
69
|
+
let pattern = patterns[evidence.dialect]
|
|
70
|
+
if (!pattern) {
|
|
71
|
+
pattern = patterns['ANSI']
|
|
72
|
+
}
|
|
73
|
+
pattern.lastIndex = 0
|
|
74
|
+
const tokens = []
|
|
78
75
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
76
|
+
let regexResult = pattern.exec(evidence.value)
|
|
77
|
+
while (regexResult != null) {
|
|
78
|
+
let start = regexResult.index
|
|
79
|
+
let end = regexResult.index + regexResult[0].length
|
|
80
|
+
const startChar = evidence.value.charAt(start)
|
|
81
|
+
if (startChar === '\'' || startChar === '"') {
|
|
82
|
+
start++
|
|
83
|
+
end--
|
|
84
|
+
} else if (end > start + 1) {
|
|
85
|
+
const nextChar = evidence.value.charAt(start + 1)
|
|
86
|
+
if (startChar === '/' && nextChar === '*') {
|
|
87
|
+
start += 2
|
|
88
|
+
end -= 2
|
|
89
|
+
} else if (startChar === '-' && startChar === nextChar) {
|
|
90
|
+
start += 2
|
|
91
|
+
} else if (startChar.toLowerCase() === 'q' && nextChar === '\'') {
|
|
92
|
+
start += 3
|
|
93
|
+
end -= 2
|
|
94
|
+
} else if (startChar === '$') {
|
|
95
|
+
const match = regexResult[0]
|
|
96
|
+
const size = match.indexOf('$', 1) + 1
|
|
97
|
+
if (size > 1) {
|
|
98
|
+
start += size
|
|
99
|
+
end -= size
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
|
-
|
|
107
|
-
tokens.push({ start, end })
|
|
108
|
-
regexResult = pattern.exec(evidence.value)
|
|
109
102
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
|
|
104
|
+
tokens.push({ start, end })
|
|
105
|
+
regexResult = pattern.exec(evidence.value)
|
|
113
106
|
}
|
|
114
|
-
return
|
|
107
|
+
return tokens
|
|
108
|
+
} catch (e) {
|
|
109
|
+
iastLog.debug(e)
|
|
115
110
|
}
|
|
111
|
+
return []
|
|
116
112
|
}
|
|
117
|
-
|
|
118
|
-
module.exports = SqlSensitiveAnalyzer
|
|
@@ -4,46 +4,37 @@ const iastLog = require('../../../iast-log')
|
|
|
4
4
|
|
|
5
5
|
const AUTHORITY = '^(?:[^:]+:)?//([^@]+)@'
|
|
6
6
|
const QUERY_FRAGMENT = '[?#&]([^=&;]+)=([^?#&]+)'
|
|
7
|
+
const pattern = new RegExp([AUTHORITY, QUERY_FRAGMENT].join('|'), 'gmi')
|
|
8
|
+
|
|
9
|
+
module.exports = function extractSensitiveRanges (evidence) {
|
|
10
|
+
try {
|
|
11
|
+
const ranges = []
|
|
12
|
+
let regexResult = pattern.exec(evidence.value)
|
|
13
|
+
|
|
14
|
+
while (regexResult != null) {
|
|
15
|
+
if (typeof regexResult[1] === 'string') {
|
|
16
|
+
// AUTHORITY regex match always ends by group + @
|
|
17
|
+
// it means that the match last chars - 1 are always the group
|
|
18
|
+
const end = regexResult.index + (regexResult[0].length - 1)
|
|
19
|
+
const start = end - regexResult[1].length
|
|
20
|
+
ranges.push({ start, end })
|
|
21
|
+
}
|
|
7
22
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
const pattern = this._pattern
|
|
16
|
-
|
|
17
|
-
const ranges = []
|
|
18
|
-
let regexResult = pattern.exec(evidence.value)
|
|
19
|
-
|
|
20
|
-
while (regexResult != null) {
|
|
21
|
-
if (typeof regexResult[1] === 'string') {
|
|
22
|
-
// AUTHORITY regex match always ends by group + @
|
|
23
|
-
// it means that the match last chars - 1 are always the group
|
|
24
|
-
const end = regexResult.index + (regexResult[0].length - 1)
|
|
25
|
-
const start = end - regexResult[1].length
|
|
26
|
-
ranges.push({ start, end })
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (typeof regexResult[3] === 'string') {
|
|
30
|
-
// QUERY_FRAGMENT regex always ends with the group
|
|
31
|
-
// it means that the match last chars are always the group
|
|
32
|
-
const end = regexResult.index + regexResult[0].length
|
|
33
|
-
const start = end - regexResult[3].length
|
|
34
|
-
ranges.push({ start, end })
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
regexResult = pattern.exec(evidence.value)
|
|
23
|
+
if (typeof regexResult[3] === 'string') {
|
|
24
|
+
// QUERY_FRAGMENT regex always ends with the group
|
|
25
|
+
// it means that the match last chars are always the group
|
|
26
|
+
const end = regexResult.index + regexResult[0].length
|
|
27
|
+
const start = end - regexResult[3].length
|
|
28
|
+
ranges.push({ start, end })
|
|
38
29
|
}
|
|
39
30
|
|
|
40
|
-
|
|
41
|
-
} catch (e) {
|
|
42
|
-
iastLog.debug(e)
|
|
31
|
+
regexResult = pattern.exec(evidence.value)
|
|
43
32
|
}
|
|
44
33
|
|
|
45
|
-
return
|
|
34
|
+
return ranges
|
|
35
|
+
} catch (e) {
|
|
36
|
+
iastLog.debug(e)
|
|
46
37
|
}
|
|
47
|
-
}
|
|
48
38
|
|
|
49
|
-
|
|
39
|
+
return []
|
|
40
|
+
}
|
|
@@ -5,11 +5,12 @@ const vulnerabilities = require('../../vulnerabilities')
|
|
|
5
5
|
|
|
6
6
|
const { contains, intersects, remove } = require('./range-utils')
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
8
|
+
const commandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
|
|
9
|
+
const headerSensitiveAnalyzer = require('./sensitive-analyzers/header-sensitive-analyzer')
|
|
10
|
+
const jsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
|
|
11
|
+
const ldapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
|
|
12
|
+
const sqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
|
|
13
|
+
const urlSensitiveAnalyzer = require('./sensitive-analyzers/url-sensitive-analyzer')
|
|
13
14
|
|
|
14
15
|
const { DEFAULT_IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN } = require('./sensitive-regex')
|
|
15
16
|
|
|
@@ -21,13 +22,15 @@ class SensitiveHandler {
|
|
|
21
22
|
this._valuePattern = new RegExp(DEFAULT_IAST_REDACTION_VALUE_PATTERN, 'gmi')
|
|
22
23
|
|
|
23
24
|
this._sensitiveAnalyzers = new Map()
|
|
24
|
-
this._sensitiveAnalyzers.set(vulnerabilities.COMMAND_INJECTION,
|
|
25
|
-
this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION,
|
|
26
|
-
this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION,
|
|
27
|
-
this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION,
|
|
28
|
-
const urlSensitiveAnalyzer = new UrlSensitiveAnalyzer()
|
|
25
|
+
this._sensitiveAnalyzers.set(vulnerabilities.COMMAND_INJECTION, commandSensitiveAnalyzer)
|
|
26
|
+
this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, jsonSensitiveAnalyzer)
|
|
27
|
+
this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, ldapSensitiveAnalyzer)
|
|
28
|
+
this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION, sqlSensitiveAnalyzer)
|
|
29
29
|
this._sensitiveAnalyzers.set(vulnerabilities.SSRF, urlSensitiveAnalyzer)
|
|
30
30
|
this._sensitiveAnalyzers.set(vulnerabilities.UNVALIDATED_REDIRECT, urlSensitiveAnalyzer)
|
|
31
|
+
this._sensitiveAnalyzers.set(vulnerabilities.HEADER_INJECTION, (evidence) => {
|
|
32
|
+
return headerSensitiveAnalyzer(evidence, this._namePattern, this._valuePattern)
|
|
33
|
+
})
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
isSensibleName (name) {
|
|
@@ -47,7 +50,7 @@ class SensitiveHandler {
|
|
|
47
50
|
scrubEvidence (vulnerabilityType, evidence, sourcesIndexes, sources) {
|
|
48
51
|
const sensitiveAnalyzer = this._sensitiveAnalyzers.get(vulnerabilityType)
|
|
49
52
|
if (sensitiveAnalyzer) {
|
|
50
|
-
const sensitiveRanges = sensitiveAnalyzer
|
|
53
|
+
const sensitiveRanges = sensitiveAnalyzer(evidence)
|
|
51
54
|
return this.toRedactedJson(evidence, sensitiveRanges, sourcesIndexes, sources)
|
|
52
55
|
}
|
|
53
56
|
return null
|
|
@@ -28,6 +28,14 @@ const { storage } = require('../../../datadog-core')
|
|
|
28
28
|
let isEnabled = false
|
|
29
29
|
let config
|
|
30
30
|
|
|
31
|
+
function sampleRequest ({ enabled, requestSampling }) {
|
|
32
|
+
if (!enabled || !requestSampling) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return Math.random() <= requestSampling
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
function enable (_config) {
|
|
32
40
|
if (isEnabled) return
|
|
33
41
|
|
|
@@ -90,6 +98,10 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
|
90
98
|
payload[addresses.HTTP_CLIENT_IP] = clientIp
|
|
91
99
|
}
|
|
92
100
|
|
|
101
|
+
if (sampleRequest(config.appsec.apiSecurity)) {
|
|
102
|
+
payload[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
103
|
+
}
|
|
104
|
+
|
|
93
105
|
const actions = waf.run(payload, req)
|
|
94
106
|
|
|
95
107
|
handleResults(actions, req, res, rootSpan, abortController)
|
|
@@ -101,7 +113,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
101
113
|
delete responseHeaders['set-cookie']
|
|
102
114
|
|
|
103
115
|
const payload = {
|
|
104
|
-
[addresses.HTTP_INCOMING_RESPONSE_CODE]: res.statusCode,
|
|
116
|
+
[addresses.HTTP_INCOMING_RESPONSE_CODE]: '' + res.statusCode,
|
|
105
117
|
[addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders
|
|
106
118
|
}
|
|
107
119
|
|