dd-trace 5.25.0 → 5.27.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 -0
- package/index.d.ts +17 -8
- package/init.js +60 -47
- package/package.json +5 -2
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-instrumentations/src/express.js +1 -1
- package/packages/datadog-instrumentations/src/handlebars.js +40 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +5 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/langchain.js +77 -0
- package/packages/datadog-instrumentations/src/next.js +19 -7
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +7 -6
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +34 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +8 -8
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-langchain/src/handlers/chain.js +50 -0
- package/packages/datadog-plugin-langchain/src/handlers/default.js +53 -0
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +63 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +99 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/index.js +48 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +57 -0
- package/packages/datadog-plugin-langchain/src/index.js +89 -0
- package/packages/datadog-plugin-langchain/src/tokens.js +35 -0
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +0 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +6 -6
- package/packages/dd-trace/src/appsec/recommended.json +353 -155
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +0 -7
- package/packages/dd-trace/src/appsec/reporter.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/utils.js +21 -2
- package/packages/dd-trace/src/config.js +21 -4
- package/packages/dd-trace/src/constants.js +6 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
- package/packages/dd-trace/src/crashtracking/index.js +15 -0
- package/packages/dd-trace/src/crashtracking/noop.js +8 -0
- package/packages/dd-trace/src/llmobs/sdk.js +1 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +3 -0
- package/packages/dd-trace/src/log/index.js +10 -13
- package/packages/dd-trace/src/log/log.js +52 -0
- package/packages/dd-trace/src/log/writer.js +50 -19
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +15 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -22
- package/packages/dd-trace/src/opentracing/span.js +14 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/tracing.js +2 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +39 -11
- package/packages/dd-trace/src/profiling/exporters/agent.js +42 -5
- package/packages/dd-trace/src/profiling/profiler.js +5 -2
- package/packages/dd-trace/src/proxy.js +5 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
- package/packages/dd-trace/src/telemetry/metrics.js +6 -1
- package/packages/dd-trace/src/util.js +16 -1
- package/version.js +4 -2
- /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { MEASURED } = require('../../../ext/tags')
|
|
4
|
+
const { storage } = require('../../datadog-core')
|
|
5
|
+
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
6
|
+
|
|
7
|
+
const API_KEY = 'langchain.request.api_key'
|
|
8
|
+
const MODEL = 'langchain.request.model'
|
|
9
|
+
const PROVIDER = 'langchain.request.provider'
|
|
10
|
+
const TYPE = 'langchain.request.type'
|
|
11
|
+
|
|
12
|
+
const LangChainHandler = require('./handlers/default')
|
|
13
|
+
const LangChainChatModelHandler = require('./handlers/language_models/chat_model')
|
|
14
|
+
const LangChainLLMHandler = require('./handlers/language_models/llm')
|
|
15
|
+
const LangChainChainHandler = require('./handlers/chain')
|
|
16
|
+
const LangChainEmbeddingHandler = require('./handlers/embedding')
|
|
17
|
+
|
|
18
|
+
class LangChainPlugin extends TracingPlugin {
|
|
19
|
+
static get id () { return 'langchain' }
|
|
20
|
+
static get operation () { return 'invoke' }
|
|
21
|
+
static get system () { return 'langchain' }
|
|
22
|
+
static get prefix () {
|
|
23
|
+
return 'tracing:apm:langchain:invoke'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
constructor () {
|
|
27
|
+
super(...arguments)
|
|
28
|
+
|
|
29
|
+
const langchainConfig = this._tracerConfig.langchain || {}
|
|
30
|
+
this.handlers = {
|
|
31
|
+
chain: new LangChainChainHandler(langchainConfig),
|
|
32
|
+
chat_model: new LangChainChatModelHandler(langchainConfig),
|
|
33
|
+
llm: new LangChainLLMHandler(langchainConfig),
|
|
34
|
+
embedding: new LangChainEmbeddingHandler(langchainConfig),
|
|
35
|
+
default: new LangChainHandler(langchainConfig)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
bindStart (ctx) {
|
|
40
|
+
const { resource, type } = ctx
|
|
41
|
+
const handler = this.handlers[type]
|
|
42
|
+
|
|
43
|
+
const instance = ctx.instance
|
|
44
|
+
const apiKey = handler.extractApiKey(instance)
|
|
45
|
+
const provider = handler.extractProvider(instance)
|
|
46
|
+
const model = handler.extractModel(instance)
|
|
47
|
+
|
|
48
|
+
const tags = handler.getSpanStartTags(ctx, provider) || []
|
|
49
|
+
|
|
50
|
+
if (apiKey) tags[API_KEY] = apiKey
|
|
51
|
+
if (provider) tags[PROVIDER] = provider
|
|
52
|
+
if (model) tags[MODEL] = model
|
|
53
|
+
if (type) tags[TYPE] = type
|
|
54
|
+
|
|
55
|
+
const span = this.startSpan('langchain.request', {
|
|
56
|
+
service: this.config.service,
|
|
57
|
+
resource,
|
|
58
|
+
kind: 'client',
|
|
59
|
+
meta: {
|
|
60
|
+
[MEASURED]: 1,
|
|
61
|
+
...tags
|
|
62
|
+
}
|
|
63
|
+
}, false)
|
|
64
|
+
|
|
65
|
+
const store = storage.getStore() || {}
|
|
66
|
+
ctx.currentStore = { ...store, span }
|
|
67
|
+
|
|
68
|
+
return ctx.currentStore
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
asyncEnd (ctx) {
|
|
72
|
+
const span = ctx.currentStore.span
|
|
73
|
+
|
|
74
|
+
const { type } = ctx
|
|
75
|
+
|
|
76
|
+
const handler = this.handlers[type]
|
|
77
|
+
const tags = handler.getSpanEndTags(ctx) || {}
|
|
78
|
+
|
|
79
|
+
span.addTags(tags)
|
|
80
|
+
|
|
81
|
+
span.finish()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getHandler (type) {
|
|
85
|
+
return this.handlers[type] || this.handlers.default
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = LangChainPlugin
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function getTokensFromLlmOutput (result) {
|
|
4
|
+
const tokens = {
|
|
5
|
+
input: 0,
|
|
6
|
+
output: 0,
|
|
7
|
+
total: 0
|
|
8
|
+
}
|
|
9
|
+
const { llmOutput } = result
|
|
10
|
+
if (!llmOutput) return tokens
|
|
11
|
+
|
|
12
|
+
const tokenUsage = llmOutput.tokenUsage || llmOutput.usage_metadata || llmOutput.usage_metadata
|
|
13
|
+
if (!tokenUsage) return tokens
|
|
14
|
+
|
|
15
|
+
for (const tokenNames of [['input', 'prompt'], ['output', 'completion'], ['total']]) {
|
|
16
|
+
let token = 0
|
|
17
|
+
for (const tokenName of tokenNames) {
|
|
18
|
+
const underScore = `${tokenName}_tokens`
|
|
19
|
+
const camelCase = `${tokenName}Tokens`
|
|
20
|
+
|
|
21
|
+
token = tokenUsage[underScore] || tokenUsage[camelCase] || token
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
tokens[tokenNames[0]] = token
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// assign total_tokens again in case it was improperly set the first time, or was not on tokenUsage
|
|
28
|
+
tokens.total = tokens.total || tokens.input + tokens.output
|
|
29
|
+
|
|
30
|
+
return tokens
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
getTokensFromLlmOutput
|
|
35
|
+
}
|
|
@@ -85,7 +85,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const relativeCoverageFiles = [...coverageFiles, suiteFile]
|
|
88
|
-
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
88
|
+
.map(filename => getTestSuitePath(filename, this.repositoryRoot || this.sourceRoot))
|
|
89
89
|
|
|
90
90
|
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
91
91
|
|
|
@@ -9,7 +9,6 @@ class MoleculerServerPlugin extends ServerPlugin {
|
|
|
9
9
|
|
|
10
10
|
start ({ action, ctx, broker }) {
|
|
11
11
|
const followsFrom = this.tracer.extract('text_map', ctx.meta)
|
|
12
|
-
|
|
13
12
|
this.startSpan(this.operationName(), {
|
|
14
13
|
childOf: followsFrom || this.activeSpan,
|
|
15
14
|
service: this.config.service || this.serviceName(),
|
|
@@ -1,61 +1,84 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const TTLCache = require('@isaacs/ttlcache')
|
|
4
|
+
const web = require('../plugins/util/web')
|
|
3
5
|
const log = require('../log')
|
|
6
|
+
const { AUTO_REJECT, USER_REJECT } = require('../../../../ext/priority')
|
|
7
|
+
|
|
8
|
+
const MAX_SIZE = 4096
|
|
4
9
|
|
|
5
10
|
let enabled
|
|
6
|
-
let
|
|
11
|
+
let sampledRequests
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
class NoopTTLCache {
|
|
14
|
+
clear () { }
|
|
15
|
+
set (key) { return undefined }
|
|
16
|
+
has (key) { return false }
|
|
17
|
+
}
|
|
9
18
|
|
|
10
19
|
function configure ({ apiSecurity }) {
|
|
11
20
|
enabled = apiSecurity.enabled
|
|
12
|
-
|
|
21
|
+
sampledRequests = apiSecurity.sampleDelay === 0
|
|
22
|
+
? new NoopTTLCache()
|
|
23
|
+
: new TTLCache({ max: MAX_SIZE, ttl: apiSecurity.sampleDelay * 1000 })
|
|
13
24
|
}
|
|
14
25
|
|
|
15
26
|
function disable () {
|
|
16
27
|
enabled = false
|
|
28
|
+
sampledRequests?.clear()
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
}
|
|
31
|
+
function sampleRequest (req, res, force = false) {
|
|
32
|
+
if (!enabled) return false
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
const key = computeKey(req, res)
|
|
35
|
+
if (!key || isSampled(key)) return false
|
|
25
36
|
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
const rootSpan = web.root(req)
|
|
38
|
+
if (!rootSpan) return false
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
let priority = getSpanPriority(rootSpan)
|
|
41
|
+
if (!priority) {
|
|
42
|
+
rootSpan._prioritySampler?.sample(rootSpan)
|
|
43
|
+
priority = getSpanPriority(rootSpan)
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function sampleRequest (req) {
|
|
38
|
-
if (!enabled || !requestSampling) {
|
|
46
|
+
if (priority === AUTO_REJECT || priority === USER_REJECT) {
|
|
39
47
|
return false
|
|
40
48
|
}
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (shouldSample) {
|
|
45
|
-
sampledRequests.add(req)
|
|
50
|
+
if (force) {
|
|
51
|
+
sampledRequests.set(key)
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
return
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isSampled (key) {
|
|
58
|
+
return sampledRequests.has(key)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function computeKey (req, res) {
|
|
62
|
+
const route = web.getContext(req)?.paths?.join('') || ''
|
|
63
|
+
const method = req.method
|
|
64
|
+
const status = res.statusCode
|
|
65
|
+
|
|
66
|
+
if (!method || !status) {
|
|
67
|
+
log.warn('Unsupported groupkey for API security')
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
return method + route + status
|
|
49
71
|
}
|
|
50
72
|
|
|
51
|
-
function
|
|
52
|
-
|
|
73
|
+
function getSpanPriority (span) {
|
|
74
|
+
const spanContext = span.context?.()
|
|
75
|
+
return spanContext._sampling?.priority
|
|
53
76
|
}
|
|
54
77
|
|
|
55
78
|
module.exports = {
|
|
56
79
|
configure,
|
|
57
80
|
disable,
|
|
58
|
-
setRequestSampling,
|
|
59
81
|
sampleRequest,
|
|
60
|
-
isSampled
|
|
82
|
+
isSampled,
|
|
83
|
+
computeKey
|
|
61
84
|
}
|
|
@@ -15,6 +15,7 @@ module.exports = {
|
|
|
15
15
|
PATH_TRAVERSAL_ANALYZER: require('./path-traversal-analyzer'),
|
|
16
16
|
SQL_INJECTION_ANALYZER: require('./sql-injection-analyzer'),
|
|
17
17
|
SSRF: require('./ssrf-analyzer'),
|
|
18
|
+
TEMPLATE_INJECTION_ANALYZER: require('./template-injection-analyzer'),
|
|
18
19
|
UNVALIDATED_REDIRECT_ANALYZER: require('./unvalidated-redirect-analyzer'),
|
|
19
20
|
WEAK_CIPHER_ANALYZER: require('./weak-cipher-analyzer'),
|
|
20
21
|
WEAK_HASH_ANALYZER: require('./weak-hash-analyzer'),
|
|
@@ -6,7 +6,6 @@ const { getNodeModulesPaths } = require('../path-line')
|
|
|
6
6
|
const { HEADER_NAME_VALUE_SEPARATOR } = require('../vulnerabilities-formatter/constants')
|
|
7
7
|
const { getRanges } = require('../taint-tracking/operations')
|
|
8
8
|
const {
|
|
9
|
-
HTTP_REQUEST_COOKIE_NAME,
|
|
10
9
|
HTTP_REQUEST_COOKIE_VALUE,
|
|
11
10
|
HTTP_REQUEST_HEADER_VALUE
|
|
12
11
|
} = require('../taint-tracking/source-types')
|
|
@@ -45,13 +44,7 @@ class HeaderInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
45
44
|
if (this.isExcludedHeaderName(lowerCasedHeaderName) || typeof value !== 'string') return
|
|
46
45
|
|
|
47
46
|
const ranges = getRanges(iastContext, value)
|
|
48
|
-
|
|
49
|
-
return !(this.isCookieExclusion(lowerCasedHeaderName, ranges) ||
|
|
50
|
-
this.isSameHeaderExclusion(lowerCasedHeaderName, ranges) ||
|
|
51
|
-
this.isAccessControlAllowExclusion(lowerCasedHeaderName, ranges))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return false
|
|
47
|
+
return ranges?.length > 0 && !this.shouldIgnoreHeader(lowerCasedHeaderName, ranges)
|
|
55
48
|
}
|
|
56
49
|
|
|
57
50
|
_getEvidence (headerInfo, iastContext) {
|
|
@@ -75,28 +68,52 @@ class HeaderInjectionAnalyzer extends InjectionAnalyzer {
|
|
|
75
68
|
return EXCLUDED_HEADER_NAMES.includes(name)
|
|
76
69
|
}
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
isAllRangesFromHeader (ranges, headerName) {
|
|
72
|
+
return ranges
|
|
73
|
+
.every(range =>
|
|
74
|
+
range.iinfo.type === HTTP_REQUEST_HEADER_VALUE && range.iinfo.parameterName?.toLowerCase() === headerName
|
|
75
|
+
)
|
|
76
|
+
}
|
|
83
77
|
|
|
84
|
-
|
|
78
|
+
isAllRangesFromSource (ranges, source) {
|
|
79
|
+
return ranges
|
|
80
|
+
.every(range => range.iinfo.type === source)
|
|
85
81
|
}
|
|
86
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Exclude access-control-allow-*: when the header starts with access-control-allow- and the
|
|
85
|
+
* source of the tainted range is a request header
|
|
86
|
+
*/
|
|
87
87
|
isAccessControlAllowExclusion (name, ranges) {
|
|
88
88
|
if (name?.startsWith('access-control-allow-')) {
|
|
89
|
-
return ranges
|
|
90
|
-
.every(range => range.iinfo.type === HTTP_REQUEST_HEADER_VALUE)
|
|
89
|
+
return this.isAllRangesFromSource(ranges, HTTP_REQUEST_HEADER_VALUE)
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
return false
|
|
94
93
|
}
|
|
95
94
|
|
|
95
|
+
/** Exclude when the header is reflected from the request */
|
|
96
96
|
isSameHeaderExclusion (name, ranges) {
|
|
97
97
|
return ranges.length === 1 && name === ranges[0].iinfo.parameterName?.toLowerCase()
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
shouldIgnoreHeader (headerName, ranges) {
|
|
101
|
+
switch (headerName) {
|
|
102
|
+
case 'set-cookie':
|
|
103
|
+
/** Exclude set-cookie header if the source of all the tainted ranges are cookies */
|
|
104
|
+
return this.isAllRangesFromSource(ranges, HTTP_REQUEST_COOKIE_VALUE)
|
|
105
|
+
case 'pragma':
|
|
106
|
+
/** Ignore pragma headers when the source is the cache control header. */
|
|
107
|
+
return this.isAllRangesFromHeader(ranges, 'cache-control')
|
|
108
|
+
case 'transfer-encoding':
|
|
109
|
+
case 'content-encoding':
|
|
110
|
+
/** Ignore transfer and content encoding headers when the source is the accept encoding header. */
|
|
111
|
+
return this.isAllRangesFromHeader(ranges, 'accept-encoding')
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return this.isAccessControlAllowExclusion(headerName, ranges) || this.isSameHeaderExclusion(headerName, ranges)
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
_getExcludedPaths () {
|
|
101
118
|
return EXCLUDED_PATHS
|
|
102
119
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const InjectionAnalyzer = require('./injection-analyzer')
|
|
4
|
+
const { TEMPLATE_INJECTION } = require('../vulnerabilities')
|
|
5
|
+
|
|
6
|
+
class TemplateInjectionAnalyzer extends InjectionAnalyzer {
|
|
7
|
+
constructor () {
|
|
8
|
+
super(TEMPLATE_INJECTION)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
onConfigure () {
|
|
12
|
+
this.addSub('datadog:handlebars:compile:start', ({ source }) => this.analyze(source))
|
|
13
|
+
this.addSub('datadog:handlebars:register-partial:start', ({ partial }) => this.analyze(partial))
|
|
14
|
+
this.addSub('datadog:pug:compile:start', ({ source }) => this.analyze(source))
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = new TemplateInjectionAnalyzer()
|
|
@@ -5,13 +5,13 @@ const vulnerabilities = require('../../vulnerabilities')
|
|
|
5
5
|
|
|
6
6
|
const { contains, intersects, remove } = require('./range-utils')
|
|
7
7
|
|
|
8
|
-
const codeInjectionSensitiveAnalyzer = require('./sensitive-analyzers/code-injection-sensitive-analyzer')
|
|
9
8
|
const commandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
|
|
10
9
|
const hardcodedPasswordAnalyzer = require('./sensitive-analyzers/hardcoded-password-analyzer')
|
|
11
10
|
const headerSensitiveAnalyzer = require('./sensitive-analyzers/header-sensitive-analyzer')
|
|
12
11
|
const jsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
|
|
13
12
|
const ldapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
|
|
14
13
|
const sqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
|
|
14
|
+
const taintedRangeBasedSensitiveAnalyzer = require('./sensitive-analyzers/tainted-range-based-sensitive-analyzer')
|
|
15
15
|
const urlSensitiveAnalyzer = require('./sensitive-analyzers/url-sensitive-analyzer')
|
|
16
16
|
|
|
17
17
|
const { DEFAULT_IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN } = require('./sensitive-regex')
|
|
@@ -24,7 +24,8 @@ class SensitiveHandler {
|
|
|
24
24
|
this._valuePattern = new RegExp(DEFAULT_IAST_REDACTION_VALUE_PATTERN, 'gmi')
|
|
25
25
|
|
|
26
26
|
this._sensitiveAnalyzers = new Map()
|
|
27
|
-
this._sensitiveAnalyzers.set(vulnerabilities.CODE_INJECTION,
|
|
27
|
+
this._sensitiveAnalyzers.set(vulnerabilities.CODE_INJECTION, taintedRangeBasedSensitiveAnalyzer)
|
|
28
|
+
this._sensitiveAnalyzers.set(vulnerabilities.TEMPLATE_INJECTION, taintedRangeBasedSensitiveAnalyzer)
|
|
28
29
|
this._sensitiveAnalyzers.set(vulnerabilities.COMMAND_INJECTION, commandSensitiveAnalyzer)
|
|
29
30
|
this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, jsonSensitiveAnalyzer)
|
|
30
31
|
this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, ldapSensitiveAnalyzer)
|
|
@@ -145,10 +145,6 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
|
145
145
|
persistent[addresses.HTTP_CLIENT_IP] = clientIp
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
if (apiSecuritySampler.sampleRequest(req)) {
|
|
149
|
-
persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
150
|
-
}
|
|
151
|
-
|
|
152
148
|
const actions = waf.run({ persistent }, req)
|
|
153
149
|
|
|
154
150
|
handleResults(actions, req, res, rootSpan, abortController)
|
|
@@ -172,6 +168,10 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
172
168
|
persistent[addresses.HTTP_INCOMING_QUERY] = req.query
|
|
173
169
|
}
|
|
174
170
|
|
|
171
|
+
if (apiSecuritySampler.sampleRequest(req, res, true)) {
|
|
172
|
+
persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
175
|
if (Object.keys(persistent).length) {
|
|
176
176
|
waf.run({ persistent }, req)
|
|
177
177
|
}
|
|
@@ -228,9 +228,9 @@ function onRequestProcessParams ({ req, res, abortController, params }) {
|
|
|
228
228
|
handleResults(results, req, res, rootSpan, abortController)
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
function onResponseBody ({ req, body }) {
|
|
231
|
+
function onResponseBody ({ req, res, body }) {
|
|
232
232
|
if (!body || typeof body !== 'object') return
|
|
233
|
-
if (!apiSecuritySampler.
|
|
233
|
+
if (!apiSecuritySampler.sampleRequest(req, res)) return
|
|
234
234
|
|
|
235
235
|
// we don't support blocking at this point, so no results needed
|
|
236
236
|
waf.run({
|