dd-trace 2.28.0 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +2 -2
- package/README.md +53 -0
- package/ci/init.js +9 -1
- package/ext/exporters.d.ts +2 -1
- package/ext/exporters.js +2 -1
- package/index.d.ts +6 -2
- package/package.json +24 -19
- package/packages/datadog-esbuild/index.js +104 -0
- package/packages/datadog-instrumentations/src/cucumber.js +80 -3
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -27
- package/packages/datadog-instrumentations/src/helpers/hook.js +13 -3
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +6 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
- package/packages/datadog-instrumentations/src/jest.js +35 -3
- package/packages/datadog-instrumentations/src/mariadb.js +130 -11
- package/packages/datadog-instrumentations/src/mocha.js +30 -6
- package/packages/datadog-instrumentations/src/mongodb-core.js +8 -2
- package/packages/datadog-instrumentations/src/mongoose.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +32 -4
- package/packages/datadog-instrumentations/src/pg.js +16 -11
- package/packages/datadog-instrumentations/src/playwright.js +2 -2
- package/packages/datadog-plugin-amqp10/src/consumer.js +1 -1
- package/packages/datadog-plugin-amqp10/src/index.js +1 -1
- package/packages/datadog-plugin-amqp10/src/producer.js +3 -2
- package/packages/datadog-plugin-amqplib/src/client.js +3 -2
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
- package/packages/datadog-plugin-amqplib/src/index.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +7 -2
- package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -0
- package/packages/datadog-plugin-bunyan/src/index.js +1 -1
- package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -2
- package/packages/datadog-plugin-connect/src/index.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +33 -6
- package/packages/datadog-plugin-cypress/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/plugin.js +40 -33
- package/packages/datadog-plugin-dns/src/index.js +1 -1
- package/packages/datadog-plugin-dns/src/lookup.js +1 -1
- package/packages/datadog-plugin-dns/src/lookup_service.js +1 -1
- package/packages/datadog-plugin-dns/src/resolve.js +1 -1
- package/packages/datadog-plugin-dns/src/reverse.js +1 -1
- package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
- package/packages/datadog-plugin-express/src/index.js +1 -1
- package/packages/datadog-plugin-fastify/src/index.js +1 -1
- package/packages/datadog-plugin-find-my-way/src/index.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +5 -5
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +7 -6
- package/packages/datadog-plugin-graphql/src/execute.js +1 -1
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/parse.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-graphql/src/validate.js +1 -1
- package/packages/datadog-plugin-grpc/src/client.js +1 -1
- package/packages/datadog-plugin-grpc/src/index.js +1 -1
- package/packages/datadog-plugin-grpc/src/server.js +1 -1
- package/packages/datadog-plugin-hapi/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +2 -2
- package/packages/datadog-plugin-http/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +2 -2
- package/packages/datadog-plugin-http2/src/client.js +4 -3
- package/packages/datadog-plugin-http2/src/index.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +2 -2
- package/packages/datadog-plugin-ioredis/src/index.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +53 -19
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
- package/packages/datadog-plugin-koa/src/index.js +1 -1
- package/packages/datadog-plugin-mariadb/src/index.js +18 -1
- package/packages/datadog-plugin-memcached/src/index.js +3 -2
- package/packages/datadog-plugin-microgateway-core/src/index.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +13 -9
- package/packages/datadog-plugin-moleculer/src/client.js +1 -1
- package/packages/datadog-plugin-moleculer/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +1 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
- package/packages/datadog-plugin-mysql/src/index.js +3 -2
- package/packages/datadog-plugin-mysql2/src/index.js +1 -1
- package/packages/datadog-plugin-net/src/index.js +9 -75
- package/packages/datadog-plugin-net/src/ipc.js +1 -1
- package/packages/datadog-plugin-net/src/tcp.js +3 -2
- package/packages/datadog-plugin-next/src/index.js +3 -3
- package/packages/datadog-plugin-opensearch/src/index.js +1 -1
- package/packages/datadog-plugin-oracledb/src/index.js +3 -2
- package/packages/datadog-plugin-paperplane/src/index.js +1 -1
- package/packages/datadog-plugin-paperplane/src/logger.js +1 -1
- package/packages/datadog-plugin-paperplane/src/server.js +1 -1
- package/packages/datadog-plugin-pg/src/index.js +3 -2
- package/packages/datadog-plugin-pino/src/index.js +1 -1
- package/packages/datadog-plugin-playwright/src/index.js +5 -4
- package/packages/datadog-plugin-redis/src/index.js +3 -2
- package/packages/datadog-plugin-restify/src/index.js +1 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
- package/packages/datadog-plugin-rhea/src/index.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +3 -2
- package/packages/datadog-plugin-router/src/index.js +8 -8
- package/packages/datadog-plugin-sharedb/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/src/index.js +3 -2
- package/packages/datadog-plugin-web/src/index.js +1 -1
- package/packages/datadog-plugin-winston/src/index.js +1 -1
- package/packages/dd-trace/src/appsec/{templates/blocked.html → blocked_templates.js} +19 -1
- package/packages/dd-trace/src/appsec/blocking.js +9 -24
- package/packages/dd-trace/src/appsec/gateway/engine/runner.js +2 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +12 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +11 -5
- package/packages/dd-trace/src/appsec/iast/iast-log.js +111 -0
- package/packages/dd-trace/src/appsec/iast/index.js +8 -4
- package/packages/dd-trace/src/appsec/iast/path-line.js +3 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +11 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +11 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +2 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +5 -3
- package/packages/dd-trace/src/appsec/iast/telemetry/log_collector.js +96 -0
- package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +87 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +27 -2
- package/packages/dd-trace/src/appsec/index.js +4 -18
- package/packages/dd-trace/src/appsec/recommended.json +43 -14
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/index.js +2 -2
- package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +27 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -9
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -7
- package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/index.js +33 -0
- package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/writer.js +37 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +8 -2
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +8 -2
- package/packages/dd-trace/src/config.js +44 -22
- package/packages/dd-trace/src/constants.js +2 -1
- package/packages/dd-trace/src/datastreams/encoding.js +80 -0
- package/packages/dd-trace/src/dcitm.js +51 -0
- package/packages/dd-trace/src/exporter.js +7 -9
- package/packages/dd-trace/src/exporters/common/agents.js +42 -0
- package/packages/dd-trace/src/exporters/common/docker.js +4 -1
- package/packages/dd-trace/src/exporters/common/request.js +1 -4
- package/packages/dd-trace/src/lambda/handler.js +14 -6
- package/packages/dd-trace/src/opentracing/propagation/log.js +23 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +28 -2
- package/packages/dd-trace/src/opentracing/span.js +19 -3
- package/packages/dd-trace/src/opentracing/span_context.js +3 -1
- package/packages/dd-trace/src/opentracing/tracer.js +3 -1
- package/packages/dd-trace/src/plugin_manager.js +7 -7
- package/packages/dd-trace/src/plugins/ci_plugin.js +16 -16
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/outgoing.js +2 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +12 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +23 -27
- package/packages/dd-trace/src/plugins/util/test.js +26 -7
- package/packages/dd-trace/src/profiling/config.js +87 -20
- package/packages/dd-trace/src/profiling/constants.js +16 -0
- package/packages/dd-trace/src/profiling/exporter_cli.js +62 -0
- package/packages/dd-trace/src/profiling/exporters/agent.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +21 -8
- package/packages/dd-trace/src/profiling/profilers/space.js +21 -1
- package/packages/dd-trace/src/span_sampler.js +3 -2
- package/packages/dd-trace/src/telemetry/index.js +16 -2
- package/packages/dd-trace/src/util.js +10 -1
- package/scripts/install_plugin_modules.js +5 -1
- package/packages/dd-trace/src/appsec/templates/blocked.json +0 -8
- package/scripts/junit_report.js +0 -25
- package/scripts/tdd.js +0 -34
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const vulnerabilityReporter = require('./vulnerability-reporter')
|
|
2
2
|
const { enableAllAnalyzers, disableAllAnalyzers } = require('./analyzers')
|
|
3
3
|
const web = require('../../plugins/util/web')
|
|
4
4
|
const { storage } = require('../../../../datadog-core')
|
|
@@ -7,6 +7,7 @@ const dc = require('diagnostics_channel')
|
|
|
7
7
|
const iastContextFunctions = require('./iast-context')
|
|
8
8
|
const { enableTaintTracking, disableTaintTracking, createTransaction, removeTransaction } = require('./taint-tracking')
|
|
9
9
|
|
|
10
|
+
const telemetryLogs = require('./telemetry/logs')
|
|
10
11
|
const IAST_ENABLED_TAG_KEY = '_dd.iast.enabled'
|
|
11
12
|
|
|
12
13
|
// TODO Change to `apm:http:server:request:[start|close]` when the subscription
|
|
@@ -16,12 +17,13 @@ const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
|
|
|
16
17
|
|
|
17
18
|
function enable (config, _tracer) {
|
|
18
19
|
enableAllAnalyzers()
|
|
19
|
-
enableTaintTracking()
|
|
20
|
+
enableTaintTracking(config.iast)
|
|
20
21
|
requestStart.subscribe(onIncomingHttpRequestStart)
|
|
21
22
|
requestClose.subscribe(onIncomingHttpRequestEnd)
|
|
22
23
|
overheadController.configure(config.iast)
|
|
23
24
|
overheadController.startGlobalContext()
|
|
24
|
-
|
|
25
|
+
vulnerabilityReporter.start(config, _tracer)
|
|
26
|
+
telemetryLogs.start()
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
function disable () {
|
|
@@ -30,6 +32,8 @@ function disable () {
|
|
|
30
32
|
overheadController.finishGlobalContext()
|
|
31
33
|
if (requestStart.hasSubscribers) requestStart.unsubscribe(onIncomingHttpRequestStart)
|
|
32
34
|
if (requestClose.hasSubscribers) requestClose.unsubscribe(onIncomingHttpRequestEnd)
|
|
35
|
+
vulnerabilityReporter.stop()
|
|
36
|
+
telemetryLogs.stop()
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
function onIncomingHttpRequestStart (data) {
|
|
@@ -63,7 +67,7 @@ function onIncomingHttpRequestEnd (data) {
|
|
|
63
67
|
if (iastContext && iastContext.rootSpan) {
|
|
64
68
|
const vulnerabilities = iastContext.vulnerabilities
|
|
65
69
|
const rootSpan = iastContext.rootSpan
|
|
66
|
-
sendVulnerabilities(vulnerabilities, rootSpan)
|
|
70
|
+
vulnerabilityReporter.sendVulnerabilities(vulnerabilities, rootSpan)
|
|
67
71
|
removeTransaction(iastContext)
|
|
68
72
|
}
|
|
69
73
|
// TODO web.getContext(data.req) is required when the request is aborted
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
1
3
|
const path = require('path')
|
|
2
4
|
const process = require('process')
|
|
5
|
+
const { calculateDDBasePath } = require('../../util')
|
|
3
6
|
const pathLine = {
|
|
4
7
|
getFirstNonDDPathAndLine,
|
|
5
8
|
getFirstNonDDPathAndLineFromCallsites, // Exported only for test purposes
|
|
@@ -19,12 +22,6 @@ const EXCLUDED_PATH_PREFIXES = [
|
|
|
19
22
|
'async_hooks'
|
|
20
23
|
]
|
|
21
24
|
|
|
22
|
-
function calculateDDBasePath (dirname) {
|
|
23
|
-
const dirSteps = dirname.split(path.sep)
|
|
24
|
-
const packagesIndex = dirSteps.lastIndexOf('packages')
|
|
25
|
-
return dirSteps.slice(0, packagesIndex).join(path.sep) + path.sep
|
|
26
|
-
}
|
|
27
|
-
|
|
28
25
|
function getCallSiteInfo () {
|
|
29
26
|
const previousPrepareStackTrace = Error.prepareStackTrace
|
|
30
27
|
const previousStackTraceLimit = Error.stackTraceLimit
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
1
3
|
const { enableRewriter, disableRewriter } = require('./rewriter')
|
|
2
|
-
const { createTransaction,
|
|
4
|
+
const { createTransaction,
|
|
5
|
+
removeTransaction,
|
|
6
|
+
setMaxTransactions,
|
|
7
|
+
enableTaintOperations,
|
|
8
|
+
disableTaintOperations } = require('./operations')
|
|
9
|
+
|
|
3
10
|
const taintTrackingPlugin = require('./plugin')
|
|
4
11
|
|
|
5
12
|
module.exports = {
|
|
6
|
-
enableTaintTracking () {
|
|
13
|
+
enableTaintTracking (config) {
|
|
7
14
|
enableRewriter()
|
|
8
15
|
enableTaintOperations()
|
|
9
16
|
taintTrackingPlugin.enable()
|
|
17
|
+
setMaxTransactions(config.maxConcurrentRequests)
|
|
10
18
|
},
|
|
11
19
|
disableTaintTracking () {
|
|
12
20
|
disableRewriter()
|
|
13
21
|
disableTaintOperations()
|
|
14
22
|
taintTrackingPlugin.disable()
|
|
15
23
|
},
|
|
24
|
+
setMaxTransactions: setMaxTransactions,
|
|
16
25
|
createTransaction: createTransaction,
|
|
17
26
|
removeTransaction: removeTransaction
|
|
18
27
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
1
3
|
const TaintedUtils = require('@datadog/native-iast-taint-tracking')
|
|
2
4
|
const { IAST_TRANSACTION_ID } = require('../iast-context')
|
|
3
5
|
const { TaintTracking, TaintTrackingDummy } = require('./taint-tracking-impl')
|
|
@@ -85,6 +87,14 @@ function disableTaintOperations () {
|
|
|
85
87
|
global._ddiast = TaintTrackingDummy
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
function setMaxTransactions (transactions) {
|
|
91
|
+
if (!transactions) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
TaintedUtils.setMaxTransactions(transactions)
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
module.exports = {
|
|
89
99
|
createTransaction,
|
|
90
100
|
removeTransaction,
|
|
@@ -94,5 +104,6 @@ module.exports = {
|
|
|
94
104
|
getRanges,
|
|
95
105
|
enableTaintOperations,
|
|
96
106
|
disableTaintOperations,
|
|
107
|
+
setMaxTransactions,
|
|
97
108
|
IAST_TRANSACTION_ID
|
|
98
109
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const Module = require('module')
|
|
4
4
|
const shimmer = require('../../../../../datadog-shimmer')
|
|
5
|
-
const
|
|
5
|
+
const iastLog = require('../iast-log')
|
|
6
6
|
const { isPrivateModule, isNotLibraryFile } = require('./filter')
|
|
7
7
|
const { csiMethods } = require('./csi-methods')
|
|
8
8
|
|
|
@@ -16,7 +16,8 @@ function getRewriter () {
|
|
|
16
16
|
getPrepareStackTrace = iastRewriter.getPrepareStackTrace
|
|
17
17
|
rewriter = new Rewriter({ csiMethods })
|
|
18
18
|
} catch (e) {
|
|
19
|
-
|
|
19
|
+
iastLog.error('Unable to initialize TaintTracking Rewriter')
|
|
20
|
+
.errorAndPublish(e)
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
return rewriter
|
|
@@ -46,7 +47,8 @@ function getCompileMethodFn (compileMethod) {
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
} catch (e) {
|
|
49
|
-
|
|
50
|
+
iastLog.error(`Error rewriting ${filename}`)
|
|
51
|
+
.errorAndPublish(e)
|
|
50
52
|
}
|
|
51
53
|
return compileMethod.apply(this, [content, filename])
|
|
52
54
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const TaintedUtils = require('@datadog/native-iast-taint-tracking')
|
|
4
4
|
const { storage } = require('../../../../../datadog-core')
|
|
5
5
|
const iastContextFunctions = require('../iast-context')
|
|
6
|
-
const
|
|
6
|
+
const iastLog = require('../iast-log')
|
|
7
7
|
|
|
8
8
|
function noop (res) { return res }
|
|
9
9
|
const TaintTrackingDummy = {
|
|
@@ -32,7 +32,8 @@ function getFilteredCsiFn (cb, filter) {
|
|
|
32
32
|
return cb(transactionId, res, target, ...rest)
|
|
33
33
|
}
|
|
34
34
|
} catch (e) {
|
|
35
|
-
|
|
35
|
+
iastLog.error(`Error invoking CSI ${target}`)
|
|
36
|
+
.errorAndPublish(e)
|
|
36
37
|
}
|
|
37
38
|
return res
|
|
38
39
|
}
|
|
@@ -80,7 +81,8 @@ const csiMethodsOverrides = {
|
|
|
80
81
|
return TaintedUtils.concat(transactionId, res, op1, op2)
|
|
81
82
|
}
|
|
82
83
|
} catch (e) {
|
|
83
|
-
|
|
84
|
+
iastLog.error(`Error invoking CSI plusOperator`)
|
|
85
|
+
.errorAndPublish(e)
|
|
84
86
|
}
|
|
85
87
|
return res
|
|
86
88
|
},
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../../log')
|
|
4
|
+
|
|
5
|
+
const logs = new Map()
|
|
6
|
+
|
|
7
|
+
// NOTE: Is this a reasonable number?
|
|
8
|
+
let maxEntries = 10000
|
|
9
|
+
let overflowedCount = 0
|
|
10
|
+
|
|
11
|
+
function hashCode (hashSource) {
|
|
12
|
+
let hash = 0
|
|
13
|
+
const size = hashSource.length
|
|
14
|
+
for (let offset = 0; offset < size; offset++) {
|
|
15
|
+
hash = (((hash * 31) | 0) + hashSource.charCodeAt(offset)) | 0
|
|
16
|
+
}
|
|
17
|
+
return hash
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createHash (logEntry) {
|
|
21
|
+
if (!logEntry) return 0
|
|
22
|
+
|
|
23
|
+
const prime = 31
|
|
24
|
+
let result = ((!logEntry.level) ? 0 : hashCode(logEntry.level))
|
|
25
|
+
result = (((prime * result) | 0) + ((!logEntry.message) ? 0 : hashCode(logEntry.message))) | 0
|
|
26
|
+
|
|
27
|
+
// NOTE: tags are not used at the moment
|
|
28
|
+
// result = (((prime * result) | 0) + ((!logEntry.tags) ? 0 : hashCode(logEntry.tags))) | 0
|
|
29
|
+
result = (((prime * result) | 0) + ((!logEntry.stack_trace) ? 0 : hashCode(logEntry.stack_trace))) | 0
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function newLogEntry (message, level, tags) {
|
|
34
|
+
return {
|
|
35
|
+
message,
|
|
36
|
+
level,
|
|
37
|
+
tags
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isValid (logEntry) {
|
|
42
|
+
return logEntry && logEntry.level && logEntry.message
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const logCollector = {
|
|
46
|
+
add (logEntry) {
|
|
47
|
+
try {
|
|
48
|
+
if (!isValid(logEntry)) {
|
|
49
|
+
log.info('IAST log collector discarding invalid log')
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// NOTE: should errors have higher priority? and discard log entries with lower priority?
|
|
54
|
+
if (logs.size >= maxEntries) {
|
|
55
|
+
overflowedCount++
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const hash = createHash(logEntry)
|
|
60
|
+
if (!logs.has(hash)) {
|
|
61
|
+
logs.set(hash, logEntry)
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
log.error(`Unable to add log to logCollector: ${e.message}`)
|
|
66
|
+
}
|
|
67
|
+
return false
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
drain () {
|
|
71
|
+
if (logs.size === 0) return
|
|
72
|
+
|
|
73
|
+
const drained = []
|
|
74
|
+
drained.push(...logs.values())
|
|
75
|
+
|
|
76
|
+
if (overflowedCount > 0) {
|
|
77
|
+
drained.push(newLogEntry(`Omitted ${overflowedCount} entries due to overflowing`, 'ERROR'))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.reset()
|
|
81
|
+
|
|
82
|
+
return drained
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
reset (max) {
|
|
86
|
+
logs.clear()
|
|
87
|
+
overflowedCount = 0
|
|
88
|
+
if (max) {
|
|
89
|
+
maxEntries = max
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
logCollector.reset()
|
|
95
|
+
|
|
96
|
+
module.exports = logCollector
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const dc = require('diagnostics_channel')
|
|
4
|
+
const logCollector = require('./log_collector')
|
|
5
|
+
const { sendData } = require('../../../telemetry/send-data')
|
|
6
|
+
const log = require('../../../log')
|
|
7
|
+
|
|
8
|
+
const telemetryStartChannel = dc.channel('datadog:telemetry:start')
|
|
9
|
+
const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
|
|
10
|
+
|
|
11
|
+
let config, application, host, interval
|
|
12
|
+
|
|
13
|
+
function publish (log) {
|
|
14
|
+
if (log && isLevelEnabled(log.level)) {
|
|
15
|
+
logCollector.add(log)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function sendLogs () {
|
|
20
|
+
try {
|
|
21
|
+
const logs = logCollector.drain()
|
|
22
|
+
if (logs) {
|
|
23
|
+
sendData(config, application, host, 'logs', logs)
|
|
24
|
+
}
|
|
25
|
+
} catch (e) {
|
|
26
|
+
log.error(e)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isLevelEnabled (level) {
|
|
31
|
+
return isLogCollectionEnabled(config) && (level !== 'DEBUG' || config.telemetry.debug)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isLogCollectionEnabled (config) {
|
|
35
|
+
return config && config.telemetry && config.telemetry.logCollection
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function onTelemetryStart (msg) {
|
|
39
|
+
if (!msg || !isLogCollectionEnabled(msg.config)) {
|
|
40
|
+
log.info('IAST telemetry logs start received but log collection is not enabled or configuration is incorrect')
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
log.info('IAST telemetry logs starting')
|
|
45
|
+
|
|
46
|
+
config = msg.config
|
|
47
|
+
application = msg.application
|
|
48
|
+
host = msg.host
|
|
49
|
+
|
|
50
|
+
if (msg.heartbeatInterval) {
|
|
51
|
+
interval = setInterval(sendLogs, msg.heartbeatInterval)
|
|
52
|
+
interval.unref()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function onTelemetryStop () {
|
|
59
|
+
stop()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function start () {
|
|
63
|
+
telemetryStartChannel.subscribe(onTelemetryStart)
|
|
64
|
+
telemetryStopChannel.subscribe(onTelemetryStop)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function stop () {
|
|
68
|
+
if (!isLogCollectionEnabled(config)) return
|
|
69
|
+
|
|
70
|
+
log.info('IAST telemetry logs stopping')
|
|
71
|
+
|
|
72
|
+
config = null
|
|
73
|
+
application = null
|
|
74
|
+
host = null
|
|
75
|
+
|
|
76
|
+
if (telemetryStartChannel.hasSubscribers) {
|
|
77
|
+
telemetryStartChannel.unsubscribe(onTelemetryStart)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (telemetryStopChannel.hasSubscribers) {
|
|
81
|
+
telemetryStopChannel.unsubscribe(onTelemetryStop)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
clearInterval(interval)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = { start, stop, publish, isLevelEnabled }
|
|
@@ -4,8 +4,11 @@ const VULNERABILITIES_KEY = 'vulnerabilities'
|
|
|
4
4
|
const IAST_JSON_TAG_KEY = '_dd.iast.json'
|
|
5
5
|
const VULNERABILITY_HASHES_MAX_SIZE = 1000
|
|
6
6
|
const VULNERABILITY_HASHES = new LRU({ max: VULNERABILITY_HASHES_MAX_SIZE })
|
|
7
|
+
const RESET_VULNERABILITY_CACHE_INTERVAL = 60 * 60 * 1000 // 1 hour
|
|
7
8
|
|
|
8
9
|
let tracer
|
|
10
|
+
let resetVulnerabilityCacheTimer
|
|
11
|
+
let deduplicationEnabled = true
|
|
9
12
|
|
|
10
13
|
function createVulnerability (type, evidence, spanId, location) {
|
|
11
14
|
if (type && evidence) {
|
|
@@ -164,7 +167,20 @@ function clearCache () { // only for test purposes
|
|
|
164
167
|
VULNERABILITY_HASHES.clear()
|
|
165
168
|
}
|
|
166
169
|
|
|
170
|
+
function startClearCacheTimer () {
|
|
171
|
+
resetVulnerabilityCacheTimer = setInterval(clearCache, RESET_VULNERABILITY_CACHE_INTERVAL)
|
|
172
|
+
resetVulnerabilityCacheTimer.unref()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function stopClearCacheTimer () {
|
|
176
|
+
if (resetVulnerabilityCacheTimer) {
|
|
177
|
+
clearInterval(resetVulnerabilityCacheTimer)
|
|
178
|
+
resetVulnerabilityCacheTimer = null
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
167
182
|
function deduplicateVulnerabilities (vulnerabilities) {
|
|
183
|
+
if (!deduplicationEnabled) return vulnerabilities
|
|
168
184
|
const deduplicated = vulnerabilities.filter((vulnerability) => {
|
|
169
185
|
const key = `${vulnerability.type}${vulnerability.hash}`
|
|
170
186
|
if (!VULNERABILITY_HASHES.get(key)) {
|
|
@@ -176,14 +192,23 @@ function deduplicateVulnerabilities (vulnerabilities) {
|
|
|
176
192
|
return deduplicated
|
|
177
193
|
}
|
|
178
194
|
|
|
179
|
-
function
|
|
195
|
+
function start (config, _tracer) {
|
|
196
|
+
deduplicationEnabled = config.iast.deduplicationEnabled
|
|
197
|
+
if (deduplicationEnabled) {
|
|
198
|
+
startClearCacheTimer()
|
|
199
|
+
}
|
|
180
200
|
tracer = _tracer
|
|
181
201
|
}
|
|
182
202
|
|
|
203
|
+
function stop () {
|
|
204
|
+
stopClearCacheTimer()
|
|
205
|
+
}
|
|
206
|
+
|
|
183
207
|
module.exports = {
|
|
184
208
|
createVulnerability,
|
|
185
209
|
addVulnerability,
|
|
186
210
|
sendVulnerabilities,
|
|
187
211
|
clearCache,
|
|
188
|
-
|
|
212
|
+
start,
|
|
213
|
+
stop
|
|
189
214
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
5
3
|
const log = require('../log')
|
|
6
4
|
const RuleManager = require('./rule_manager')
|
|
7
5
|
const remoteConfig = require('./remote_config')
|
|
@@ -12,7 +10,7 @@ const Reporter = require('./reporter')
|
|
|
12
10
|
const web = require('../plugins/util/web')
|
|
13
11
|
const { extractIp } = require('../plugins/util/ip_extractor')
|
|
14
12
|
const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
|
|
15
|
-
const { block,
|
|
13
|
+
const { block, setTemplates } = require('./blocking')
|
|
16
14
|
|
|
17
15
|
let isEnabled = false
|
|
18
16
|
let config
|
|
@@ -21,21 +19,10 @@ function enable (_config) {
|
|
|
21
19
|
if (isEnabled) return
|
|
22
20
|
|
|
23
21
|
try {
|
|
24
|
-
|
|
25
|
-
const rules = fs.readFileSync(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
|
|
26
|
-
enableFromRules(_config, JSON.parse(rules))
|
|
27
|
-
} catch (err) {
|
|
28
|
-
abortEnable(err)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
22
|
+
setTemplates(_config)
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await loadTemplatesAsync(_config)
|
|
37
|
-
const rules = await fs.promises.readFile(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
|
|
38
|
-
enableFromRules(_config, JSON.parse(rules))
|
|
24
|
+
// TODO: inline this function
|
|
25
|
+
enableFromRules(_config, _config.appsec.rules)
|
|
39
26
|
} catch (err) {
|
|
40
27
|
abortEnable(err)
|
|
41
28
|
}
|
|
@@ -169,7 +156,6 @@ function disable () {
|
|
|
169
156
|
|
|
170
157
|
module.exports = {
|
|
171
158
|
enable,
|
|
172
|
-
enableAsync,
|
|
173
159
|
disable,
|
|
174
160
|
incomingHttpStartTranslator,
|
|
175
161
|
incomingHttpEndTranslator
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.2",
|
|
3
3
|
"metadata": {
|
|
4
|
-
"rules_version": "1.
|
|
4
|
+
"rules_version": "1.6.0"
|
|
5
5
|
},
|
|
6
6
|
"rules": [
|
|
7
7
|
{
|
|
@@ -2907,7 +2907,8 @@
|
|
|
2907
2907
|
}
|
|
2908
2908
|
],
|
|
2909
2909
|
"transformers": [
|
|
2910
|
-
"removeNulls"
|
|
2910
|
+
"removeNulls",
|
|
2911
|
+
"urlDecodeUni"
|
|
2911
2912
|
]
|
|
2912
2913
|
},
|
|
2913
2914
|
{
|
|
@@ -2957,7 +2958,8 @@
|
|
|
2957
2958
|
}
|
|
2958
2959
|
],
|
|
2959
2960
|
"transformers": [
|
|
2960
|
-
"removeNulls"
|
|
2961
|
+
"removeNulls",
|
|
2962
|
+
"urlDecodeUni"
|
|
2961
2963
|
]
|
|
2962
2964
|
},
|
|
2963
2965
|
{
|
|
@@ -3007,7 +3009,8 @@
|
|
|
3007
3009
|
}
|
|
3008
3010
|
],
|
|
3009
3011
|
"transformers": [
|
|
3010
|
-
"removeNulls"
|
|
3012
|
+
"removeNulls",
|
|
3013
|
+
"urlDecodeUni"
|
|
3011
3014
|
]
|
|
3012
3015
|
},
|
|
3013
3016
|
{
|
|
@@ -3054,7 +3057,8 @@
|
|
|
3054
3057
|
}
|
|
3055
3058
|
],
|
|
3056
3059
|
"transformers": [
|
|
3057
|
-
"removeNulls"
|
|
3060
|
+
"removeNulls",
|
|
3061
|
+
"urlDecodeUni"
|
|
3058
3062
|
]
|
|
3059
3063
|
},
|
|
3060
3064
|
{
|
|
@@ -3088,8 +3092,7 @@
|
|
|
3088
3092
|
".parentnode",
|
|
3089
3093
|
".innerhtml",
|
|
3090
3094
|
"window.location",
|
|
3091
|
-
"-moz-binding"
|
|
3092
|
-
"<![cdata["
|
|
3095
|
+
"-moz-binding"
|
|
3093
3096
|
]
|
|
3094
3097
|
},
|
|
3095
3098
|
"operator": "phrase_match"
|
|
@@ -3545,7 +3548,7 @@
|
|
|
3545
3548
|
"address": "grpc.server.request.message"
|
|
3546
3549
|
}
|
|
3547
3550
|
],
|
|
3548
|
-
"regex": "\\b(?i:eval|settimeout|setinterval|new\\s+Function|alert|prompt)\\s*\\([^\\)]",
|
|
3551
|
+
"regex": "\\b(?i:eval|settimeout|setinterval|new\\s+Function|alert|prompt)[\\s+]*\\([^\\)]",
|
|
3549
3552
|
"options": {
|
|
3550
3553
|
"case_sensitive": true,
|
|
3551
3554
|
"min_length": 5
|
|
@@ -5347,14 +5350,12 @@
|
|
|
5347
5350
|
"address": "grpc.server.request.message"
|
|
5348
5351
|
}
|
|
5349
5352
|
],
|
|
5350
|
-
"regex": "(http|https):\\/\\/(?:.*\\.)?(?:burpcollaborator\\.net|localtest\\.me|mail\\.ebc\\.apple\\.com|bugbounty\\.dod\\.network|.*\\.[nx]ip\\.io|oastify\\.com|oast\\.(?:pro|live|site|online|fun|me)|sslip\\.io|requestbin\\.com|requestbin\\.net|hookbin\\.com|webhook\\.site|canarytokens\\.com|interact\\.sh|ngrok\\.io|bugbounty\\.click|prbly\\.win|qualysperiscope\\.com)"
|
|
5353
|
+
"regex": "(http|https):\\/\\/(?:.*\\.)?(?:burpcollaborator\\.net|localtest\\.me|mail\\.ebc\\.apple\\.com|bugbounty\\.dod\\.network|.*\\.[nx]ip\\.io|oastify\\.com|oast\\.(?:pro|live|site|online|fun|me)|sslip\\.io|requestbin\\.com|requestbin\\.net|hookbin\\.com|webhook\\.site|canarytokens\\.com|interact\\.sh|ngrok\\.io|bugbounty\\.click|prbly\\.win|qualysperiscope\\.com|vii.one|act1on3.ru)"
|
|
5351
5354
|
},
|
|
5352
5355
|
"operator": "match_regex"
|
|
5353
5356
|
}
|
|
5354
5357
|
],
|
|
5355
|
-
"transformers": [
|
|
5356
|
-
"lowercase"
|
|
5357
|
-
]
|
|
5358
|
+
"transformers": []
|
|
5358
5359
|
},
|
|
5359
5360
|
{
|
|
5360
5361
|
"id": "sqr-000-015",
|
|
@@ -5429,7 +5430,9 @@
|
|
|
5429
5430
|
"operator": "match_regex"
|
|
5430
5431
|
}
|
|
5431
5432
|
],
|
|
5432
|
-
"transformers": [
|
|
5433
|
+
"transformers": [
|
|
5434
|
+
"unicode_normalize"
|
|
5435
|
+
]
|
|
5433
5436
|
},
|
|
5434
5437
|
{
|
|
5435
5438
|
"id": "ua0-600-0xx",
|
|
@@ -5905,7 +5908,7 @@
|
|
|
5905
5908
|
"tags": {
|
|
5906
5909
|
"type": "security_scanner",
|
|
5907
5910
|
"category": "attack_attempt",
|
|
5908
|
-
"confidence": "
|
|
5911
|
+
"confidence": "0"
|
|
5909
5912
|
},
|
|
5910
5913
|
"conditions": [
|
|
5911
5914
|
{
|
|
@@ -6616,6 +6619,32 @@
|
|
|
6616
6619
|
"block"
|
|
6617
6620
|
]
|
|
6618
6621
|
},
|
|
6622
|
+
{
|
|
6623
|
+
"id": "ua0-600-57x",
|
|
6624
|
+
"name": "AlertLogic",
|
|
6625
|
+
"tags": {
|
|
6626
|
+
"type": "security_scanner",
|
|
6627
|
+
"category": "attack_attempt",
|
|
6628
|
+
"confidence": "0"
|
|
6629
|
+
},
|
|
6630
|
+
"conditions": [
|
|
6631
|
+
{
|
|
6632
|
+
"parameters": {
|
|
6633
|
+
"inputs": [
|
|
6634
|
+
{
|
|
6635
|
+
"address": "server.request.headers.no_cookies",
|
|
6636
|
+
"key_path": [
|
|
6637
|
+
"user-agent"
|
|
6638
|
+
]
|
|
6639
|
+
}
|
|
6640
|
+
],
|
|
6641
|
+
"regex": "\\bAlertLogic-MDR-"
|
|
6642
|
+
},
|
|
6643
|
+
"operator": "match_regex"
|
|
6644
|
+
}
|
|
6645
|
+
],
|
|
6646
|
+
"transformers": []
|
|
6647
|
+
},
|
|
6619
6648
|
{
|
|
6620
6649
|
"id": "ua0-600-5xx",
|
|
6621
6650
|
"name": "Blind SQL Injection Brute Forcer",
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
const { trackUserLoginSuccessEvent, trackUserLoginFailureEvent, trackCustomEvent } = require('./track_event')
|
|
4
4
|
const { checkUserAndSetUser, blockRequest } = require('./user_blocking')
|
|
5
|
-
const {
|
|
5
|
+
const { setTemplates } = require('../blocking')
|
|
6
6
|
const { setUser } = require('./set_user')
|
|
7
7
|
|
|
8
8
|
class AppsecSdk {
|
|
9
9
|
constructor (tracer, config) {
|
|
10
10
|
this._tracer = tracer
|
|
11
11
|
if (config) {
|
|
12
|
-
|
|
12
|
+
setTemplates(config)
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
class JSONEncoder {
|
|
4
|
+
constructor () {
|
|
5
|
+
this.payloads = []
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
encode (payload) {
|
|
9
|
+
this.payloads.push(payload)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
count () {
|
|
13
|
+
return this.payloads.length
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
reset () {
|
|
17
|
+
this.payloads = []
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
makePayload () {
|
|
21
|
+
const data = JSON.stringify(this.payloads)
|
|
22
|
+
this.reset()
|
|
23
|
+
return data
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = { JSONEncoder }
|