dd-trace 6.20.1 → 6.22.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 +9 -14
- package/ci/init.js +1 -2
- package/ci/test-optimization-validation/ci-discovery.js +9 -4
- package/ci/test-optimization-validation/executable.js +1 -5
- package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
- package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
- package/ci/test-optimization-validation/generated-files.js +6 -4
- package/ci/test-optimization-validation/generated-test-contract.js +7 -3
- package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
- package/ci/test-optimization-validation/manifest-schema.js +6 -7
- package/ci/test-optimization-validation/report-writer.js +6 -2
- package/ci/test-optimization-validation/runner-command.js +2 -4
- package/ci/test-optimization-validation/runner-contract.js +1 -2
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
- package/ci/vitest-no-worker-init-setup.mjs +10 -7
- package/index.d.ts +116 -17
- package/initialize.mjs +1 -3
- package/openfeature/rules-based.d.ts +11 -0
- package/openfeature/rules-based.js +7 -0
- package/package.json +13 -11
- package/packages/datadog-core/src/storage.js +16 -0
- package/packages/datadog-esbuild/index.js +18 -12
- package/packages/datadog-instrumentations/src/aerospike.js +3 -3
- package/packages/datadog-instrumentations/src/ai.js +3 -3
- package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
- package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
- package/packages/datadog-instrumentations/src/cucumber.js +48 -33
- package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
- package/packages/datadog-instrumentations/src/electron.js +6 -6
- package/packages/datadog-instrumentations/src/fastify.js +13 -4
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
- package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +36 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +87 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +64 -11
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
- package/packages/datadog-instrumentations/src/ioredis.js +7 -5
- package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
- package/packages/datadog-instrumentations/src/jest.js +122 -11
- package/packages/datadog-instrumentations/src/knex.js +9 -5
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
- package/packages/datadog-instrumentations/src/mocha/utils.js +127 -38
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +61 -34
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
- package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
- package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
- package/packages/datadog-instrumentations/src/nova-sonic/session.js +483 -0
- package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
- package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
- package/packages/datadog-instrumentations/src/openai.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +5 -6
- package/packages/datadog-instrumentations/src/playwright.js +3 -0
- package/packages/datadog-instrumentations/src/redis.js +27 -13
- package/packages/datadog-instrumentations/src/router.js +30 -0
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -5
- package/packages/datadog-instrumentations/src/vitest-main.js +9 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +2 -2
- package/packages/datadog-instrumentations/src/webdriverio.js +118 -21
- package/packages/datadog-instrumentations/src/ws.js +1 -4
- package/packages/datadog-plugin-amqplib/src/client.js +1 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
- package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
- package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +18 -5
- package/packages/datadog-plugin-cypress/src/index.js +6 -6
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
- package/packages/datadog-plugin-cypress/src/support.js +1 -4
- package/packages/datadog-plugin-express/src/code_origin.js +1 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
- package/packages/datadog-plugin-graphql/src/execute.js +5 -5
- package/packages/datadog-plugin-grpc/src/util.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +223 -39
- package/packages/datadog-plugin-mocha/src/webdriverio-video.js +453 -0
- package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
- package/packages/datadog-plugin-next/src/index.js +1 -2
- package/packages/datadog-plugin-openai/src/tracing.js +5 -2
- package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
- package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
- package/packages/datadog-plugin-postgres/src/index.js +24 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
- package/packages/datadog-plugin-vitest/src/index.js +5 -2
- package/packages/datadog-shimmer/src/shimmer.js +5 -4
- package/packages/datadog-webpack/index.js +55 -43
- package/packages/datadog-webpack/src/loader.js +56 -8
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
- package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
- package/packages/dd-trace/src/aiguard/redaction.js +8 -2
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
- package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
- package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
- package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
- package/packages/dd-trace/src/appsec/lambda.js +1 -3
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
- package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
- package/packages/dd-trace/src/appsec/reporter.js +21 -1
- package/packages/dd-trace/src/appsec/stack_trace.js +1 -2
- package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
- package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
- package/packages/dd-trace/src/config/config-types.d.ts +2 -2
- package/packages/dd-trace/src/config/defaults.js +5 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +8 -0
- package/packages/dd-trace/src/config/helper.js +34 -3
- package/packages/dd-trace/src/config/index.js +10 -9
- package/packages/dd-trace/src/config/normalize-service.js +1 -1
- package/packages/dd-trace/src/config/parsers.js +2 -2
- package/packages/dd-trace/src/config/supported-configurations.json +35 -0
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -3
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +17 -12
- package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/worker-error.js +21 -0
- package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
- package/packages/dd-trace/src/debugger/index.js +24 -2
- package/packages/dd-trace/src/debugger/probe_sampler.js +108 -11
- package/packages/dd-trace/src/dogstatsd.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +2 -5
- package/packages/dd-trace/src/exporters/common/url.js +1 -1
- package/packages/dd-trace/src/id.js +15 -5
- package/packages/dd-trace/src/lambda/handler.js +179 -19
- package/packages/dd-trace/src/lambda/index.js +15 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
- package/packages/dd-trace/src/llmobs/agent-manifest.js +296 -0
- package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +13 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +56 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
- package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
- package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +23 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +18 -8
- package/packages/dd-trace/src/llmobs/tagger.js +56 -3
- package/packages/dd-trace/src/llmobs/util.js +1 -2
- package/packages/dd-trace/src/llmobs/writers/base.js +7 -6
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -1
- package/packages/dd-trace/src/log/log.js +1 -5
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +30 -1
- package/packages/dd-trace/src/openfeature/configuration_source.js +17 -2
- package/packages/dd-trace/src/openfeature/debug-logging-hook.js +25 -0
- package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +59 -3
- package/packages/dd-trace/src/openfeature/remote_config.js +9 -0
- package/packages/dd-trace/src/openfeature/writers/util.js +43 -4
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +1 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +6 -23
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
- package/packages/dd-trace/src/otel-sampling.js +4 -5
- package/packages/dd-trace/src/otel-thread-ctx.js +81 -15
- package/packages/dd-trace/src/plugins/database.js +7 -16
- package/packages/dd-trace/src/plugins/util/git.js +9 -25
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
- package/packages/dd-trace/src/plugins/util/test.js +48 -4
- package/packages/dd-trace/src/priority_sampler.js +1 -2
- package/packages/dd-trace/src/profiling/profiler.js +4 -6
- package/packages/dd-trace/src/profiling/profilers/wall.js +4 -10
- package/packages/dd-trace/src/proxy.js +3 -2
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +10 -0
- package/packages/dd-trace/src/span_processor.js +13 -17
- package/packages/dd-trace/src/storage-channels.js +112 -46
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
- package/packages/dd-trace/src/util.js +29 -0
- package/packages/dd-trace/src/web-tags-cache.js +6 -2
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
|
@@ -314,11 +314,11 @@ function assertMethod (target, name, method) {
|
|
|
314
314
|
let message = 'No target object provided'
|
|
315
315
|
|
|
316
316
|
if (target) {
|
|
317
|
-
if (typeof target
|
|
318
|
-
message = 'Invalid target'
|
|
319
|
-
} else {
|
|
317
|
+
if (typeof target === 'object' || typeof target === 'function') {
|
|
320
318
|
name = String(name)
|
|
321
319
|
message = method ? `Original method ${name} is not a function` : `No original method ${name}`
|
|
320
|
+
} else {
|
|
321
|
+
message = 'Invalid target'
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
@@ -335,7 +335,8 @@ function assertMethod (target, name, method) {
|
|
|
335
335
|
function assertNotClass (target) {
|
|
336
336
|
// Frozen functions also have a non-writable `prototype`; inspect their source only then.
|
|
337
337
|
if ('prototype' in target &&
|
|
338
|
-
|
|
338
|
+
// Bound generators inherit `prototype` without owning one, so the descriptor may still be missing.
|
|
339
|
+
Object.getOwnPropertyDescriptor(target, 'prototype')?.writable === false &&
|
|
339
340
|
(!Object.isFrozen(target) || Function.prototype.toString.call(target).startsWith('class'))) {
|
|
340
341
|
throw new TypeError('Target is a native class constructor and cannot be wrapped.')
|
|
341
342
|
}
|
|
@@ -6,11 +6,15 @@ const fs = require('node:fs')
|
|
|
6
6
|
const instrumentations = require('../datadog-instrumentations/src/helpers/instrumentations')
|
|
7
7
|
const extractPackageAndModulePath = require('../datadog-instrumentations/src/helpers/extract-package-and-module-path')
|
|
8
8
|
const hooks = require('../datadog-instrumentations/src/helpers/hooks')
|
|
9
|
+
const { getRewriteTarget } = require('../datadog-instrumentations/src/helpers/rewriter/targets')
|
|
9
10
|
const { isESMFile } = require('../datadog-esbuild/src/utils')
|
|
11
|
+
const { getValueFromEnvSources } = require('../dd-trace/src/config/helper')
|
|
10
12
|
const log = require('./src/log')
|
|
11
13
|
|
|
12
14
|
const PLUGIN_NAME = 'DatadogWebpackPlugin'
|
|
13
15
|
|
|
16
|
+
const DD_BUNDLER_INJECT_GIT_METADATA = getValueFromEnvSources('DD_BUNDLER_INJECT_GIT_METADATA') !== false
|
|
17
|
+
|
|
14
18
|
for (const hook of Object.values(hooks)) {
|
|
15
19
|
if (hook !== null && typeof hook === 'object') {
|
|
16
20
|
hook.fn()
|
|
@@ -80,50 +84,55 @@ class DatadogWebpackPlugin {
|
|
|
80
84
|
}
|
|
81
85
|
})
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
for (const
|
|
103
|
-
if (!
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
87
|
+
// Bake DD_GIT_* into assets unless DD_BUNDLER_INJECT_GIT_METADATA=false (stable artifact hashes).
|
|
88
|
+
if (DD_BUNDLER_INJECT_GIT_METADATA) {
|
|
89
|
+
const gitMetadata = getGitMetadata()
|
|
90
|
+
if (gitMetadata.repositoryURL || gitMetadata.commitSHA) {
|
|
91
|
+
const banner =
|
|
92
|
+
'if (typeof process === \'object\' && process !== null &&\n' +
|
|
93
|
+
' process.env !== null && typeof process.env === \'object\') {\n' +
|
|
94
|
+
(gitMetadata.repositoryURL
|
|
95
|
+
? ` process.env.DD_GIT_REPOSITORY_URL = ${JSON.stringify(gitMetadata.repositoryURL)};\n`
|
|
96
|
+
: '') +
|
|
97
|
+
(gitMetadata.commitSHA
|
|
98
|
+
? ` process.env.DD_GIT_COMMIT_SHA = ${JSON.stringify(gitMetadata.commitSHA)};\n`
|
|
99
|
+
: '') +
|
|
100
|
+
'}\n'
|
|
101
|
+
|
|
102
|
+
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
|
|
103
|
+
compilation.hooks.processAssets.tap(
|
|
104
|
+
{ name: PLUGIN_NAME, stage: -2000 },
|
|
105
|
+
() => {
|
|
106
|
+
for (const chunk of compilation.chunks) {
|
|
107
|
+
if (!chunk.canBeInitial()) continue
|
|
108
|
+
for (const filename of chunk.files) {
|
|
109
|
+
if (!filename.endsWith('.js') && !filename.endsWith('.mjs')) continue
|
|
110
|
+
compilation.updateAsset(filename, (old) => {
|
|
111
|
+
const content = banner + old.source()
|
|
112
|
+
return {
|
|
113
|
+
source () { return content },
|
|
114
|
+
size () { return Buffer.byteLength(content, 'utf8') },
|
|
115
|
+
map () { return old.map() },
|
|
116
|
+
sourceAndMap () { return { source: content, map: old.map() } },
|
|
117
|
+
updateHash (hash) { hash.update(content) },
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
}
|
|
114
121
|
}
|
|
115
122
|
}
|
|
116
|
-
|
|
117
|
-
)
|
|
118
|
-
})
|
|
123
|
+
)
|
|
124
|
+
})
|
|
119
125
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
log.debug(
|
|
127
|
+
'Automatically injected git metadata (DD_GIT_REPOSITORY_URL: %s, DD_GIT_COMMIT_SHA: %s)',
|
|
128
|
+
gitMetadata.repositoryURL || 'not available',
|
|
129
|
+
gitMetadata.commitSHA || 'not available'
|
|
130
|
+
)
|
|
131
|
+
} else {
|
|
132
|
+
log.warn('No git metadata available - skipping injection')
|
|
133
|
+
}
|
|
125
134
|
} else {
|
|
126
|
-
log.
|
|
135
|
+
log.debug('Skipping git metadata injection (DD_BUNDLER_INJECT_GIT_METADATA=false)')
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (nmf) => {
|
|
@@ -146,8 +155,9 @@ class DatadogWebpackPlugin {
|
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
const request = resolveData.request
|
|
158
|
+
const isModuleOfInterest = modulesOfInterest.has(request) || modulesOfInterest.has(`${pkg}/${modulePath}`)
|
|
149
159
|
|
|
150
|
-
if (!
|
|
160
|
+
if (!isModuleOfInterest && getRewriteTarget(normalizedResource) === undefined) {
|
|
151
161
|
return
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -177,10 +187,12 @@ class DatadogWebpackPlugin {
|
|
|
177
187
|
const version = packageJson.version
|
|
178
188
|
const pkgPath = request === pkg ? pkg : `${pkg}/${modulePath}`
|
|
179
189
|
|
|
190
|
+
// Webpack runs loaders right-to-left, so appending makes this loader see the package's original source
|
|
191
|
+
// before any user transpiler lowers the syntax Orchestrion function queries match on.
|
|
180
192
|
createData.loaders ||= []
|
|
181
|
-
createData.loaders.
|
|
193
|
+
createData.loaders.push({
|
|
182
194
|
loader: require.resolve('./src/loader'),
|
|
183
|
-
options: { pkg, version, path: pkgPath },
|
|
195
|
+
options: { pkg, version, path: pkgPath, rewriteOnly: !isModuleOfInterest },
|
|
184
196
|
})
|
|
185
197
|
|
|
186
198
|
log.debug('LOAD: %s@%s, pkg "%s"', pkg, version, pkgPath)
|
|
@@ -1,26 +1,74 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { filename } = require('../../datadog-instrumentations/src/helpers/instrumentation-utils')
|
|
4
|
+
const { createBundlerRewriter } = require('../../datadog-instrumentations/src/helpers/rewriter')
|
|
5
|
+
const { getRewriteTarget } = require('../../datadog-instrumentations/src/helpers/rewriter/targets')
|
|
6
|
+
|
|
3
7
|
const CHANNEL = 'dd-trace:bundler:load'
|
|
8
|
+
// Resolved from dd-trace so the injected require works even when dc-polyfill is not hoisted next to the target.
|
|
9
|
+
const DC_MODULE = require.resolve('dc-polyfill').replaceAll('\\', '/')
|
|
10
|
+
const DC_MODULE_LITERAL = JSON.stringify(DC_MODULE)
|
|
11
|
+
|
|
12
|
+
let rewrite
|
|
4
13
|
|
|
5
14
|
/**
|
|
6
|
-
* Webpack loader
|
|
7
|
-
*
|
|
15
|
+
* Webpack loader called for each module-of-interest identified by DatadogWebpackPlugin.
|
|
16
|
+
* Orchestrion rewrite targets are rewritten and, for pure Orchestrion integrations, get an activation publish
|
|
17
|
+
* appended. Modules with export hooks get a dc-polyfill channel publish of their CJS exports appended.
|
|
8
18
|
*
|
|
9
19
|
* @param {string} source
|
|
20
|
+
* @param {string|object} [inputSourceMap]
|
|
10
21
|
*/
|
|
11
|
-
module.exports = function loader (source) {
|
|
22
|
+
module.exports = function loader (source, inputSourceMap) {
|
|
12
23
|
this.cacheable(false)
|
|
13
|
-
const { pkg, version, path: pkgPath } = this.getOptions()
|
|
24
|
+
const { pkg, version, path: pkgPath, rewriteOnly } = this.getOptions()
|
|
25
|
+
const target = getRewriteTarget(this.resourcePath.replaceAll('\\', '/'))
|
|
26
|
+
|
|
27
|
+
let code = source
|
|
28
|
+
let map = inputSourceMap
|
|
29
|
+
|
|
30
|
+
if (target) {
|
|
31
|
+
rewrite ??= createBundlerRewriter(DC_MODULE)
|
|
32
|
+
const result = rewrite(source, this.resourcePath, 'commonjs', target, inputSourceMap)
|
|
33
|
+
code = result.code
|
|
34
|
+
map = result.map
|
|
35
|
+
|
|
36
|
+
if (code !== source && target.activate) {
|
|
37
|
+
const payload = JSON.stringify({
|
|
38
|
+
activate: true,
|
|
39
|
+
package: target.moduleName,
|
|
40
|
+
version,
|
|
41
|
+
path: filename(target.moduleName, target.filePath),
|
|
42
|
+
})
|
|
43
|
+
this.callback(
|
|
44
|
+
null,
|
|
45
|
+
`${code}\n;{\n` +
|
|
46
|
+
` const __dd_ch = require(${DC_MODULE_LITERAL}).channel('${CHANNEL}');\n` +
|
|
47
|
+
` if (__dd_ch.hasSubscribers) __dd_ch.publish(${payload});\n` +
|
|
48
|
+
'}\n',
|
|
49
|
+
map
|
|
50
|
+
)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Rewrite-only targets have no export hook, so publishing their exports would only report a missing hook.
|
|
56
|
+
if (rewriteOnly) {
|
|
57
|
+
this.callback(null, code, map)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
14
60
|
|
|
15
|
-
|
|
16
|
-
|
|
61
|
+
this.callback(
|
|
62
|
+
null,
|
|
63
|
+
code +
|
|
17
64
|
'\n;{\n' +
|
|
18
|
-
|
|
65
|
+
` const __dd_dc = require(${DC_MODULE_LITERAL});\n` +
|
|
19
66
|
` const __dd_ch = __dd_dc.channel('${CHANNEL}');\n` +
|
|
20
67
|
' const __dd_mod = module.exports;\n' +
|
|
21
68
|
` const __dd_payload = { module: __dd_mod, version: '${version}', package: '${pkg}', path: '${pkgPath}' };\n` +
|
|
22
69
|
' __dd_ch.publish(__dd_payload);\n' +
|
|
23
70
|
' module.exports = __dd_payload.module;\n' +
|
|
24
|
-
'}\n'
|
|
71
|
+
'}\n',
|
|
72
|
+
map
|
|
25
73
|
)
|
|
26
74
|
}
|
|
@@ -73,8 +73,7 @@ function onModelIntercept (ctx) {
|
|
|
73
73
|
null,
|
|
74
74
|
'AIGuard: unable to decode the model result: %s'
|
|
75
75
|
)
|
|
76
|
-
if (outputMessages === null) return result
|
|
77
|
-
if (!outputMessages.length) return result
|
|
76
|
+
if (outputMessages === null || !outputMessages.length) return result
|
|
78
77
|
|
|
79
78
|
return evaluate(ctx, aiguard, [outputMessages], opts).then(() => result)
|
|
80
79
|
}
|
|
@@ -112,8 +111,7 @@ function interceptStreamedResult (ctx, result, inputMessages) {
|
|
|
112
111
|
null,
|
|
113
112
|
'AIGuard: unable to decode the streamed model result: %s'
|
|
114
113
|
)
|
|
115
|
-
if (outputMessages === null) return replayed
|
|
116
|
-
if (!outputMessages.length) return replayed
|
|
114
|
+
if (outputMessages === null || !outputMessages.length) return replayed
|
|
117
115
|
|
|
118
116
|
return evaluate(ctx, aiguard, [outputMessages], opts).then(() => replayed)
|
|
119
117
|
})
|
|
@@ -10,8 +10,7 @@ const IMAGE_FALLBACK = '[image]'
|
|
|
10
10
|
* @returns {string|undefined|null}
|
|
11
11
|
*/
|
|
12
12
|
function stringifyIfNeeded (value) {
|
|
13
|
-
if (value == null) return value
|
|
14
|
-
if (typeof value === 'string') return value
|
|
13
|
+
if (value == null || typeof value === 'string') return value
|
|
15
14
|
|
|
16
15
|
try {
|
|
17
16
|
return JSON.stringify(value)
|
|
@@ -102,8 +102,14 @@ function resolveWritableString (root, path) {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
if (
|
|
106
|
-
|
|
105
|
+
if (
|
|
106
|
+
!node ||
|
|
107
|
+
typeof node !== 'object' ||
|
|
108
|
+
!Object.hasOwn(node, terminal.name) ||
|
|
109
|
+
typeof node[terminal.name] !== 'string'
|
|
110
|
+
) {
|
|
111
|
+
return
|
|
112
|
+
}
|
|
107
113
|
return { container: node, key: terminal.name }
|
|
108
114
|
}
|
|
109
115
|
|
|
@@ -383,8 +383,9 @@ function presenceBitmask (optionalGroups, present) {
|
|
|
383
383
|
* @returns {string|null}
|
|
384
384
|
*/
|
|
385
385
|
function normalizeRouteExpress (route, params, urlPath, parse, makeMatcher) {
|
|
386
|
-
if (typeof route !== 'string' || !route)
|
|
387
|
-
|
|
386
|
+
if (typeof route !== 'string' || !route || typeof parse !== 'function' || typeof makeMatcher !== 'function') {
|
|
387
|
+
return null
|
|
388
|
+
}
|
|
388
389
|
|
|
389
390
|
let entry = routeCache.get(route)
|
|
390
391
|
if (entry === undefined) {
|
|
@@ -58,9 +58,7 @@ function disable () {
|
|
|
58
58
|
* @returns {'sample' | 'missing_route' | 'skip'}
|
|
59
59
|
*/
|
|
60
60
|
function sampleRootSpanRequest (rootSpan, request, record = false) {
|
|
61
|
-
if (!enabled) return SamplingDecision.SKIP
|
|
62
|
-
|
|
63
|
-
if (!rootSpan) return SamplingDecision.SKIP
|
|
61
|
+
if (!enabled || !rootSpan) return SamplingDecision.SKIP
|
|
64
62
|
|
|
65
63
|
const { method, statusCode, route, blocked = false } = request ?? {}
|
|
66
64
|
|
|
@@ -102,9 +100,7 @@ function sampleRequest (req, res, record = false) {
|
|
|
102
100
|
if (!enabled) return SamplingDecision.SKIP
|
|
103
101
|
|
|
104
102
|
const rootSpan = web.root(req)
|
|
105
|
-
if (!rootSpan) return SamplingDecision.SKIP
|
|
106
|
-
|
|
107
|
-
if (isRejected(rootSpan)) return SamplingDecision.SKIP
|
|
103
|
+
if (!rootSpan || isRejected(rootSpan)) return SamplingDecision.SKIP
|
|
108
104
|
|
|
109
105
|
const statusCode = res.statusCode
|
|
110
106
|
const route = getRouteOrEndpoint(web.getContext(req), statusCode)
|
|
@@ -163,15 +163,7 @@ function isRedirectResponse (res) {
|
|
|
163
163
|
* @param {object} ctx http client instrumentation context (mutated).
|
|
164
164
|
*/
|
|
165
165
|
function planResponseBodyCollection (originatingReq, res, ctx) {
|
|
166
|
-
if (!config) {
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (isRedirectResponse(res)) {
|
|
171
|
-
return
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (!shouldSampleBody(originatingReq)) {
|
|
166
|
+
if (!config || isRedirectResponse(res) || !shouldSampleBody(originatingReq)) {
|
|
175
167
|
return
|
|
176
168
|
}
|
|
177
169
|
|
|
@@ -60,9 +60,7 @@ function onRequestCookieParser ({ req, res, abortController, cookies }) {
|
|
|
60
60
|
if (!cookies || typeof cookies !== 'object') return
|
|
61
61
|
|
|
62
62
|
const rootSpan = web.root(req)
|
|
63
|
-
if (!rootSpan) return
|
|
64
|
-
|
|
65
|
-
if (isEmpty(cookies)) return
|
|
63
|
+
if (!rootSpan || isEmpty(cookies)) return
|
|
66
64
|
analyzedCookies.add(cookies)
|
|
67
65
|
|
|
68
66
|
const results = waf.run({
|
|
@@ -189,9 +187,7 @@ function onRequestQueryParsed ({ req, res, query, abortController }) {
|
|
|
189
187
|
}
|
|
190
188
|
|
|
191
189
|
const rootSpan = web.root(req)
|
|
192
|
-
if (!rootSpan) return
|
|
193
|
-
|
|
194
|
-
if (isEmpty(query)) return
|
|
190
|
+
if (!rootSpan || isEmpty(query)) return
|
|
195
191
|
|
|
196
192
|
const results = waf.run({
|
|
197
193
|
persistent: {
|
|
@@ -204,9 +200,7 @@ function onRequestQueryParsed ({ req, res, query, abortController }) {
|
|
|
204
200
|
|
|
205
201
|
function onRequestProcessParams ({ req, res, abortController, params }) {
|
|
206
202
|
const rootSpan = web.root(req)
|
|
207
|
-
if (!rootSpan) return
|
|
208
|
-
|
|
209
|
-
if (!params || typeof params !== 'object' || isEmpty(params)) return
|
|
203
|
+
if (!rootSpan || !params || typeof params !== 'object' || isEmpty(params)) return
|
|
210
204
|
|
|
211
205
|
const results = waf.run({
|
|
212
206
|
persistent: {
|
|
@@ -11,8 +11,13 @@ const { storedResponseHeaders, copyHeadersOmitting } = require('./http-shared')
|
|
|
11
11
|
const responseAnalyzedSet = new WeakSet()
|
|
12
12
|
|
|
13
13
|
function onResponseBody ({ req, res, body }) {
|
|
14
|
-
if (
|
|
15
|
-
|
|
14
|
+
if (
|
|
15
|
+
!body ||
|
|
16
|
+
typeof body !== 'object' ||
|
|
17
|
+
apiSecurity.sampleRequest(req, res) !== apiSecurity.SamplingDecision.SAMPLE
|
|
18
|
+
) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
// we don't support blocking at this point, so no results needed
|
|
18
23
|
waf.run({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path')
|
|
4
4
|
|
|
5
|
+
const { APPSEC_FS_STORAGE } = require('../../rasp/fs-plugin')
|
|
5
6
|
const { getIastContext } = require('../iast-context')
|
|
6
7
|
const { storage } = require('../../../../../datadog-core')
|
|
7
8
|
const { PATH_TRAVERSAL } = require('../vulnerabilities')
|
|
@@ -29,10 +30,10 @@ class PathTraversalAnalyzer extends InjectionAnalyzer {
|
|
|
29
30
|
|
|
30
31
|
onConfigure () {
|
|
31
32
|
this.addSub('apm:fs:operation:start', (obj) => {
|
|
32
|
-
const
|
|
33
|
-
const outOfReqOrChild = !
|
|
33
|
+
const fs = storage(APPSEC_FS_STORAGE).getStore()
|
|
34
|
+
const outOfReqOrChild = !fs?.root
|
|
34
35
|
|
|
35
|
-
// we could filter out all the nested fs.operations based on
|
|
36
|
+
// we could filter out all the nested fs.operations based on fs.root
|
|
36
37
|
// but if we spect a store in the context to be present we are going to exclude
|
|
37
38
|
// all out_of_the_request fs.operations
|
|
38
39
|
// AppsecFsPlugin must be enabled
|
|
@@ -17,10 +17,7 @@ class SetCookiesHeaderInterceptor extends Plugin {
|
|
|
17
17
|
|
|
18
18
|
_handleCookies (name, value, res) {
|
|
19
19
|
if (name.toLowerCase() === 'set-cookie') {
|
|
20
|
-
|
|
21
|
-
if (typeof value === 'string') {
|
|
22
|
-
allCookies = [value]
|
|
23
|
-
}
|
|
20
|
+
const allCookies = typeof value === 'string' ? [value] : value
|
|
24
21
|
const alreadyCheckedCookies = this._getAlreadyCheckedCookiesInResponse(res)
|
|
25
22
|
|
|
26
23
|
let location
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
const TaintedUtils = require('@datadog/native-iast-taint-tracking')
|
|
4
4
|
const { IAST_TRANSACTION_ID } = require('../iast-context')
|
|
5
5
|
const log = require('../../../log')
|
|
6
|
+
const { typedArrayLength } = require('../../../util')
|
|
6
7
|
const { HTTP_REQUEST_PARAMETER } = require('./source-types')
|
|
7
8
|
|
|
8
|
-
const SEPARATOR = '\
|
|
9
|
+
const SEPARATOR = '\0' // Unit Separator (cannot be in URL keys)
|
|
10
|
+
const MAX_TRAVERSED_BINARY_VIEW_LENGTH = 1024
|
|
9
11
|
|
|
10
12
|
function taintObject (iastContext, object, type) {
|
|
11
13
|
let result = object
|
|
@@ -31,6 +33,10 @@ function taintObject (iastContext, object, type) {
|
|
|
31
33
|
} else if (typeof value === 'object' && !visited.has(value)) {
|
|
32
34
|
visited.add(value)
|
|
33
35
|
|
|
36
|
+
// Binary view elements are numbers, but named properties may hold strings. Their keys cannot be listed
|
|
37
|
+
// without also materializing one key per element, so only small views are walked.
|
|
38
|
+
if (ArrayBuffer.isView(value) && typedArrayLength(value) > MAX_TRAVERSED_BINARY_VIEW_LENGTH) continue
|
|
39
|
+
|
|
34
40
|
for (const key of Object.keys(value)) {
|
|
35
41
|
queue.push({ parent: value, property: property ? `${property}.${key}` : key, value: value[key], key })
|
|
36
42
|
}
|
|
@@ -264,9 +264,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
_taintDatabaseResult (result, dbOrigin, iastContext, name) {
|
|
267
|
-
if (!iastContext) return result
|
|
268
|
-
|
|
269
|
-
if (this._rowsToTaint === 0) return result
|
|
267
|
+
if (!iastContext || this._rowsToTaint === 0) return result
|
|
270
268
|
|
|
271
269
|
if (Array.isArray(result)) {
|
|
272
270
|
for (let i = 0; i < result.length && i < this._rowsToTaint; i++) {
|
|
@@ -31,9 +31,7 @@ export async function initialize (data) {
|
|
|
31
31
|
export async function load (url, context, nextLoad) {
|
|
32
32
|
const result = await nextLoad(url, context)
|
|
33
33
|
|
|
34
|
-
if (!port) return result
|
|
35
|
-
if (!result.source) return result
|
|
36
|
-
if (url.includes(ddTraceDir) || url.includes('iitm=true')) return result
|
|
34
|
+
if (!port || !result.source || url.includes(ddTraceDir) || url.includes('iitm=true')) return result
|
|
37
35
|
|
|
38
36
|
let passes
|
|
39
37
|
try {
|
|
@@ -24,12 +24,7 @@ function formatTags (tags, tagKey) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function getNamespace (scope, context) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (scope === Scope.REQUEST) {
|
|
30
|
-
namespace = getNamespaceFromContext(context) || globalNamespace
|
|
31
|
-
}
|
|
32
|
-
return namespace
|
|
27
|
+
return scope === Scope.REQUEST ? getNamespaceFromContext(context) || globalNamespace : globalNamespace
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
class IastMetric {
|
|
@@ -169,9 +169,7 @@ function parseResponseBody (rawBody, headers, isBase64Encoded) {
|
|
|
169
169
|
// A handler that answered with the payload itself needs no parsing, and no content type either.
|
|
170
170
|
if (typeof rawBody === 'object') return rawBody
|
|
171
171
|
|
|
172
|
-
if (typeof rawBody !== 'string') return
|
|
173
|
-
|
|
174
|
-
if (!isJsonContentType(headers?.['content-type'])) return
|
|
172
|
+
if (typeof rawBody !== 'string' || !isJsonContentType(headers?.['content-type'])) return
|
|
175
173
|
|
|
176
174
|
if (isOverSizeCap(rawBody, isBase64Encoded)) {
|
|
177
175
|
log.debug('[ASM] Lambda response body larger than %d bytes, skipping schema extraction',
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const dc = require('dc-polyfill')
|
|
4
|
+
|
|
4
5
|
const { storage } = require('../../../../datadog-core')
|
|
5
6
|
const log = require('../../log')
|
|
6
7
|
|
|
7
8
|
const RASP_MODULE = 'rasp'
|
|
8
9
|
const IAST_MODULE = 'iast'
|
|
10
|
+
const APPSEC_FS_STORAGE = 'appsec-fs'
|
|
9
11
|
|
|
10
12
|
const enabledFor = {
|
|
11
13
|
[RASP_MODULE]: false,
|
|
@@ -13,42 +15,53 @@ const enabledFor = {
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
let fsPlugin
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
const legacyStorage = storage('legacy')
|
|
19
|
+
const appsecFsStorage = storage(APPSEC_FS_STORAGE)
|
|
20
|
+
const fsOperationStart = dc.channel('apm:fs:operation:start')
|
|
21
|
+
const fsOperationFinish = dc.channel('apm:fs:operation:finish')
|
|
22
|
+
const responseRenderStart = dc.channel('tracing:datadog:express:response:render:start')
|
|
23
|
+
const responseRenderEnd = dc.channel('tracing:datadog:express:response:render:end')
|
|
24
|
+
|
|
25
|
+
function getStoreToStart (fsProps, store = appsecFsStorage.getStore()) {
|
|
26
|
+
// Only track operations inside a traced context, like a request. Callbacks of fs streams and watchers keep
|
|
27
|
+
// the state of the operation that created them, so state created outside of one would leak into every request
|
|
28
|
+
// of a server started from such a callback. The tracing fs plugin enters a noop store when no span is active.
|
|
29
|
+
const legacyStore = legacyStorage.getStore()
|
|
30
|
+
if (!legacyStore || legacyStore.noop) return
|
|
31
|
+
|
|
32
|
+
if (!store || !store.opExcluded) {
|
|
19
33
|
return {
|
|
20
34
|
...store,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...fsProps,
|
|
24
|
-
parentStore: store,
|
|
25
|
-
},
|
|
35
|
+
...fsProps,
|
|
36
|
+
parentStore: store,
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
39
|
|
|
29
40
|
return store
|
|
30
41
|
}
|
|
31
42
|
|
|
32
|
-
class AppsecFsPlugin
|
|
43
|
+
class AppsecFsPlugin {
|
|
33
44
|
enable () {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
// The tracing fs plugin binds the legacy store on these channels. AppSec
|
|
46
|
+
// keeps its fs-only state in a dedicated storage namespace to avoid
|
|
47
|
+
// clobbering tracing state while still tracking nested operations.
|
|
48
|
+
fsOperationStart.bindStore(appsecFsStorage, this._onFsOperationStart)
|
|
49
|
+
fsOperationFinish.bindStore(appsecFsStorage, this._onFsOperationFinishOrRenderEnd)
|
|
50
|
+
responseRenderStart.bindStore(appsecFsStorage, this._onResponseRenderStart)
|
|
51
|
+
responseRenderEnd.bindStore(appsecFsStorage, this._onFsOperationFinishOrRenderEnd)
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
disable () {
|
|
44
|
-
|
|
55
|
+
fsOperationStart.unbindStore(appsecFsStorage)
|
|
56
|
+
fsOperationFinish.unbindStore(appsecFsStorage)
|
|
57
|
+
responseRenderStart.unbindStore(appsecFsStorage)
|
|
58
|
+
responseRenderEnd.unbindStore(appsecFsStorage)
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
_onFsOperationStart () {
|
|
48
|
-
const store =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
62
|
+
const store = appsecFsStorage.getStore()
|
|
63
|
+
|
|
64
|
+
return getStoreToStart({ root: store?.root === undefined }, store)
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
_onResponseRenderStart () {
|
|
@@ -56,11 +69,7 @@ class AppsecFsPlugin extends Plugin {
|
|
|
56
69
|
}
|
|
57
70
|
|
|
58
71
|
_onFsOperationFinishOrRenderEnd () {
|
|
59
|
-
|
|
60
|
-
if (store?.fs) {
|
|
61
|
-
return store.fs.parentStore
|
|
62
|
-
}
|
|
63
|
-
return store
|
|
72
|
+
return appsecFsStorage.getStore()?.parentStore
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
|
|
@@ -97,6 +106,7 @@ module.exports = {
|
|
|
97
106
|
disable,
|
|
98
107
|
|
|
99
108
|
AppsecFsPlugin,
|
|
109
|
+
APPSEC_FS_STORAGE,
|
|
100
110
|
|
|
101
111
|
RASP_MODULE,
|
|
102
112
|
IAST_MODULE,
|
|
@@ -6,9 +6,14 @@ const { fsOperationStart, incomingHttpRequestStart, expressResponseRenderStart }
|
|
|
6
6
|
const { storage } = require('../../../../datadog-core')
|
|
7
7
|
const web = require('../../plugins/util/web')
|
|
8
8
|
const { FS_OPERATION_PATH } = require('../addresses')
|
|
9
|
-
const {
|
|
9
|
+
const { getActiveRequest } = require('../store')
|
|
10
10
|
const waf = require('../waf')
|
|
11
|
-
const {
|
|
11
|
+
const {
|
|
12
|
+
APPSEC_FS_STORAGE,
|
|
13
|
+
enable: enableFsPlugin,
|
|
14
|
+
disable: disableFsPlugin,
|
|
15
|
+
RASP_MODULE,
|
|
16
|
+
} = require('./fs-plugin')
|
|
12
17
|
const { RULE_TYPES, handleResult } = require('./utils')
|
|
13
18
|
|
|
14
19
|
let config
|
|
@@ -59,11 +64,10 @@ function analyzeLfiInResponseRender (ctx) {
|
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
function analyzeLfi (ctx) {
|
|
62
|
-
const
|
|
63
|
-
const fs = store?.fs
|
|
67
|
+
const fs = storage(APPSEC_FS_STORAGE).getStore()
|
|
64
68
|
if (!fs) return
|
|
65
69
|
|
|
66
|
-
const req =
|
|
70
|
+
const req = getActiveRequest()
|
|
67
71
|
if (!req) return
|
|
68
72
|
|
|
69
73
|
const res = web.getContext(req)?.res
|