dd-trace 6.7.0 → 6.9.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/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +14 -8
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/playwright.js +5 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +47 -37
- package/ci/test-optimization-validation/generated-test-contract.js +9 -7
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +301 -52
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/offline-output.js +6 -6
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +41 -21
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/safe-files.js +4 -4
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +60 -6
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/scenarios/test-management.js +2 -2
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +377 -84
- package/index.d.ts +175 -14
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +12 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-esbuild/src/utils.js +17 -2
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +85 -9
- package/packages/datadog-instrumentations/src/cucumber.js +131 -51
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +175 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +38 -7
- package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -3
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +986 -246
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +109 -51
- package/packages/datadog-instrumentations/src/mocha/utils.js +120 -32
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +44 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +441 -43
- package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/pg.js +180 -6
- package/packages/datadog-instrumentations/src/playwright.js +176 -81
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +567 -65
- package/packages/datadog-instrumentations/src/vitest-main.js +438 -54
- package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
- package/packages/datadog-instrumentations/src/webdriverio.js +1090 -0
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aerospike/src/index.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
- package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -11
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
- package/packages/datadog-plugin-graphql/src/execute.js +1 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +3 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +3 -21
- package/packages/datadog-plugin-jest/src/util.js +4 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +342 -6
- package/packages/datadog-plugin-next/src/index.js +57 -9
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-pg/src/index.js +65 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-prisma/src/index.js +5 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +179 -18
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/datadog-webpack/index.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +10 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +29 -15
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +25 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +2 -2
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/defaults.js +14 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +31 -5
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +13 -6
- package/packages/dd-trace/src/datastreams/encoding.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/url.js +3 -5
- package/packages/dd-trace/src/exporters/electron/index.js +4 -1
- package/packages/dd-trace/src/external-logger/src/index.js +1 -2
- package/packages/dd-trace/src/flare/index.js +2 -2
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/id.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
- package/packages/dd-trace/src/llmobs/experiments/index.js +66 -19
- package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
- package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
- package/packages/dd-trace/src/llmobs/experiments/util.js +220 -0
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +152 -78
- package/packages/dd-trace/src/llmobs/span_processor.js +9 -7
- package/packages/dd-trace/src/llmobs/tagger.js +1 -2
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span_context.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +124 -23
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +13 -6
- package/packages/dd-trace/src/plugins/util/git.js +7 -5
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +3 -3
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +356 -86
- package/packages/dd-trace/src/plugins/util/url.js +5 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +24 -2
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +10 -20
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/startup-log.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/packages/dd-trace/src/util.js +16 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -15,6 +15,10 @@ const skipMethodSize = skipMethods.size
|
|
|
15
15
|
|
|
16
16
|
const nonConfigurableModuleExports = new WeakMap()
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {NonNullable<ReturnType<typeof globalThis.Object.getOwnPropertyDescriptor>>} Descriptor
|
|
20
|
+
*/
|
|
21
|
+
|
|
18
22
|
// Reused descriptor scratch space for the `name` and `length` slots that
|
|
19
23
|
// `copyProperties` and `wrapCallback` rewrite per wrap. `Object.defineProperty`
|
|
20
24
|
// reads the descriptor's slots synchronously and does not retain the object,
|
|
@@ -46,7 +50,7 @@ function copyProperties (original, wrapped) {
|
|
|
46
50
|
if (ownKeys.length !== 2) {
|
|
47
51
|
for (const key of ownKeys) {
|
|
48
52
|
if (skipMethods.has(key)) continue
|
|
49
|
-
const descriptor = /** @type {
|
|
53
|
+
const descriptor = /** @type {Descriptor} */ (Object.getOwnPropertyDescriptor(original, key))
|
|
50
54
|
if (descriptor.writable && descriptor.enumerable && descriptor.configurable) {
|
|
51
55
|
wrapped[key] = original[key]
|
|
52
56
|
} else if (descriptor.writable || descriptor.configurable || !Object.hasOwn(wrapped, key)) {
|
|
@@ -65,7 +69,7 @@ function copyObjectProperties (original, wrapped, skipKey) {
|
|
|
65
69
|
const ownKeys = Reflect.ownKeys(original)
|
|
66
70
|
for (const key of ownKeys) {
|
|
67
71
|
if (key === skipKey) continue
|
|
68
|
-
const descriptor = /** @type {
|
|
72
|
+
const descriptor = /** @type {Descriptor} */ (Object.getOwnPropertyDescriptor(original, key))
|
|
69
73
|
if (descriptor.writable && descriptor.enumerable && descriptor.configurable) {
|
|
70
74
|
wrapped[key] = original[key]
|
|
71
75
|
} else if (descriptor.writable || descriptor.configurable || !Object.hasOwn(wrapped, key)) {
|
|
@@ -141,7 +141,7 @@ class DatadogWebpackPlugin {
|
|
|
141
141
|
// (#8980); absent peers stay opaque, so a build that does not opt into the feature does
|
|
142
142
|
// not follow their dependency chain (#8635).
|
|
143
143
|
if (matchesOptionalPeerFile(normalizedResource)) {
|
|
144
|
-
createData.loaders
|
|
144
|
+
createData.loaders ||= []
|
|
145
145
|
createData.loaders.push({ loader: require.resolve('./src/optional-peer-loader') })
|
|
146
146
|
log.debug('INLINE: optional-peer loader applied to %s', normalizedResource)
|
|
147
147
|
return
|
|
@@ -188,7 +188,7 @@ class DatadogWebpackPlugin {
|
|
|
188
188
|
const version = packageJson.version
|
|
189
189
|
const pkgPath = request === pkg ? pkg : `${pkg}/${modulePath}`
|
|
190
190
|
|
|
191
|
-
createData.loaders
|
|
191
|
+
createData.loaders ||= []
|
|
192
192
|
createData.loaders.unshift({
|
|
193
193
|
loader: require.resolve('./src/loader'),
|
|
194
194
|
options: { pkg, version, path: pkgPath },
|
|
@@ -121,6 +121,9 @@ class AIGuard extends NoopAIGuard {
|
|
|
121
121
|
*
|
|
122
122
|
* - Clones each message so callers cannot mutate the data set in the meta struct.
|
|
123
123
|
* - Truncates the list of messages and `content` fields emitting metrics accordingly.
|
|
124
|
+
*
|
|
125
|
+
* @param {import('../../../../index').aiguard.Message[]} messages
|
|
126
|
+
* @param {{ source: string, integration: string }} telemetryTags
|
|
124
127
|
*/
|
|
125
128
|
#buildMessagesForMetaStruct (messages, telemetryTags) {
|
|
126
129
|
const size = Math.min(messages.length, this.#maxMessagesLength)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { LRUCache } = require('
|
|
4
|
-
const log = require('
|
|
5
|
-
const web = require('
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const { LRUCache } = require('../../../../../vendor/dist/lru-cache')
|
|
4
|
+
const log = require('../../log')
|
|
5
|
+
const web = require('../../plugins/util/web')
|
|
6
|
+
const { updateBlockFailureMetric } = require('../telemetry')
|
|
7
|
+
const blockedTemplates = require('./templates')
|
|
8
8
|
|
|
9
9
|
// Bounded by the LRU as defense-in-depth: getSpecificKey already keys on the
|
|
10
10
|
// resolved route (or the path with the query string stripped) so cardinality
|
|
@@ -182,7 +182,26 @@ function getBlockingAction (actions) {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
|
-
*
|
|
185
|
+
* Turns a WAF result's actions into a blocking response, when one is requested.
|
|
186
|
+
* Single seam from WAF output to {@link block}, shared by every request/response/auth handler.
|
|
187
|
+
*
|
|
188
|
+
* @param {Record<string, unknown>|undefined} actions WAF result actions.
|
|
189
|
+
* @param {import('http').IncomingMessage} req
|
|
190
|
+
* @param {import('http').ServerResponse} res
|
|
191
|
+
* @param {object} rootSpan
|
|
192
|
+
* @param {AbortController} abortController
|
|
193
|
+
*/
|
|
194
|
+
function handleResults (actions, req, res, rootSpan, abortController) {
|
|
195
|
+
if (!actions || !req || !res || !rootSpan || !abortController) return
|
|
196
|
+
|
|
197
|
+
const blockingAction = getBlockingAction(actions)
|
|
198
|
+
if (blockingAction) {
|
|
199
|
+
block(req, res, rootSpan, abortController, blockingAction)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @param {import('../../config/config-base')} [config] - Tracer configuration
|
|
186
205
|
*/
|
|
187
206
|
function setTemplates (config) {
|
|
188
207
|
templates.html.body = config?.appsec?.blockedTemplateHtml
|
|
@@ -233,6 +252,7 @@ module.exports = {
|
|
|
233
252
|
specificBlockingTypes,
|
|
234
253
|
getBlockingData,
|
|
235
254
|
getBlockingAction,
|
|
255
|
+
handleResults,
|
|
236
256
|
setTemplates,
|
|
237
257
|
isBlocked,
|
|
238
258
|
setDefaultBlockingActionParameters,
|
|
@@ -307,7 +307,7 @@ function parseBody (body, contentType) {
|
|
|
307
307
|
const formBody = Buffer.isBuffer(body) ? body.toString('utf8') : String(body)
|
|
308
308
|
const params = new URLSearchParams(formBody)
|
|
309
309
|
const result = {}
|
|
310
|
-
for (const [key, value] of params
|
|
310
|
+
for (const [key, value] of params) {
|
|
311
311
|
if (key in result) {
|
|
312
312
|
const existing = result[key]
|
|
313
313
|
if (Array.isArray(existing)) {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../log')
|
|
4
|
+
const web = require('../../plugins/util/web')
|
|
5
|
+
const addresses = require('../addresses')
|
|
6
|
+
const { handleResults } = require('../blocking')
|
|
7
|
+
const { getActiveRequest } = require('../store')
|
|
8
|
+
const UserTracking = require('../user_tracking')
|
|
9
|
+
const waf = require('../waf')
|
|
10
|
+
|
|
11
|
+
function onPassportVerify ({ framework, login, user, success, abortController }) {
|
|
12
|
+
const req = getActiveRequest()
|
|
13
|
+
const rootSpan = req && web.root(req)
|
|
14
|
+
|
|
15
|
+
if (!rootSpan) {
|
|
16
|
+
log.warn('[ASM] No rootSpan found in onPassportVerify')
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const results = UserTracking.trackLogin(framework, login, user, success, rootSpan)
|
|
21
|
+
|
|
22
|
+
handleResults(results?.actions, req, web.getContext(req)?.res, rootSpan, abortController)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function onPassportDeserializeUser ({ user, abortController }) {
|
|
26
|
+
const req = getActiveRequest()
|
|
27
|
+
const rootSpan = req && web.root(req)
|
|
28
|
+
|
|
29
|
+
if (!rootSpan) {
|
|
30
|
+
log.warn('[ASM] No rootSpan found in onPassportDeserializeUser')
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const results = UserTracking.trackUser(user, rootSpan)
|
|
35
|
+
|
|
36
|
+
handleResults(results?.actions, req, web.getContext(req)?.res, rootSpan, abortController)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function onExpressSession ({ req, res, sessionId, abortController }) {
|
|
40
|
+
const rootSpan = web.root(req)
|
|
41
|
+
if (!rootSpan) {
|
|
42
|
+
log.warn('[ASM] No rootSpan found in onExpressSession')
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isSdkCalled = rootSpan.context().getTag('usr.session_id')
|
|
47
|
+
if (isSdkCalled) return
|
|
48
|
+
|
|
49
|
+
const results = waf.run({
|
|
50
|
+
persistent: {
|
|
51
|
+
[addresses.USER_SESSION_ID]: sessionId,
|
|
52
|
+
},
|
|
53
|
+
}, req)
|
|
54
|
+
|
|
55
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
onPassportVerify,
|
|
60
|
+
onPassportDeserializeUser,
|
|
61
|
+
onExpressSession,
|
|
62
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { HTTP_CLIENT_IP } = require('../../../../../ext/tags')
|
|
4
|
+
const web = require('../../plugins/util/web')
|
|
5
|
+
const { extractIp } = require('../../plugins/util/ip_extractor')
|
|
6
|
+
const { isEmpty } = require('../../util')
|
|
7
|
+
const addresses = require('../addresses')
|
|
8
|
+
const apiSecurity = require('../api_security')
|
|
9
|
+
const { handleResults } = require('../blocking')
|
|
10
|
+
const Reporter = require('../reporter')
|
|
11
|
+
const { getActiveRequest } = require('../store')
|
|
12
|
+
const waf = require('../waf')
|
|
13
|
+
const { storedResponseHeaders, copyHeadersOmitting } = require('./http-shared')
|
|
14
|
+
|
|
15
|
+
const analyzedBodies = new WeakSet()
|
|
16
|
+
const analyzedCookies = new WeakSet()
|
|
17
|
+
const storedBodies = new WeakMap()
|
|
18
|
+
|
|
19
|
+
let config
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {import('../../config/config-base')|undefined} _config
|
|
23
|
+
*/
|
|
24
|
+
function setConfig (_config) {
|
|
25
|
+
config = _config
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function onRequestBodyParsed ({ req, res, body, abortController }) {
|
|
29
|
+
if (body === undefined || body === null) return
|
|
30
|
+
|
|
31
|
+
if (!req) {
|
|
32
|
+
req = getActiveRequest()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const rootSpan = web.root(req)
|
|
36
|
+
if (!rootSpan) return
|
|
37
|
+
|
|
38
|
+
if (!req.body) {
|
|
39
|
+
// do not store body if it is in req.body
|
|
40
|
+
storedBodies.set(req, body)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (typeof body === 'object') {
|
|
44
|
+
if (isEmpty(body)) return
|
|
45
|
+
analyzedBodies.add(body)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const results = waf.run({
|
|
49
|
+
persistent: {
|
|
50
|
+
[addresses.HTTP_INCOMING_BODY]: body,
|
|
51
|
+
},
|
|
52
|
+
}, req)
|
|
53
|
+
|
|
54
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function onRequestCookieParser ({ req, res, abortController, cookies }) {
|
|
58
|
+
if (!cookies || typeof cookies !== 'object') return
|
|
59
|
+
|
|
60
|
+
const rootSpan = web.root(req)
|
|
61
|
+
if (!rootSpan) return
|
|
62
|
+
|
|
63
|
+
if (isEmpty(cookies)) return
|
|
64
|
+
analyzedCookies.add(cookies)
|
|
65
|
+
|
|
66
|
+
const results = waf.run({
|
|
67
|
+
persistent: {
|
|
68
|
+
[addresses.HTTP_INCOMING_COOKIES]: cookies,
|
|
69
|
+
},
|
|
70
|
+
}, req)
|
|
71
|
+
|
|
72
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
76
|
+
const rootSpan = web.root(req)
|
|
77
|
+
if (!rootSpan) return
|
|
78
|
+
|
|
79
|
+
const clientIp = extractIp(config, req)
|
|
80
|
+
|
|
81
|
+
rootSpan.addTags({
|
|
82
|
+
'_dd.appsec.enabled': 1,
|
|
83
|
+
'_dd.runtime_family': 'nodejs',
|
|
84
|
+
[HTTP_CLIENT_IP]: clientIp,
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
if (config.inferredProxyServicesEnabled) {
|
|
88
|
+
const context = web.getContext(req)
|
|
89
|
+
if (context?.inferredProxySpan) {
|
|
90
|
+
context.inferredProxySpan.setTag('_dd.appsec.enabled', 1)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const persistent = {
|
|
95
|
+
[addresses.HTTP_INCOMING_URL]: req.url,
|
|
96
|
+
[addresses.HTTP_INCOMING_HEADERS]: copyHeadersOmitting(req.headers, 'cookie'),
|
|
97
|
+
[addresses.HTTP_INCOMING_METHOD]: req.method,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (clientIp) {
|
|
101
|
+
persistent[addresses.HTTP_CLIENT_IP] = clientIp
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const results = waf.run({ persistent }, req)
|
|
105
|
+
|
|
106
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function incomingHttpEndTranslator ({ req, res }) {
|
|
110
|
+
const persistent = {}
|
|
111
|
+
|
|
112
|
+
// we need to keep this to support other body parsers
|
|
113
|
+
if (req.body !== undefined && req.body !== null) {
|
|
114
|
+
if (typeof req.body === 'object') {
|
|
115
|
+
if (!isEmpty(req.body) && !analyzedBodies.has(req.body)) {
|
|
116
|
+
persistent[addresses.HTTP_INCOMING_BODY] = req.body
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
persistent[addresses.HTTP_INCOMING_BODY] = req.body
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// we need to keep this to support other cookie parsers
|
|
124
|
+
if (
|
|
125
|
+
req.cookies !== null &&
|
|
126
|
+
typeof req.cookies === 'object' &&
|
|
127
|
+
!isEmpty(req.cookies) &&
|
|
128
|
+
!analyzedCookies.has(req.cookies)
|
|
129
|
+
) {
|
|
130
|
+
persistent[addresses.HTTP_INCOMING_COOKIES] = req.cookies
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// we need to keep this to support nextjs
|
|
134
|
+
const query = req.query
|
|
135
|
+
if (
|
|
136
|
+
query !== null &&
|
|
137
|
+
typeof query === 'object' &&
|
|
138
|
+
!isEmpty(query)
|
|
139
|
+
) {
|
|
140
|
+
persistent[addresses.HTTP_INCOMING_QUERY] = query
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// This hook runs before span finish, so ensure route/endpoint tags are available before API Security sampling runs.
|
|
144
|
+
web.setRouteOrEndpointTag(req)
|
|
145
|
+
|
|
146
|
+
const apiSecSamplingDecision = apiSecurity.sampleRequest(req, res, true)
|
|
147
|
+
if (apiSecSamplingDecision === apiSecurity.SamplingDecision.SAMPLE) {
|
|
148
|
+
persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let wafResult
|
|
152
|
+
if (!isEmpty(persistent)) {
|
|
153
|
+
wafResult = waf.run({ persistent }, req)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
apiSecurity.reportRequest(req, apiSecSamplingDecision, wafResult)
|
|
157
|
+
|
|
158
|
+
waf.disposeContext(req)
|
|
159
|
+
|
|
160
|
+
const storedHeaders = storedResponseHeaders.get(req) || {}
|
|
161
|
+
|
|
162
|
+
const body = req.body || storedBodies.get(req)
|
|
163
|
+
Reporter.finishRequest(req, res, storedHeaders, body)
|
|
164
|
+
|
|
165
|
+
if (storedHeaders) {
|
|
166
|
+
storedResponseHeaders.delete(req)
|
|
167
|
+
}
|
|
168
|
+
storedBodies.delete(req)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function onRequestQueryParsed ({ req, res, query, abortController }) {
|
|
172
|
+
if (!query || typeof query !== 'object') return
|
|
173
|
+
|
|
174
|
+
if (!req) {
|
|
175
|
+
req = getActiveRequest()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const rootSpan = web.root(req)
|
|
179
|
+
if (!rootSpan) return
|
|
180
|
+
|
|
181
|
+
if (isEmpty(query)) return
|
|
182
|
+
|
|
183
|
+
const results = waf.run({
|
|
184
|
+
persistent: {
|
|
185
|
+
[addresses.HTTP_INCOMING_QUERY]: query,
|
|
186
|
+
},
|
|
187
|
+
}, req)
|
|
188
|
+
|
|
189
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function onRequestProcessParams ({ req, res, abortController, params }) {
|
|
193
|
+
const rootSpan = web.root(req)
|
|
194
|
+
if (!rootSpan) return
|
|
195
|
+
|
|
196
|
+
if (!params || typeof params !== 'object' || isEmpty(params)) return
|
|
197
|
+
|
|
198
|
+
const results = waf.run({
|
|
199
|
+
persistent: {
|
|
200
|
+
[addresses.HTTP_INCOMING_PARAMS]: params,
|
|
201
|
+
},
|
|
202
|
+
}, req)
|
|
203
|
+
|
|
204
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = {
|
|
208
|
+
setConfig,
|
|
209
|
+
onRequestBodyParsed,
|
|
210
|
+
onRequestCookieParser,
|
|
211
|
+
incomingHttpStartTranslator,
|
|
212
|
+
incomingHttpEndTranslator,
|
|
213
|
+
onRequestQueryParsed,
|
|
214
|
+
onRequestProcessParams,
|
|
215
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const web = require('../../plugins/util/web')
|
|
4
|
+
const { isEmpty } = require('../../util')
|
|
5
|
+
const addresses = require('../addresses')
|
|
6
|
+
const apiSecurity = require('../api_security')
|
|
7
|
+
const { isBlocked, callBlockDelegation, handleResults } = require('../blocking')
|
|
8
|
+
const waf = require('../waf')
|
|
9
|
+
const { storedResponseHeaders, copyHeadersOmitting } = require('./http-shared')
|
|
10
|
+
|
|
11
|
+
const responseAnalyzedSet = new WeakSet()
|
|
12
|
+
|
|
13
|
+
function onResponseBody ({ req, res, body }) {
|
|
14
|
+
if (!body || typeof body !== 'object') return
|
|
15
|
+
if (apiSecurity.sampleRequest(req, res) !== apiSecurity.SamplingDecision.SAMPLE) return
|
|
16
|
+
|
|
17
|
+
// we don't support blocking at this point, so no results needed
|
|
18
|
+
waf.run({
|
|
19
|
+
persistent: {
|
|
20
|
+
[addresses.HTTP_INCOMING_RESPONSE_BODY]: body,
|
|
21
|
+
},
|
|
22
|
+
}, req)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function onResponseWriteHead ({ req, res, abortController, statusCode, responseHeaders }) {
|
|
26
|
+
// Normalize header names to lowercase so downstream consumers see the same shape
|
|
27
|
+
// regardless of how the caller wrote them.
|
|
28
|
+
const normalizedResponseHeaders = {}
|
|
29
|
+
for (const [key, value] of Object.entries(responseHeaders)) {
|
|
30
|
+
normalizedResponseHeaders[key.toLowerCase()] = value
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!isEmpty(normalizedResponseHeaders)) {
|
|
34
|
+
storedResponseHeaders.set(req, normalizedResponseHeaders)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// TODO: do not call waf if inside block()
|
|
38
|
+
// if (isBlocking()) {
|
|
39
|
+
// return
|
|
40
|
+
// }
|
|
41
|
+
|
|
42
|
+
// avoid "write after end" error
|
|
43
|
+
if (isBlocked(res) || callBlockDelegation(res)) {
|
|
44
|
+
abortController?.abort()
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// avoid double waf call
|
|
49
|
+
if (responseAnalyzedSet.has(res)) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const rootSpan = web.root(req)
|
|
54
|
+
if (!rootSpan) return
|
|
55
|
+
|
|
56
|
+
const results = waf.run({
|
|
57
|
+
persistent: {
|
|
58
|
+
[addresses.HTTP_INCOMING_RESPONSE_CODE]: String(statusCode),
|
|
59
|
+
[addresses.HTTP_INCOMING_RESPONSE_HEADERS]: copyHeadersOmitting(normalizedResponseHeaders, 'set-cookie'),
|
|
60
|
+
},
|
|
61
|
+
}, req)
|
|
62
|
+
|
|
63
|
+
responseAnalyzedSet.add(res)
|
|
64
|
+
|
|
65
|
+
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function onResponseOperation ({ res, abortController }) {
|
|
69
|
+
if (isBlocked(res)) {
|
|
70
|
+
abortController?.abort()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
onResponseBody,
|
|
76
|
+
onResponseWriteHead,
|
|
77
|
+
onResponseOperation,
|
|
78
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Response headers captured on `responseWriteHead` (http-response) and later read
|
|
4
|
+
// when the request finishes (http-request end translator). This is the only piece
|
|
5
|
+
// of per-request state shared across the two handler modules.
|
|
6
|
+
const storedResponseHeaders = new WeakMap()
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {Record<string, unknown>} src
|
|
10
|
+
* @param {string} omit
|
|
11
|
+
* @returns {Record<string, unknown>}
|
|
12
|
+
*/
|
|
13
|
+
function copyHeadersOmitting (src, omit) {
|
|
14
|
+
const filtered = {}
|
|
15
|
+
for (const key of Object.keys(src)) {
|
|
16
|
+
if (key !== omit) filtered[key] = src[key]
|
|
17
|
+
}
|
|
18
|
+
return filtered
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
storedResponseHeaders,
|
|
23
|
+
copyHeadersOmitting,
|
|
24
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const addresses = require('../addresses')
|
|
4
|
+
const waf = require('../waf')
|
|
5
|
+
|
|
6
|
+
function onStripeCheckoutSessionCreate (payload) {
|
|
7
|
+
if (payload?.mode !== 'payment') return
|
|
8
|
+
|
|
9
|
+
waf.run({
|
|
10
|
+
persistent: {
|
|
11
|
+
[addresses.PAYMENT_CREATION]: {
|
|
12
|
+
integration: 'stripe',
|
|
13
|
+
id: payload.id,
|
|
14
|
+
amount_total: payload.amount_total,
|
|
15
|
+
client_reference_id: payload.client_reference_id,
|
|
16
|
+
currency: payload.currency,
|
|
17
|
+
'discounts.coupon': payload.discounts?.[0]?.coupon,
|
|
18
|
+
'discounts.promotion_code': payload.discounts?.[0]?.promotion_code,
|
|
19
|
+
livemode: payload.livemode,
|
|
20
|
+
'total_details.amount_discount': payload.total_details?.amount_discount,
|
|
21
|
+
'total_details.amount_shipping': payload.total_details?.amount_shipping,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function onStripePaymentIntentCreate (payload) {
|
|
28
|
+
if (payload === null || typeof payload !== 'object') return
|
|
29
|
+
|
|
30
|
+
waf.run({
|
|
31
|
+
persistent: {
|
|
32
|
+
[addresses.PAYMENT_CREATION]: {
|
|
33
|
+
integration: 'stripe',
|
|
34
|
+
id: payload.id,
|
|
35
|
+
amount: payload.amount,
|
|
36
|
+
currency: payload.currency,
|
|
37
|
+
livemode: payload.livemode,
|
|
38
|
+
payment_method: payload.payment_method,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function onStripeConstructEvent (payload) {
|
|
45
|
+
const object = payload?.data?.object
|
|
46
|
+
if (object === null || typeof object !== 'object') return
|
|
47
|
+
|
|
48
|
+
let persistent
|
|
49
|
+
|
|
50
|
+
switch (payload.type) {
|
|
51
|
+
case 'payment_intent.succeeded':
|
|
52
|
+
persistent = {
|
|
53
|
+
[addresses.PAYMENT_SUCCESS]: {
|
|
54
|
+
integration: 'stripe',
|
|
55
|
+
id: object.id,
|
|
56
|
+
amount: object.amount,
|
|
57
|
+
currency: object.currency,
|
|
58
|
+
livemode: object.livemode,
|
|
59
|
+
payment_method: object.payment_method,
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
case 'payment_intent.payment_failed':
|
|
65
|
+
persistent = {
|
|
66
|
+
[addresses.PAYMENT_FAILURE]: {
|
|
67
|
+
integration: 'stripe',
|
|
68
|
+
id: object.id,
|
|
69
|
+
amount: object.amount,
|
|
70
|
+
currency: object.currency,
|
|
71
|
+
'last_payment_error.code': object.last_payment_error?.code,
|
|
72
|
+
'last_payment_error.decline_code': object.last_payment_error?.decline_code,
|
|
73
|
+
'last_payment_error.payment_method.id': object.last_payment_error?.payment_method?.id,
|
|
74
|
+
'last_payment_error.payment_method.type': object.last_payment_error?.payment_method?.type,
|
|
75
|
+
livemode: object.livemode,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
case 'payment_intent.canceled':
|
|
81
|
+
persistent = {
|
|
82
|
+
[addresses.PAYMENT_CANCELLATION]: {
|
|
83
|
+
integration: 'stripe',
|
|
84
|
+
id: object.id,
|
|
85
|
+
amount: object.amount,
|
|
86
|
+
cancellation_reason: object.cancellation_reason,
|
|
87
|
+
currency: object.currency,
|
|
88
|
+
livemode: object.livemode,
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
default:
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
waf.run({ persistent })
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
onStripeCheckoutSessionCreate,
|
|
102
|
+
onStripePaymentIntentCreate,
|
|
103
|
+
onStripeConstructEvent,
|
|
104
|
+
}
|
|
@@ -31,7 +31,7 @@ class HstsHeaderMissingAnalyzer extends MissingHeaderAnalyzer {
|
|
|
31
31
|
semicolonIndex === -1 ? headerValue.length : semicolonIndex
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
const timestamp = Number.parseInt(timestampString)
|
|
34
|
+
const timestamp = Number.parseInt(timestampString, 10)
|
|
35
35
|
// eslint-disable-next-line eqeqeq
|
|
36
36
|
return timestamp > 0 && timestamp == timestampString
|
|
37
37
|
}
|
|
@@ -74,7 +74,7 @@ class SqlInjectionAnalyzer extends StoredInjectionAnalyzer {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
analyze (value, store, dialect) {
|
|
77
|
-
store
|
|
77
|
+
store ||= storage('legacy').getStore()
|
|
78
78
|
if (!(store && store.sqlAnalyzed)) {
|
|
79
79
|
super.analyze(value, store, dialect)
|
|
80
80
|
}
|
|
@@ -215,9 +215,7 @@ function getTaintTrackingImpl (telemetryVerbosity, dummy = false) {
|
|
|
215
215
|
if (dummy) return TaintTrackingNoop
|
|
216
216
|
|
|
217
217
|
// with Verbosity.DEBUG every invocation of a TaintedUtils method increases the EXECUTED_PROPAGATION metric
|
|
218
|
-
return isDebugAllowed(telemetryVerbosity)
|
|
219
|
-
? createImplWith(getContextDebug)
|
|
220
|
-
: createImplWith(getContextDefault)
|
|
218
|
+
return createImplWith(isDebugAllowed(telemetryVerbosity) ? getContextDebug : getContextDefault)
|
|
221
219
|
}
|
|
222
220
|
|
|
223
221
|
function getTaintTrackingNoop () {
|
|
@@ -35,7 +35,7 @@ function stringifyWithRanges (obj, objRanges, loadSensitiveRanges = false) {
|
|
|
35
35
|
let value
|
|
36
36
|
const ranges = []
|
|
37
37
|
const sensitiveRanges = []
|
|
38
|
-
objRanges
|
|
38
|
+
objRanges ||= {}
|
|
39
39
|
|
|
40
40
|
if (objRanges || loadSensitiveRanges) {
|
|
41
41
|
const cloneObj = Array.isArray(obj) ? [] : {}
|
|
@@ -150,7 +150,7 @@ function stringifyWithRanges (obj, objRanges, loadSensitiveRanges = false) {
|
|
|
150
150
|
|
|
151
151
|
sensitiveRanges.push({
|
|
152
152
|
start,
|
|
153
|
-
end: start + Number.parseInt(regexRes[1]),
|
|
153
|
+
end: start + Number.parseInt(regexRes[1], 10),
|
|
154
154
|
})
|
|
155
155
|
segments.push(value.slice(pos, rangeKeyIndex))
|
|
156
156
|
outputLength += cleanLength
|