dd-trace 2.39.0 → 2.41.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.
Files changed (62) hide show
  1. package/package.json +3 -3
  2. package/packages/datadog-instrumentations/src/cucumber.js +5 -2
  3. package/packages/datadog-instrumentations/src/grpc/client.js +44 -42
  4. package/packages/datadog-instrumentations/src/grpc/server.js +69 -60
  5. package/packages/datadog-instrumentations/src/http2/client.js +25 -26
  6. package/packages/datadog-instrumentations/src/jest.js +3 -1
  7. package/packages/datadog-instrumentations/src/kafkajs.js +11 -2
  8. package/packages/datadog-instrumentations/src/mocha.js +5 -3
  9. package/packages/datadog-instrumentations/src/redis.js +48 -5
  10. package/packages/datadog-plugin-cypress/src/plugin.js +4 -2
  11. package/packages/datadog-plugin-grpc/src/client.js +29 -11
  12. package/packages/datadog-plugin-grpc/src/server.js +22 -6
  13. package/packages/datadog-plugin-http2/src/client.js +46 -29
  14. package/packages/datadog-plugin-kafkajs/src/producer.js +6 -1
  15. package/packages/datadog-plugin-openai/src/services.js +14 -10
  16. package/packages/datadog-plugin-router/src/index.js +1 -1
  17. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +3 -0
  18. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +7 -1
  19. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +3 -0
  20. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +19 -15
  21. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +5 -2
  22. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +2 -0
  23. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +3 -1
  24. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +18 -19
  25. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +3 -0
  26. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -0
  27. package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
  28. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +205 -0
  29. package/packages/dd-trace/src/appsec/iast/index.js +6 -5
  30. package/packages/dd-trace/src/appsec/iast/tags.js +2 -1
  31. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +6 -6
  32. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
  33. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +23 -4
  34. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +32 -16
  35. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +33 -0
  36. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +23 -16
  37. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +76 -37
  38. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +101 -0
  39. package/packages/dd-trace/src/appsec/iast/telemetry/index.js +45 -0
  40. package/packages/dd-trace/src/appsec/iast/telemetry/{logs.js → log/index.js} +5 -5
  41. package/packages/dd-trace/src/appsec/iast/telemetry/{log_collector.js → log/log-collector.js} +1 -1
  42. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +76 -0
  43. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +53 -0
  44. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +42 -0
  45. package/packages/dd-trace/src/config.js +21 -2
  46. package/packages/dd-trace/src/constants.js +1 -0
  47. package/packages/dd-trace/src/dogstatsd.js +14 -1
  48. package/packages/dd-trace/src/metrics.js +2 -2
  49. package/packages/dd-trace/src/opentracing/tracer.js +1 -0
  50. package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
  51. package/packages/dd-trace/src/plugins/outbound.js +29 -12
  52. package/packages/dd-trace/src/plugins/plugin.js +28 -0
  53. package/packages/dd-trace/src/plugins/tracing.js +33 -16
  54. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  55. package/packages/dd-trace/src/plugins/util/test.js +55 -11
  56. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -22
  57. package/packages/dd-trace/src/profiling/config.js +0 -3
  58. package/packages/dd-trace/src/profiling/index.js +0 -2
  59. package/packages/dd-trace/src/profiling/profilers/wall.js +23 -11
  60. package/packages/diagnostics_channel/src/index.js +64 -0
  61. package/packages/dd-trace/src/profiling/profilers/cpu.js +0 -126
  62. /package/packages/dd-trace/src/appsec/iast/taint-tracking/{origin-types.js → source-types.js} +0 -0
