dd-trace 5.101.0 → 5.102.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/package.json +9 -7
- package/packages/datadog-instrumentations/src/aerospike.js +2 -2
- package/packages/datadog-instrumentations/src/ai.js +8 -8
- package/packages/datadog-instrumentations/src/amqplib.js +6 -7
- package/packages/datadog-instrumentations/src/anthropic.js +10 -10
- package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
- package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
- package/packages/datadog-instrumentations/src/avsc.js +6 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
- package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
- package/packages/datadog-instrumentations/src/bluebird.js +2 -2
- package/packages/datadog-instrumentations/src/body-parser.js +2 -2
- package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
- package/packages/datadog-instrumentations/src/child_process.js +12 -12
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +9 -9
- package/packages/datadog-instrumentations/src/connect.js +7 -7
- package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
- package/packages/datadog-instrumentations/src/cookie.js +2 -2
- package/packages/datadog-instrumentations/src/couchbase.js +16 -30
- package/packages/datadog-instrumentations/src/crypto.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +77 -16
- package/packages/datadog-instrumentations/src/dns.js +0 -3
- package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
- package/packages/datadog-instrumentations/src/express-session.js +4 -4
- package/packages/datadog-instrumentations/src/express.js +10 -11
- package/packages/datadog-instrumentations/src/fastify.js +2 -2
- package/packages/datadog-instrumentations/src/fs.js +14 -14
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
- package/packages/datadog-instrumentations/src/google-genai.js +4 -4
- package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
- package/packages/datadog-instrumentations/src/hapi.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
- package/packages/datadog-instrumentations/src/hono.js +2 -2
- package/packages/datadog-instrumentations/src/http/client.js +6 -6
- package/packages/datadog-instrumentations/src/http/server.js +9 -9
- package/packages/datadog-instrumentations/src/jest.js +31 -31
- package/packages/datadog-instrumentations/src/kafkajs.js +9 -9
- package/packages/datadog-instrumentations/src/knex.js +17 -17
- package/packages/datadog-instrumentations/src/koa.js +12 -12
- package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
- package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
- package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
- package/packages/datadog-instrumentations/src/lodash.js +4 -4
- package/packages/datadog-instrumentations/src/mariadb.js +13 -13
- package/packages/datadog-instrumentations/src/memcached.js +2 -2
- package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +12 -10
- package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
- package/packages/datadog-instrumentations/src/mongodb-core.js +9 -22
- package/packages/datadog-instrumentations/src/mongodb.js +5 -5
- package/packages/datadog-instrumentations/src/mongoose.js +21 -21
- package/packages/datadog-instrumentations/src/mquery.js +5 -5
- package/packages/datadog-instrumentations/src/multer.js +4 -4
- package/packages/datadog-instrumentations/src/mysql.js +16 -16
- package/packages/datadog-instrumentations/src/mysql2.js +4 -4
- package/packages/datadog-instrumentations/src/net.js +14 -8
- package/packages/datadog-instrumentations/src/nyc.js +5 -5
- package/packages/datadog-instrumentations/src/openai.js +19 -19
- package/packages/datadog-instrumentations/src/oracledb.js +6 -6
- package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
- package/packages/datadog-instrumentations/src/pg.js +15 -15
- package/packages/datadog-instrumentations/src/pino.js +6 -10
- package/packages/datadog-instrumentations/src/playwright.js +20 -15
- package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
- package/packages/datadog-instrumentations/src/redis.js +1 -2
- package/packages/datadog-instrumentations/src/restify.js +2 -2
- package/packages/datadog-instrumentations/src/router.js +12 -12
- package/packages/datadog-instrumentations/src/stripe.js +12 -12
- package/packages/datadog-instrumentations/src/vitest.js +107 -26
- package/packages/datadog-instrumentations/src/winston.js +4 -4
- package/packages/datadog-instrumentations/src/ws.js +7 -7
- package/packages/datadog-plugin-aws-sdk/src/base.js +52 -4
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +19 -12
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +45 -35
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +33 -22
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +12 -13
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +73 -54
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +19 -17
- package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
- package/packages/datadog-plugin-cucumber/src/index.js +4 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
- package/packages/datadog-plugin-http/src/client.js +1 -5
- package/packages/datadog-plugin-jest/src/util.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +4 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +12 -23
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +8 -1
- package/packages/datadog-shimmer/src/shimmer.js +7 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
- package/packages/dd-trace/src/appsec/index.js +21 -24
- package/packages/dd-trace/src/appsec/reporter.js +3 -1
- package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
- package/packages/dd-trace/src/config/git_properties.js +2 -2
- package/packages/dd-trace/src/datastreams/index.js +2 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
- package/packages/dd-trace/src/encode/0.4.js +757 -232
- package/packages/dd-trace/src/encode/0.5.js +13 -7
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
- package/packages/dd-trace/src/llmobs/sdk.js +24 -26
- package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
- package/packages/dd-trace/src/llmobs/util.js +1 -0
- package/packages/dd-trace/src/msgpack/chunk.js +6 -3
- package/packages/dd-trace/src/openfeature/noop.js +40 -36
- package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
- package/packages/dd-trace/src/plugins/util/ci.js +1 -1
- package/packages/dd-trace/src/plugins/util/git-cache.js +3 -5
- package/packages/dd-trace/src/plugins/util/test.js +19 -7
- package/packages/dd-trace/src/plugins/util/url.js +1 -3
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +5 -7
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
- package/packages/dd-trace/src/profiling/profilers/wall.js +4 -5
- package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
- package/packages/dd-trace/src/scope.js +3 -10
- package/packages/dd-trace/src/serverless.js +1 -4
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +7 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +4 -0
- package/packages/dd-trace/src/tracer.js +7 -7
|
@@ -83,14 +83,12 @@ class VulnerabilityFormatter {
|
|
|
83
83
|
formatVulnerability (vulnerability, sourcesIndexes, sources) {
|
|
84
84
|
const { type, hash, evidence, location } = vulnerability
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
return {
|
|
87
87
|
type,
|
|
88
88
|
hash,
|
|
89
89
|
evidence: this.formatEvidence(type, evidence, sourcesIndexes, sources),
|
|
90
90
|
location,
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
return formattedVulnerability
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
toJson (vulnerabilitiesToFormat) {
|
|
@@ -9,8 +9,9 @@ const STRINGIFY_SENSITIVE_KEY = STRINGIFY_RANGE_KEY + 'SENSITIVE'
|
|
|
9
9
|
const STRINGIFY_SENSITIVE_NOT_STRING_KEY = STRINGIFY_SENSITIVE_KEY + 'NOTSTRING'
|
|
10
10
|
|
|
11
11
|
// eslint-disable-next-line @stylistic/max-len
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const REGEX_FOR_STRINGIFY_SENSITIVE_NOT_STRING = new RegExp(String.raw`"${STRINGIFY_SENSITIVE_NOT_STRING_KEY}_\d+_([\s\-+0-9.a-zA-Z]*)"`)
|
|
13
|
+
const REGEX_FOR_STRINGIFY_SENSITIVE = new RegExp(String.raw`${STRINGIFY_SENSITIVE_KEY}_\d+_(\d+)_`)
|
|
14
|
+
const REGEX_FOR_STRINGIFY_RANGE = new RegExp(String.raw`(${STRINGIFY_RANGE_KEY}_\d+_)`)
|
|
14
15
|
|
|
15
16
|
const sensitiveValueRegex = new RegExp(/** @type {string} */ (defaults['iast.redactionValuePattern']), 'gmi')
|
|
16
17
|
|
|
@@ -41,7 +42,6 @@ function stringifyWithRanges (obj, objRanges, loadSensitiveRanges = false) {
|
|
|
41
42
|
let counter = 0
|
|
42
43
|
const allRanges = {}
|
|
43
44
|
const sensitiveKeysMapping = {}
|
|
44
|
-
|
|
45
45
|
iterateObject(obj, (val, levelKeys, parent, key) => {
|
|
46
46
|
let currentLevelClone = cloneObj
|
|
47
47
|
for (let i = 0; i < levelKeys.length - 1; i++) {
|
|
@@ -108,55 +108,90 @@ function stringifyWithRanges (obj, objRanges, loadSensitiveRanges = false) {
|
|
|
108
108
|
value = JSON.stringify(cloneObj, null, 2)
|
|
109
109
|
|
|
110
110
|
if (counter > 0) {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
// is
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
111
|
+
const segments = []
|
|
112
|
+
let outputLength = 0
|
|
113
|
+
let pos = 0
|
|
114
|
+
let rangeKeyIndex = value.indexOf(STRINGIFY_RANGE_KEY)
|
|
115
|
+
|
|
116
|
+
while (rangeKeyIndex > -1) {
|
|
117
|
+
let remainingStringValue = value.slice(rangeKeyIndex)
|
|
118
|
+
let cleanLength = rangeKeyIndex - pos
|
|
119
|
+
|
|
120
|
+
if (remainingStringValue.startsWith(STRINGIFY_SENSITIVE_NOT_STRING_KEY)) {
|
|
121
|
+
// In this case, we want to remove also the previous " char, because the value is not an string
|
|
122
|
+
rangeKeyIndex--
|
|
123
|
+
cleanLength--
|
|
124
|
+
remainingStringValue = value.slice(rangeKeyIndex)
|
|
125
|
+
const regexRes = REGEX_FOR_STRINGIFY_SENSITIVE_NOT_STRING.exec(remainingStringValue)
|
|
126
|
+
|
|
127
|
+
if (regexRes?.index === 0) {
|
|
128
|
+
const matchValue = regexRes[0]
|
|
129
|
+
const originalValue = regexRes[1]
|
|
130
|
+
const start = outputLength + cleanLength
|
|
131
|
+
|
|
132
|
+
sensitiveRanges.push({
|
|
133
|
+
start,
|
|
134
|
+
end: start + originalValue.length,
|
|
135
|
+
})
|
|
136
|
+
segments.push(value.slice(pos, rangeKeyIndex), originalValue)
|
|
137
|
+
outputLength += cleanLength + originalValue.length
|
|
138
|
+
pos = rangeKeyIndex + matchValue.length
|
|
139
|
+
} else {
|
|
140
|
+
// can't happen, the only way to this to happen is
|
|
141
|
+
// if the JSON has a value starting with the value of STRINGIFY_SENSITIVE_NOT_STRING_KEY
|
|
142
|
+
segments.push(value.slice(pos, rangeKeyIndex + STRINGIFY_SENSITIVE_NOT_STRING_KEY.length + 1))
|
|
143
|
+
outputLength += cleanLength + STRINGIFY_SENSITIVE_NOT_STRING_KEY.length + 1
|
|
144
|
+
pos = rangeKeyIndex + STRINGIFY_SENSITIVE_NOT_STRING_KEY.length + 1
|
|
145
|
+
}
|
|
146
|
+
} else if (remainingStringValue.startsWith(STRINGIFY_SENSITIVE_KEY)) {
|
|
147
|
+
const regexRes = REGEX_FOR_STRINGIFY_SENSITIVE.exec(remainingStringValue)
|
|
148
|
+
if (regexRes?.index === 0) {
|
|
149
|
+
const start = outputLength + cleanLength
|
|
150
|
+
|
|
151
|
+
sensitiveRanges.push({
|
|
152
|
+
start,
|
|
153
|
+
end: start + Number.parseInt(regexRes[1]),
|
|
154
|
+
})
|
|
155
|
+
segments.push(value.slice(pos, rangeKeyIndex))
|
|
156
|
+
outputLength += cleanLength
|
|
157
|
+
pos = rangeKeyIndex + regexRes[0].length
|
|
158
|
+
} else {
|
|
159
|
+
// can't happen, the only way to this to happen is
|
|
160
|
+
// if the JSON has a value starting with the value of STRINGIFY_SENSITIVE_KEY
|
|
161
|
+
segments.push(value.slice(pos, rangeKeyIndex + STRINGIFY_SENSITIVE_KEY.length))
|
|
162
|
+
outputLength += cleanLength + STRINGIFY_SENSITIVE_KEY.length
|
|
163
|
+
pos = rangeKeyIndex + STRINGIFY_SENSITIVE_KEY.length
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
const regexRes = REGEX_FOR_STRINGIFY_RANGE.exec(remainingStringValue)
|
|
167
|
+
if (regexRes?.index === 0) {
|
|
168
|
+
const start = outputLength + cleanLength
|
|
169
|
+
const rangesId = regexRes[1]
|
|
170
|
+
|
|
171
|
+
const updatedRanges = allRanges[rangesId].map(range => ({
|
|
127
172
|
...range,
|
|
128
|
-
start: range.start +
|
|
129
|
-
end: range.end +
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
value = value.replace(sensitiveId, '')
|
|
144
|
-
} else if (regexRes[4]) {
|
|
145
|
-
// is a sensitive value (number, null, false, ...)
|
|
146
|
-
const sensitiveId = regexRes[4]
|
|
147
|
-
const originalValue = regexRes[5]
|
|
148
|
-
|
|
149
|
-
sensitiveRanges.push({
|
|
150
|
-
start: regexRes.index,
|
|
151
|
-
end: regexRes.index + originalValue.length,
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
value = value.replace(sensitiveId, originalValue)
|
|
173
|
+
start: range.start + start,
|
|
174
|
+
end: range.end + start,
|
|
175
|
+
}))
|
|
176
|
+
ranges.push(...updatedRanges)
|
|
177
|
+
|
|
178
|
+
segments.push(value.slice(pos, rangeKeyIndex))
|
|
179
|
+
outputLength += cleanLength
|
|
180
|
+
pos = rangeKeyIndex + regexRes[0].length
|
|
181
|
+
} else {
|
|
182
|
+
// can't happen, the only way to this to happen is
|
|
183
|
+
// if the JSON has a value starting with the value of STRINGIFY_RANGE_KEY
|
|
184
|
+
segments.push(value.slice(pos, rangeKeyIndex + STRINGIFY_RANGE_KEY.length))
|
|
185
|
+
outputLength += cleanLength + STRINGIFY_RANGE_KEY.length
|
|
186
|
+
pos = rangeKeyIndex + STRINGIFY_RANGE_KEY.length
|
|
187
|
+
}
|
|
155
188
|
}
|
|
156
189
|
|
|
157
|
-
|
|
158
|
-
regexRes = keysRegex.exec(value)
|
|
190
|
+
rangeKeyIndex = value.indexOf(STRINGIFY_RANGE_KEY, pos)
|
|
159
191
|
}
|
|
192
|
+
|
|
193
|
+
segments.push(value.slice(pos))
|
|
194
|
+
value = segments.join('')
|
|
160
195
|
}
|
|
161
196
|
} else {
|
|
162
197
|
value = JSON.stringify(obj, null, 2)
|
|
@@ -5,6 +5,7 @@ const web = require('../plugins/util/web')
|
|
|
5
5
|
const { extractIp } = require('../plugins/util/ip_extractor')
|
|
6
6
|
const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
|
|
7
7
|
const { IS_SERVERLESS } = require('../serverless')
|
|
8
|
+
const { isEmpty } = require('../util')
|
|
8
9
|
const RuleManager = require('./rule_manager')
|
|
9
10
|
const appsecRemoteConfig = require('./remote_config')
|
|
10
11
|
const {
|
|
@@ -128,7 +129,7 @@ function onRequestBodyParsed ({ req, res, body, abortController }) {
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
if (typeof body === 'object') {
|
|
131
|
-
if (
|
|
132
|
+
if (isEmpty(body)) return
|
|
132
133
|
analyzedBodies.add(body)
|
|
133
134
|
}
|
|
134
135
|
|
|
@@ -149,7 +150,7 @@ function onRequestCookieParser ({ req, res, abortController, cookies }) {
|
|
|
149
150
|
const rootSpan = web.root(req)
|
|
150
151
|
if (!rootSpan) return
|
|
151
152
|
|
|
152
|
-
if (
|
|
153
|
+
if (isEmpty(cookies)) return
|
|
153
154
|
analyzedCookies.add(cookies)
|
|
154
155
|
|
|
155
156
|
const results = waf.run({
|
|
@@ -180,12 +181,9 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
|
180
181
|
}
|
|
181
182
|
}
|
|
182
183
|
|
|
183
|
-
const requestHeaders = { ...req.headers }
|
|
184
|
-
delete requestHeaders.cookie
|
|
185
|
-
|
|
186
184
|
const persistent = {
|
|
187
185
|
[addresses.HTTP_INCOMING_URL]: req.url,
|
|
188
|
-
[addresses.HTTP_INCOMING_HEADERS]:
|
|
186
|
+
[addresses.HTTP_INCOMING_HEADERS]: copyHeadersOmitting(req.headers, 'cookie'),
|
|
189
187
|
[addresses.HTTP_INCOMING_METHOD]: req.method,
|
|
190
188
|
}
|
|
191
189
|
|
|
@@ -204,7 +202,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
204
202
|
// we need to keep this to support other body parsers
|
|
205
203
|
if (req.body !== undefined && req.body !== null) {
|
|
206
204
|
if (typeof req.body === 'object') {
|
|
207
|
-
if (!
|
|
205
|
+
if (!isEmpty(req.body) && !analyzedBodies.has(req.body)) {
|
|
208
206
|
persistent[addresses.HTTP_INCOMING_BODY] = req.body
|
|
209
207
|
}
|
|
210
208
|
} else {
|
|
@@ -216,7 +214,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
216
214
|
if (
|
|
217
215
|
req.cookies !== null &&
|
|
218
216
|
typeof req.cookies === 'object' &&
|
|
219
|
-
!
|
|
217
|
+
!isEmpty(req.cookies) &&
|
|
220
218
|
!analyzedCookies.has(req.cookies)
|
|
221
219
|
) {
|
|
222
220
|
persistent[addresses.HTTP_INCOMING_COOKIES] = req.cookies
|
|
@@ -227,7 +225,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
227
225
|
if (
|
|
228
226
|
query !== null &&
|
|
229
227
|
typeof query === 'object' &&
|
|
230
|
-
!
|
|
228
|
+
!isEmpty(query)
|
|
231
229
|
) {
|
|
232
230
|
persistent[addresses.HTTP_INCOMING_QUERY] = query
|
|
233
231
|
}
|
|
@@ -239,7 +237,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
239
237
|
persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
240
238
|
}
|
|
241
239
|
|
|
242
|
-
if (!
|
|
240
|
+
if (!isEmpty(persistent)) {
|
|
243
241
|
waf.run({ persistent }, req)
|
|
244
242
|
}
|
|
245
243
|
|
|
@@ -313,7 +311,7 @@ function onRequestQueryParsed ({ req, res, query, abortController }) {
|
|
|
313
311
|
const rootSpan = web.root(req)
|
|
314
312
|
if (!rootSpan) return
|
|
315
313
|
|
|
316
|
-
if (
|
|
314
|
+
if (isEmpty(query)) return
|
|
317
315
|
|
|
318
316
|
const results = waf.run({
|
|
319
317
|
persistent: {
|
|
@@ -328,7 +326,7 @@ function onRequestProcessParams ({ req, res, abortController, params }) {
|
|
|
328
326
|
const rootSpan = web.root(req)
|
|
329
327
|
if (!rootSpan) return
|
|
330
328
|
|
|
331
|
-
if (!params || typeof params !== 'object' ||
|
|
329
|
+
if (!params || typeof params !== 'object' || isEmpty(params)) return
|
|
332
330
|
|
|
333
331
|
const results = waf.run({
|
|
334
332
|
persistent: {
|
|
@@ -352,7 +350,7 @@ function onResponseBody ({ req, res, body }) {
|
|
|
352
350
|
}
|
|
353
351
|
|
|
354
352
|
function onResponseWriteHead ({ req, res, abortController, statusCode, responseHeaders }) {
|
|
355
|
-
if (!
|
|
353
|
+
if (!isEmpty(responseHeaders)) {
|
|
356
354
|
storedResponseHeaders.set(req, responseHeaders)
|
|
357
355
|
}
|
|
358
356
|
|
|
@@ -375,13 +373,10 @@ function onResponseWriteHead ({ req, res, abortController, statusCode, responseH
|
|
|
375
373
|
const rootSpan = web.root(req)
|
|
376
374
|
if (!rootSpan) return
|
|
377
375
|
|
|
378
|
-
responseHeaders = { ...responseHeaders }
|
|
379
|
-
delete responseHeaders['set-cookie']
|
|
380
|
-
|
|
381
376
|
const results = waf.run({
|
|
382
377
|
persistent: {
|
|
383
378
|
[addresses.HTTP_INCOMING_RESPONSE_CODE]: String(statusCode),
|
|
384
|
-
[addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders,
|
|
379
|
+
[addresses.HTTP_INCOMING_RESPONSE_HEADERS]: copyHeadersOmitting(responseHeaders, 'set-cookie'),
|
|
385
380
|
},
|
|
386
381
|
}, req)
|
|
387
382
|
|
|
@@ -540,14 +535,16 @@ function disable () {
|
|
|
540
535
|
if (stripeConstructEvent.hasSubscribers) stripeConstructEvent.unsubscribe(onStripeConstructEvent)
|
|
541
536
|
}
|
|
542
537
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
538
|
+
/**
|
|
539
|
+
* @param {Record<string, unknown>} src
|
|
540
|
+
* @param {string} omit
|
|
541
|
+
*/
|
|
542
|
+
function copyHeadersOmitting (src, omit) {
|
|
543
|
+
const filtered = {}
|
|
544
|
+
for (const key of Object.keys(src)) {
|
|
545
|
+
if (key !== omit) filtered[key] = src[key]
|
|
548
546
|
}
|
|
549
|
-
|
|
550
|
-
return true
|
|
547
|
+
return filtered
|
|
551
548
|
}
|
|
552
549
|
|
|
553
550
|
module.exports = {
|
|
@@ -509,7 +509,9 @@ function finishRequest (req, res, storedResponseHeaders, requestBody) {
|
|
|
509
509
|
if (!rootSpan) return
|
|
510
510
|
|
|
511
511
|
if (metricsQueue.size) {
|
|
512
|
-
|
|
512
|
+
for (const [key, value] of metricsQueue) {
|
|
513
|
+
rootSpan.setTag(key, value)
|
|
514
|
+
}
|
|
513
515
|
|
|
514
516
|
keepTrace(rootSpan, ASM)
|
|
515
517
|
|
|
@@ -142,12 +142,14 @@ function extractErrors (diagnostics) {
|
|
|
142
142
|
|
|
143
143
|
for (const diagnosticKey of DIAGNOSTIC_KEYS) {
|
|
144
144
|
if (diagnostics[diagnosticKey]?.error) {
|
|
145
|
-
|
|
145
|
+
result[diagnosticKey] ??= {}
|
|
146
|
+
result[diagnosticKey].error = diagnostics[diagnosticKey]?.error
|
|
146
147
|
isResultPopulated = true
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
if (diagnostics[diagnosticKey]?.errors) {
|
|
150
|
-
|
|
151
|
+
result[diagnosticKey] ??= {}
|
|
152
|
+
result[diagnosticKey].errors = diagnostics[diagnosticKey]?.errors
|
|
151
153
|
isResultPopulated = true
|
|
152
154
|
}
|
|
153
155
|
}
|
|
@@ -20,6 +20,20 @@ class WAFContextWrapper {
|
|
|
20
20
|
this.knownAddresses = knownAddresses
|
|
21
21
|
this.addressesToSkip = new Set()
|
|
22
22
|
this.cachedUserIdResults = new Map()
|
|
23
|
+
// Reused across run() calls; Reporter.reportMetrics consumes it synchronously.
|
|
24
|
+
this.metrics = {
|
|
25
|
+
rulesVersion,
|
|
26
|
+
wafVersion,
|
|
27
|
+
wafTimeout: false,
|
|
28
|
+
duration: 0,
|
|
29
|
+
durationExt: 0,
|
|
30
|
+
blockTriggered: false,
|
|
31
|
+
ruleTriggered: false,
|
|
32
|
+
errorCode: null,
|
|
33
|
+
maxTruncatedString: null,
|
|
34
|
+
maxTruncatedContainerSize: null,
|
|
35
|
+
maxTruncatedContainerDepth: null,
|
|
36
|
+
}
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
run ({ persistent, ephemeral }, raspRule, req) {
|
|
@@ -44,7 +58,8 @@ class WAFContextWrapper {
|
|
|
44
58
|
|
|
45
59
|
const payload = {}
|
|
46
60
|
let payloadHasData = false
|
|
47
|
-
|
|
61
|
+
// Cloned lazily; only the preventDuplicateAddresses branch below adds to it.
|
|
62
|
+
let newAddressesToSkip
|
|
48
63
|
|
|
49
64
|
if (persistent !== null && typeof persistent === 'object') {
|
|
50
65
|
const persistentInputs = {}
|
|
@@ -55,6 +70,7 @@ class WAFContextWrapper {
|
|
|
55
70
|
hasPersistentInputs = true
|
|
56
71
|
persistentInputs[key] = persistent[key]
|
|
57
72
|
if (preventDuplicateAddresses.has(key)) {
|
|
73
|
+
newAddressesToSkip ??= new Set(this.addressesToSkip)
|
|
58
74
|
newAddressesToSkip.add(key)
|
|
59
75
|
}
|
|
60
76
|
}
|
|
@@ -85,19 +101,16 @@ class WAFContextWrapper {
|
|
|
85
101
|
|
|
86
102
|
if (!payloadHasData) return
|
|
87
103
|
|
|
88
|
-
const metrics =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
maxTruncatedContainerSize: null,
|
|
99
|
-
maxTruncatedContainerDepth: null,
|
|
100
|
-
}
|
|
104
|
+
const metrics = this.metrics
|
|
105
|
+
metrics.wafTimeout = false
|
|
106
|
+
metrics.duration = 0
|
|
107
|
+
metrics.durationExt = 0
|
|
108
|
+
metrics.blockTriggered = false
|
|
109
|
+
metrics.ruleTriggered = false
|
|
110
|
+
metrics.errorCode = null
|
|
111
|
+
metrics.maxTruncatedString = null
|
|
112
|
+
metrics.maxTruncatedContainerSize = null
|
|
113
|
+
metrics.maxTruncatedContainerDepth = null
|
|
101
114
|
|
|
102
115
|
try {
|
|
103
116
|
const start = process.hrtime.bigint()
|
|
@@ -106,7 +119,7 @@ class WAFContextWrapper {
|
|
|
106
119
|
|
|
107
120
|
const end = process.hrtime.bigint()
|
|
108
121
|
|
|
109
|
-
metrics.durationExt = Number
|
|
122
|
+
metrics.durationExt = Number(end - start) / 1e3
|
|
110
123
|
|
|
111
124
|
if (typeof result.errorCode === 'number' && result.errorCode < 0) {
|
|
112
125
|
const error = new Error('WAF code error')
|
|
@@ -123,7 +136,9 @@ class WAFContextWrapper {
|
|
|
123
136
|
if (maxTruncatedContainerDepth) metrics.maxTruncatedContainerDepth = maxTruncatedContainerDepth
|
|
124
137
|
}
|
|
125
138
|
|
|
126
|
-
|
|
139
|
+
if (newAddressesToSkip !== undefined) {
|
|
140
|
+
this.addressesToSkip = newAddressesToSkip
|
|
141
|
+
}
|
|
127
142
|
|
|
128
143
|
const ruleTriggered = !!result.events?.length
|
|
129
144
|
|
|
@@ -4,8 +4,8 @@ const fs = require('fs')
|
|
|
4
4
|
const path = require('path')
|
|
5
5
|
|
|
6
6
|
const gitPropertiesCommitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
|
|
7
|
-
const gitPropertiesRepositoryUrlRegex = /git\.repository_url=([\w
|
|
8
|
-
const repositoryUrlRegex = /^([\w
|
|
7
|
+
const gitPropertiesRepositoryUrlRegex = /git\.repository_url=([\w:@/.-]+)/
|
|
8
|
+
const repositoryUrlRegex = /^([\w:@/.-]+)$/
|
|
9
9
|
const remoteOriginRegex = /^\[remote\s+"origin"\]/i
|
|
10
10
|
const gitHeadRefRegex = /ref:\s+(refs\/[A-Za-z0-9._/-]+)/
|
|
11
11
|
const commitSHARegex = /^[0-9a-f]{40}$/
|
|
@@ -271,8 +271,7 @@ class DataStreamsProcessor {
|
|
|
271
271
|
*/
|
|
272
272
|
bucketFromTimestamp (timestamp) {
|
|
273
273
|
const bucketTime = Math.round(timestamp - (timestamp % this.bucketSizeNs))
|
|
274
|
-
|
|
275
|
-
return bucket
|
|
274
|
+
return this.buckets.forTime(bucketTime)
|
|
276
275
|
}
|
|
277
276
|
|
|
278
277
|
recordCheckpoint (checkpoint, span = null) {
|
|
@@ -175,6 +175,7 @@ function parseJsonToTree (json) {
|
|
|
175
175
|
switch (json.charCodeAt(index)) {
|
|
176
176
|
case 34: { // 34: double quote
|
|
177
177
|
const stringStart = index + 1
|
|
178
|
+
// eslint-disable-next-line sonarjs/updated-loop-counter -- skip past the string token
|
|
178
179
|
index = skipString(json, index)
|
|
179
180
|
const stringLength = index - stringStart
|
|
180
181
|
|