@@ -0,0 +1,205 @@
1
+ 'use strict'
2
+
3
+ const { channel } = require('../../../../diagnostics_channel')
4
+
5
+ const iastLog = require('./iast-log')
6
+ const Plugin = require('../../plugins/plugin')
7
+ const iastTelemetry = require('./telemetry')
8
+ const { getInstrumentedMetric, getExecutedMetric, TagKey, EXECUTED_SOURCE } = require('./telemetry/iast-metric')
9
+ const { storage } = require('../../../../datadog-core')
10
+ const { getIastContext } = require('./iast-context')
11
+ const instrumentations = require('../../../../datadog-instrumentations/src/helpers/instrumentations')
12
+
13
+ /**
14
+ * Used by vulnerability sources and sinks to subscribe diagnostic channel events
15
+ * and indicate what kind of metrics the subscription provides
16
+ * - moduleName is used identify when a module is loaded and
17
+ * to increment the INSTRUMENTED_[SINK|SOURCE] metric when it occurs
18
+ * - channelName is the channel used by the hook to publish execution events
19
+ * - tag indicates the name of the metric: taint-tracking/source-types for Sources and analyzers type for Sinks
20
+ * - tagKey can be only SOURCE_TYPE (Source) or VULNERABILITY_TYPE (Sink)
21
+ */
22
+ class IastPluginSubscription {
23
+ constructor (moduleName, channelName, tag, tagKey = TagKey.VULNERABILITY_TYPE) {
24
+ this.moduleName = moduleName
25
+ this.channelName = channelName
26
+ this.tag = tag
27
+ this.tagKey = tagKey
28
+ this.executedMetric = getExecutedMetric(this.tagKey)
29
+ this.instrumentedMetric = getInstrumentedMetric(this.tagKey)
30
+ this.moduleInstrumented = false
31
+ }
32
+
33
+ increaseInstrumented () {
34
+ if (this.moduleInstrumented) return
35
+
36
+ this.moduleInstrumented = true
37
+ this.instrumentedMetric.inc(this.tag)
38
+ }
39
+
40
+ increaseExecuted (iastContext) {
41
+ this.executedMetric.inc(this.tag, iastContext)
42
+ }
43
+
44
+ matchesModuleInstrumented (name) {
45
+ // https module is a special case because it's events are published as http
46
+ name = name === 'https' ? 'http' : name
47
+ return this.moduleName === name
48
+ }
49
+ }
50
+
51
+ class IastPlugin extends Plugin {
52
+ constructor () {
53
+ super()
54
+ this.configured = false
55
+ this.pluginSubs = []
56
+ }
57
+
58
+ _wrapHandler (handler) {
59
+ return (message, name) => {
60
+ try {
61
+ handler(message, name)
62
+ } catch (e) {
63
+ iastLog.errorAndPublish(e)
64
+ }
65
+ }
66
+ }
67
+
68
+ _getTelemetryHandler (iastSub) {
69
+ return () => {
70
+ try {
71
+ const iastContext = getIastContext(storage.getStore())
72
+ iastSub.increaseExecuted(iastContext)
73
+ } catch (e) {
74
+ iastLog.errorAndPublish(e)
75
+ }
76
+ }
77
+ }
78
+
79
+ _execHandlerAndIncMetric ({ handler, metric, tag, iastContext = getIastContext(storage.getStore()) }) {
80
+ try {
81
+ const result = handler()
82
+ iastTelemetry.isEnabled() && metric.inc(tag, iastContext)
83
+ return result
84
+ } catch (e) {
85
+ iastLog.errorAndPublish(e)
86
+ }
87
+ }
88
+
89
+ addSub (iastSub, handler) {
90
+ if (typeof iastSub === 'string') {
91
+ super.addSub(iastSub, this._wrapHandler(handler))
92
+ } else {
93
+ iastSub = this._getAndRegisterSubscription(iastSub)
94
+ if (iastSub) {
95
+ super.addSub(iastSub.channelName, this._wrapHandler(handler))
96
+
97
+ if (iastTelemetry.isEnabled()) {
98
+ super.addSub(iastSub.channelName, this._getTelemetryHandler(iastSub))
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ onConfigure () {}
105
+
106
+ configure (config) {
107
+ if (typeof config !== 'object') {
108
+ config = { enabled: config }
109
+ }
110
+ if (config.enabled && !this.configured) {
111
+ this.onConfigure()
112
+ this.configured = true
113
+ }
114
+
115
+ if (iastTelemetry.isEnabled()) {
116
+ if (config.enabled) {
117
+ this.enableTelemetry()
118
+ } else {
119
+ this.disableTelemetry()
120
+ }
121
+ }
122
+
123
+ super.configure(config)
124
+ }
125
+
126
+ _getAndRegisterSubscription ({ moduleName, channelName, tag, tagKey }) {
127
+ if (!channelName && !moduleName) return
128
+
129
+ if (!moduleName) {
130
+ const firstSep = channelName.indexOf(':')
131
+ if (firstSep === -1) {
132
+ moduleName = channelName
133
+ } else {
134
+ const lastSep = channelName.indexOf(':', firstSep + 1)
135
+ moduleName = channelName.substring(firstSep + 1, lastSep !== -1 ? lastSep : channelName.length)
136
+ }
137
+ }
138
+
139
+ const iastSub = new IastPluginSubscription(moduleName, channelName, tag, tagKey)
140
+ this.pluginSubs.push(iastSub)
141
+ return iastSub
142
+ }
143
+
144
+ enableTelemetry () {
145
+ if (this.onInstrumentationLoadedListener) return
146
+
147
+ this.onInstrumentationLoadedListener = ({ name }) => this._onInstrumentationLoaded(name)
148
+ const loadChannel = channel('dd-trace:instrumentation:load')
149
+ loadChannel.subscribe(this.onInstrumentationLoadedListener)
150
+
151
+ // check for already instrumented modules
152
+ for (const name in instrumentations) {
153
+ this._onInstrumentationLoaded(name)
154
+ }
155
+ }
156
+
157
+ disableTelemetry () {
158
+ if (!this.onInstrumentationLoadedListener) return
159
+
160
+ const loadChannel = channel('dd-trace:instrumentation:load')
161
+ if (loadChannel.hasSubscribers) {
162
+ loadChannel.unsubscribe(this.onInstrumentationLoadedListener)
163
+ }
164
+ this.onInstrumentationLoadedListener = null
165
+ }
166
+
167
+ _onInstrumentationLoaded (name) {
168
+ this.pluginSubs
169
+ .filter(sub => sub.matchesModuleInstrumented(name))
170
+ .forEach(sub => sub.increaseInstrumented())
171
+ }
172
+ }
173
+
174
+ class SourceIastPlugin extends IastPlugin {
175
+ addSub (iastPluginSub, handler) {
176
+ return super.addSub({ tagKey: TagKey.SOURCE_TYPE, ...iastPluginSub }, handler)
177
+ }
178
+
179
+ addInstrumentedSource (moduleName, tag) {
180
+ this._getAndRegisterSubscription({
181
+ moduleName,
182
+ tag,
183
+ tagKey: TagKey.SOURCE_TYPE
184
+ })
185
+ }
186
+
187
+ execSource (sourceHandlerInfo) {
188
+ this._execHandlerAndIncMetric({
189
+ metric: EXECUTED_SOURCE,
190
+ ...sourceHandlerInfo
191
+ })
192
+ }
193
+ }
194
+
195
+ class SinkIastPlugin extends IastPlugin {
196
+ addSub (iastPluginSub, handler) {
197
+ return super.addSub({ tagKey: TagKey.VULNERABILITY_TYPE, ...iastPluginSub }, handler)
198
+ }
199
+ }
200
+
201
+ module.exports = {
202
+ SourceIastPlugin,
203
+ SinkIastPlugin,
204
+ IastPlugin
205
+ }
@@ -13,8 +13,7 @@ const {
13
13
  taintTrackingPlugin
14
14
  } = require('./taint-tracking')
15
15
  const { IAST_ENABLED_TAG_KEY } = require('./tags')
16
-
17
- const telemetryLogs = require('./telemetry/logs')
16
+ const iastTelemetry = require('./telemetry')
18
17
 
19
18
  // TODO Change to `apm:http:server:request:[start|close]` when the subscription
20
19
  // order of the callbacks can be enforce
@@ -22,24 +21,24 @@ const requestStart = dc.channel('dd-trace:incomingHttpRequestStart')
22
21
  const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
23
22
 
24
23
  function enable (config, _tracer) {
24
+ iastTelemetry.configure(config, config.iast && config.iast.telemetryVerbosity)
25
25
  enableAllAnalyzers()
26
- enableTaintTracking(config.iast)
26
+ enableTaintTracking(config.iast, iastTelemetry.verbosity)
27
27
  requestStart.subscribe(onIncomingHttpRequestStart)
28
28
  requestClose.subscribe(onIncomingHttpRequestEnd)
29
29
  overheadController.configure(config.iast)
30
30
  overheadController.startGlobalContext()
31
31
  vulnerabilityReporter.start(config, _tracer)
32
- telemetryLogs.start()
33
32
  }
34
33
 
35
34
  function disable () {
35
+ iastTelemetry.stop()
36
36
  disableAllAnalyzers()
37
37
  disableTaintTracking()
38
38
  overheadController.finishGlobalContext()
39
39
  if (requestStart.hasSubscribers) requestStart.unsubscribe(onIncomingHttpRequestStart)
40
40
  if (requestClose.hasSubscribers) requestClose.unsubscribe(onIncomingHttpRequestEnd)
41
41
  vulnerabilityReporter.stop()
42
- telemetryLogs.stop()
43
42
  }
44
43
 
45
44
  function onIncomingHttpRequestStart (data) {
@@ -54,6 +53,7 @@ function onIncomingHttpRequestStart (data) {
54
53
  const iastContext = iastContextFunctions.saveIastContext(store, topContext, { rootSpan, req: data.req })
55
54
  createTransaction(rootSpan.context().toSpanId(), iastContext)
56
55
  overheadController.initializeRequestContext(iastContext)
56
+ iastTelemetry.onRequestStart(iastContext)
57
57
  taintTrackingPlugin.taintHeaders(data.req.headers, iastContext)
58
58
  }
59
59
  if (rootSpan.addTags) {
@@ -76,6 +76,7 @@ function onIncomingHttpRequestEnd (data) {
76
76
  const rootSpan = iastContext.rootSpan
77
77
  vulnerabilityReporter.sendVulnerabilities(vulnerabilities, rootSpan)
78
78
  removeTransaction(iastContext)
79
+ iastTelemetry.onRequestEnd(iastContext, iastContext.rootSpan)
79
80
  }
80
81
  // TODO web.getContext(data.req) is required when the request is aborted
81
82
  if (iastContextFunctions.cleanIastContext(store, topContext, iastContext)) {
@@ -2,5 +2,6 @@
2
2
 
3
3
  module.exports = {
4
4
  IAST_ENABLED_TAG_KEY: '_dd.iast.enabled',
5
- IAST_JSON_TAG_KEY: '_dd.iast.json'
5
+ IAST_JSON_TAG_KEY: '_dd.iast.json',
6
+ IAST_TRACE_METRIC_PREFIX: '_dd.iast.telemetry'
6
7
  }
@@ -1,15 +1,15 @@
1
1
  'use strict'
2
2
 
3
3
  const csiMethods = [
4
+ { src: 'concat' },
4
5
  { src: 'plusOperator', operator: true },
6
+ { src: 'replace' },
7
+ { src: 'slice' },
8
+ { src: 'substr' },
9
+ { src: 'substring' },
5
10
  { src: 'trim' },
6
- { src: 'trimStart', dst: 'trim' },
7
11
  { src: 'trimEnd' },
8
- { src: 'concat' },
9
- { src: 'substring' },
10
- { src: 'substr' },
11
- { src: 'slice' },
12
- { src: 'replace' }
12
+ { src: 'trimStart', dst: 'trim' }
13
13
  ]
14
14
 
15
15
  module.exports = {
@@ -10,9 +10,9 @@ const { createTransaction,
10
10
  const taintTrackingPlugin = require('./plugin')
11
11
 
12
12
  module.exports = {
13
- enableTaintTracking (config) {
14
- enableRewriter()
15
- enableTaintOperations()
13
+ enableTaintTracking (config, telemetryVerbosity) {
14
+ enableRewriter(telemetryVerbosity)
15
+ enableTaintOperations(telemetryVerbosity)
16
16
  taintTrackingPlugin.enable()
17
17
  setMaxTransactions(config.maxConcurrentRequests)
18
18
  },
@@ -3,7 +3,10 @@
3
3
  const TaintedUtils = require('@datadog/native-iast-taint-tracking')
4
4
  const { IAST_TRANSACTION_ID } = require('../iast-context')
5
5
  const iastLog = require('../iast-log')
6
- const { TaintTracking, TaintTrackingDummy } = require('./taint-tracking-impl')
6
+ const iastTelemetry = require('../telemetry')
7
+ const { REQUEST_TAINTED } = require('../telemetry/iast-metric')
8
+ const { isInfoAllowed } = require('../telemetry/verbosity')
9
+ const { getTaintTrackingImpl, getTaintTrackingNoop } = require('./taint-tracking-impl')
7
10
 
8
11
  function createTransaction (id, iastContext) {
9
12
  if (id && iastContext) {
@@ -11,9 +14,21 @@ function createTransaction (id, iastContext) {
11
14
  }
12
15
  }
13
16
 
17
+ let onRemoveTransaction = (transactionId, iastContext) => {}
18
+
19
+ function onRemoveTransactionInformationTelemetry (transactionId, iastContext) {
20
+ const metrics = TaintedUtils.getMetrics(transactionId, iastTelemetry.verbosity)
21
+ if (metrics && metrics.requestCount) {
22
+ REQUEST_TAINTED.add(metrics.requestCount, null, iastContext)
23
+ }
24
+ }
25
+
14
26
  function removeTransaction (iastContext) {
15
27
  if (iastContext && iastContext[IAST_TRANSACTION_ID]) {
16
28
  const transactionId = iastContext[IAST_TRANSACTION_ID]
29
+
30
+ onRemoveTransaction(transactionId, iastContext)
31
+
17
32
  TaintedUtils.removeTransaction(transactionId)
18
33
  delete iastContext[IAST_TRANSACTION_ID]
19
34
  }
@@ -96,12 +111,16 @@ function getRanges (iastContext, string) {
96
111
  return result
97
112
  }
98
113
 
99
- function enableTaintOperations () {
100
- global._ddiast = TaintTracking
114
+ function enableTaintOperations (telemetryVerbosity) {
115
+ if (isInfoAllowed(telemetryVerbosity)) {
116
+ onRemoveTransaction = onRemoveTransactionInformationTelemetry
117
+ }
118
+
119
+ global._ddiast = getTaintTrackingImpl(telemetryVerbosity)
101
120
  }
102
121
 
103
122
  function disableTaintOperations () {
104
- global._ddiast = TaintTrackingDummy
123
+ global._ddiast = getTaintTrackingNoop()
105
124
  }
106
125
 
107
126
  function setMaxTransactions (transactions) {
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../../plugins/plugin')
3
+ const { SourceIastPlugin } = require('../iast-plugin')
4
4
  const { getIastContext } = require('../iast-context')
5
5
  const { storage } = require('../../../../../datadog-core')
6
6
  const { taintObject } = require('./operations')
@@ -12,15 +12,17 @@ const {
12
12
  HTTP_REQUEST_HEADER_NAME,
13
13
  HTTP_REQUEST_PARAMETER,
14
14
  HTTP_REQUEST_PATH_PARAM
15
+ } = require('./source-types')
15
16
 
16
- } = require('./origin-types')
17
-
18
- class TaintTrackingPlugin extends Plugin {
17
+ class TaintTrackingPlugin extends SourceIastPlugin {
19
18
  constructor () {
20
19
  super()
21
20
  this._type = 'taint-tracking'
21
+ }
22
+
23
+ onConfigure () {
22
24
  this.addSub(
23
- 'datadog:body-parser:read:finish',
25
+ { channelName: 'datadog:body-parser:read:finish', tag: HTTP_REQUEST_BODY },
24
26
  ({ req }) => {
25
27
  const iastContext = getIastContext(storage.getStore())
26
28
  if (iastContext && iastContext['body'] !== req.body) {
@@ -29,31 +31,41 @@ class TaintTrackingPlugin extends Plugin {
29
31
  }
30
32
  }
31
33
  )
34
+
32
35
  this.addSub(
33
- 'datadog:qs:parse:finish',
36
+ { channelName: 'datadog:qs:parse:finish', tag: HTTP_REQUEST_PARAMETER },
34
37
  ({ qs }) => this._taintTrackingHandler(HTTP_REQUEST_PARAMETER, qs)
35
38
  )
36
- this.addSub('apm:express:middleware:next', ({ req }) => {
37
- if (req && req.body && typeof req.body === 'object') {
38
- const iastContext = getIastContext(storage.getStore())
39
- if (iastContext && iastContext['body'] !== req.body) {
40
- this._taintTrackingHandler(HTTP_REQUEST_BODY, req, 'body', iastContext)
41
- iastContext['body'] = req.body
39
+
40
+ this.addSub(
41
+ { channelName: 'apm:express:middleware:next', tag: HTTP_REQUEST_BODY },
42
+ ({ req }) => {
43
+ if (req && req.body && typeof req.body === 'object') {
44
+ const iastContext = getIastContext(storage.getStore())
45
+ if (iastContext && iastContext['body'] !== req.body) {
46
+ this._taintTrackingHandler(HTTP_REQUEST_BODY, req, 'body', iastContext)
47
+ iastContext['body'] = req.body
48
+ }
42
49
  }
43
50
  }
44
- })
51
+ )
52
+
45
53
  this.addSub(
46
- 'datadog:cookie:parse:finish',
54
+ { channelName: 'datadog:cookie:parse:finish', tag: [HTTP_REQUEST_COOKIE_VALUE, HTTP_REQUEST_COOKIE_NAME] },
47
55
  ({ cookies }) => this._cookiesTaintTrackingHandler(cookies)
48
56
  )
57
+
49
58
  this.addSub(
50
- 'datadog:express:process_params:start',
59
+ { channelName: 'datadog:express:process_params:start', tag: HTTP_REQUEST_PATH_PARAM },
51
60
  ({ req }) => {
52
61
  if (req && req.params && typeof req.params === 'object') {
53
62
  this._taintTrackingHandler(HTTP_REQUEST_PATH_PARAM, req, 'params')
54
63
  }
55
64
  }
56
65
  )
66
+
67
+ // this is a special case to increment INSTRUMENTED_SOURCE metric for header
68
+ this.addInstrumentedSource('http', [HTTP_REQUEST_HEADER_VALUE, HTTP_REQUEST_HEADER_NAME])
57
69
  }
58
70
 
59
71
  _taintTrackingHandler (type, target, property, iastContext = getIastContext(storage.getStore())) {
@@ -70,7 +82,11 @@ class TaintTrackingPlugin extends Plugin {
70
82
  }
71
83
 
72
84
  taintHeaders (headers, iastContext) {
73
- taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE, true, HTTP_REQUEST_HEADER_NAME)
85
+ this.execSource({
86
+ handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE, true, HTTP_REQUEST_HEADER_NAME),
87
+ tag: [HTTP_REQUEST_HEADER_VALUE, HTTP_REQUEST_HEADER_NAME],
88
+ iastContext
89
+ })
74
90
  }
75
91
 
76
92
  enable () {
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+
3
+ const iastTelemetry = require('../telemetry')
4
+ const { Verbosity } = require('../telemetry/verbosity')
5
+ const { INSTRUMENTED_PROPAGATION } = require('../telemetry/iast-metric')
6
+
7
+ const telemetryRewriter = {
8
+ off (content, filename, rewriter) {
9
+ return rewriter.rewrite(content, filename)
10
+ },
11
+
12
+ information (content, filename, rewriter) {
13
+ const response = this.off(content, filename, rewriter)
14
+
15
+ const metrics = response.metrics
16
+ if (metrics && metrics.instrumentedPropagation) {
17
+ INSTRUMENTED_PROPAGATION.add(metrics.instrumentedPropagation)
18
+ }
19
+
20
+ return response
21
+ }
22
+ }
23
+
24
+ function getRewriteFunction (rewriter) {
25
+ switch (iastTelemetry.verbosity) {
26
+ case Verbosity.OFF:
27
+ return (content, filename) => telemetryRewriter.off(content, filename, rewriter)
28
+ default:
29
+ return (content, filename) => telemetryRewriter.information(content, filename, rewriter)
30
+ }
31
+ }
32
+
33
+ module.exports = { getRewriteFunction }
@@ -5,20 +5,17 @@ const shimmer = require('../../../../../datadog-shimmer')
5
5
  const iastLog = require('../iast-log')
6
6
  const { isPrivateModule, isNotLibraryFile } = require('./filter')
7
7
  const { csiMethods } = require('./csi-methods')
8
+ const { getName } = require('../telemetry/verbosity')
9
+ const { getRewriteFunction } = require('./rewriter-telemetry')
8
10
 
9
11
  let rewriter
10
12
  let getPrepareStackTrace
11
- function getRewriter () {
13
+ function getRewriter (telemetryVerbosity) {
12
14
  if (!rewriter) {
13
- try {
14
- const iastRewriter = require('@datadog/native-iast-rewriter')
15
- const Rewriter = iastRewriter.Rewriter
16
- getPrepareStackTrace = iastRewriter.getPrepareStackTrace
17
- rewriter = new Rewriter({ csiMethods })
18
- } catch (e) {
19
- iastLog.error('Unable to initialize TaintTracking Rewriter')
20
- .errorAndPublish(e)
21
- }
15
+ const iastRewriter = require('@datadog/native-iast-rewriter')
16
+ const Rewriter = iastRewriter.Rewriter
17
+ getPrepareStackTrace = iastRewriter.getPrepareStackTrace
18
+ rewriter = new Rewriter({ csiMethods, telemetryVerbosity: getName(telemetryVerbosity) })
22
19
  }
23
20
  return rewriter
24
21
  }
@@ -27,6 +24,7 @@ let originalPrepareStackTrace = Error.prepareStackTrace
27
24
  function getPrepareStackTraceAccessor () {
28
25
  let actual = getPrepareStackTrace(originalPrepareStackTrace)
29
26
  return {
27
+ configurable: true,
30
28
  get () {
31
29
  return actual
32
30
  },
@@ -38,10 +36,11 @@ function getPrepareStackTraceAccessor () {
38
36
  }
39
37
 
40
38
  function getCompileMethodFn (compileMethod) {
39
+ const rewriteFn = getRewriteFunction(rewriter)
41
40
  return function (content, filename) {
42
41
  try {
43
42
  if (isPrivateModule(filename) && isNotLibraryFile(filename)) {
44
- const rewritten = rewriter.rewrite(content, filename)
43
+ const rewritten = rewriteFn(content, filename)
45
44
  if (rewritten && rewritten.content) {
46
45
  return compileMethod.apply(this, [rewritten.content, filename])
47
46
  }
@@ -54,11 +53,19 @@ function getCompileMethodFn (compileMethod) {
54
53
  }
55
54
  }
56
55
 
57
- function enableRewriter () {
58
- const rewriter = getRewriter()
59
- if (rewriter) {
60
- Object.defineProperty(global.Error, 'prepareStackTrace', getPrepareStackTraceAccessor())
61
- shimmer.wrap(Module.prototype, '_compile', compileMethod => getCompileMethodFn(compileMethod))
56
+ function enableRewriter (telemetryVerbosity) {
57
+ try {
58
+ const rewriter = getRewriter(telemetryVerbosity)
59
+ if (rewriter) {
60
+ const pstDescriptor = Object.getOwnPropertyDescriptor(global.Error, 'prepareStackTrace')
61
+ if (!pstDescriptor || pstDescriptor.configurable) {
62
+ Object.defineProperty(global.Error, 'prepareStackTrace', getPrepareStackTraceAccessor())
63
+ }
64
+ shimmer.wrap(Module.prototype, '_compile', compileMethod => getCompileMethodFn(compileMethod))
65
+ }
66
+ } catch (e) {
67
+ iastLog.error('Error enabling TaintTracking Rewriter')
68
+ .errorAndPublish(e)
62
69
  }
63
70
  }
64
71