dd-trace 5.38.0 → 5.40.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 (97) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +30 -21
  3. package/package.json +4 -2
  4. package/packages/datadog-instrumentations/src/apollo-server-core.js +1 -1
  5. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  6. package/packages/datadog-instrumentations/src/express-session.js +41 -0
  7. package/packages/datadog-instrumentations/src/fetch.js +27 -6
  8. package/packages/datadog-instrumentations/src/helpers/fetch.js +6 -1
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  10. package/packages/datadog-instrumentations/src/jest.js +16 -10
  11. package/packages/datadog-instrumentations/src/mocha/main.js +2 -1
  12. package/packages/datadog-instrumentations/src/nyc.js +2 -1
  13. package/packages/datadog-instrumentations/src/vitest.js +4 -2
  14. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
  15. package/packages/datadog-plugin-amqplib/src/producer.js +1 -2
  16. package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
  17. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -1
  18. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -8
  19. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -4
  20. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
  21. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  22. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  23. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
  24. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
  25. package/packages/datadog-plugin-kafkajs/src/consumer.js +5 -2
  26. package/packages/datadog-plugin-kafkajs/src/producer.js +4 -3
  27. package/packages/datadog-plugin-mongodb-core/src/index.js +10 -13
  28. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  29. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  30. package/packages/datadog-plugin-rhea/src/producer.js +1 -2
  31. package/packages/datadog-shimmer/src/shimmer.js +95 -95
  32. package/packages/dd-trace/src/appsec/addresses.js +1 -0
  33. package/packages/dd-trace/src/appsec/channels.js +1 -0
  34. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +1 -1
  35. package/packages/dd-trace/src/appsec/iast/iast-context.js +2 -2
  36. package/packages/dd-trace/src/appsec/iast/index.js +0 -1
  37. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -2
  38. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -5
  39. package/packages/dd-trace/src/appsec/index.js +23 -1
  40. package/packages/dd-trace/src/appsec/reporter.js +3 -8
  41. package/packages/dd-trace/src/appsec/rule_manager.js +1 -1
  42. package/packages/dd-trace/src/appsec/sdk/set_user.js +9 -5
  43. package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -4
  44. package/packages/dd-trace/src/appsec/telemetry/common.js +24 -0
  45. package/packages/dd-trace/src/appsec/telemetry/index.js +126 -0
  46. package/packages/dd-trace/src/appsec/telemetry/rasp.js +35 -0
  47. package/packages/dd-trace/src/appsec/telemetry/user.js +24 -0
  48. package/packages/dd-trace/src/appsec/telemetry/waf.js +92 -0
  49. package/packages/dd-trace/src/appsec/user_tracking.js +2 -4
  50. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +16 -4
  51. package/packages/dd-trace/src/config.js +31 -14
  52. package/packages/dd-trace/src/constants.js +1 -1
  53. package/packages/dd-trace/src/{data_streams.js → datastreams/checkpointer.js} +1 -1
  54. package/packages/dd-trace/src/{data_streams_context.js → datastreams/context.js} +2 -2
  55. package/packages/dd-trace/src/datastreams/index.js +104 -0
  56. package/packages/dd-trace/src/datastreams/manager.js +27 -0
  57. package/packages/dd-trace/src/datastreams/processor.js +1 -44
  58. package/packages/dd-trace/src/datastreams/size.js +53 -0
  59. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -2
  60. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -1
  61. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +22 -15
  62. package/packages/dd-trace/src/dogstatsd.js +23 -4
  63. package/packages/dd-trace/src/exporters/agent/index.js +2 -2
  64. package/packages/dd-trace/src/flare/index.js +3 -0
  65. package/packages/dd-trace/src/noop/dogstatsd.js +6 -0
  66. package/packages/dd-trace/src/opentelemetry/tracer.js +45 -1
  67. package/packages/dd-trace/src/opentracing/propagation/text_map.js +11 -47
  68. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +1 -1
  69. package/packages/dd-trace/src/opentracing/span.js +12 -2
  70. package/packages/dd-trace/src/payload-tagging/config/aws.json +8 -0
  71. package/packages/dd-trace/src/plugin_manager.js +4 -3
  72. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
  73. package/packages/dd-trace/src/priority_sampler.js +5 -3
  74. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  75. package/packages/dd-trace/src/profiling/profilers/wall.js +15 -4
  76. package/packages/dd-trace/src/proxy.js +41 -22
  77. package/packages/dd-trace/src/{appsec/remote_config → remote_config}/capabilities.js +1 -0
  78. package/packages/dd-trace/src/{appsec/remote_config → remote_config}/index.js +8 -5
  79. package/packages/dd-trace/src/{appsec/remote_config → remote_config}/manager.js +5 -5
  80. package/packages/dd-trace/src/runtime_metrics/index.js +34 -0
  81. package/packages/dd-trace/src/{runtime_metrics.js → runtime_metrics/runtime_metrics.js} +4 -4
  82. package/packages/dd-trace/src/serverless.js +10 -1
  83. package/packages/dd-trace/src/service-naming/index.js +12 -4
  84. package/packages/dd-trace/src/span_processor.js +7 -4
  85. package/packages/dd-trace/src/span_stats.js +1 -2
  86. package/packages/dd-trace/src/standalone/index.js +70 -0
  87. package/packages/dd-trace/src/standalone/product.js +24 -0
  88. package/packages/dd-trace/src/standalone/tracesource.js +22 -0
  89. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +47 -0
  90. package/packages/dd-trace/src/telemetry/index.js +16 -387
  91. package/packages/dd-trace/src/telemetry/telemetry.js +394 -0
  92. package/packages/dd-trace/src/tracer.js +7 -15
  93. package/packages/dd-trace/src/appsec/standalone.js +0 -130
  94. package/packages/dd-trace/src/appsec/telemetry.js +0 -218
  95. package/packages/dd-trace/src/service-naming/schemas/index.js +0 -6
  96. /package/packages/dd-trace/src/{appsec/remote_config → remote_config}/apply_states.js +0 -0
  97. /package/packages/dd-trace/src/{appsec/remote_config → remote_config}/scheduler.js +0 -0
@@ -25,7 +25,7 @@ class MongodbCorePlugin extends DatabasePlugin {
25
25
  'out.port': options.port
26
26
  }
27
27
  })
28
- ops = this.injectDbmCommand(span, ops, service)
28
+ ops.comment = this.injectDbmComment(span, ops.comment, service)
29
29
  }
30
30
 
31
31
  getPeerService (tags) {
@@ -37,28 +37,25 @@ class MongodbCorePlugin extends DatabasePlugin {
37
37
  return super.getPeerService(tags)
38
38
  }
39
39
 
40
- injectDbmCommand (span, command, serviceName) {
40
+ injectDbmComment (span, comment, serviceName) {
41
41
  const dbmTraceComment = this.createDbmComment(span, serviceName)
42
42
 
43
43
  if (!dbmTraceComment) {
44
- return command
44
+ return comment
45
45
  }
46
46
 
47
- // create a copy of the command to avoid mutating the original
48
- const dbmTracedCommand = { ...command }
49
-
50
- if (dbmTracedCommand.comment) {
47
+ if (comment) {
51
48
  // if the command already has a comment, append the dbm trace comment
52
- if (typeof dbmTracedCommand.comment === 'string') {
53
- dbmTracedCommand.comment += `,${dbmTraceComment}`
54
- } else if (Array.isArray(dbmTracedCommand.comment)) {
55
- dbmTracedCommand.comment.push(dbmTraceComment)
49
+ if (typeof comment === 'string') {
50
+ comment += `,${dbmTraceComment}`
51
+ } else if (Array.isArray(comment)) {
52
+ comment.push(dbmTraceComment)
56
53
  } // do nothing if the comment is not a string or an array
57
54
  } else {
58
- dbmTracedCommand.comment = dbmTraceComment
55
+ comment = dbmTraceComment
59
56
  }
60
57
 
61
- return dbmTracedCommand
58
+ return comment
62
59
  }
63
60
  }
64
61
 
@@ -10,7 +10,7 @@ const {
10
10
  const log = require('../../dd-trace/src/log')
11
11
  const {
12
12
  SchemaBuilder
13
- } = require('../../dd-trace/src/datastreams/schemas/schema_builder')
13
+ } = require('../../dd-trace/src/datastreams')
14
14
 
15
15
  class SchemaExtractor {
16
16
  constructor (schema) {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
4
4
  const { storage } = require('../../datadog-core')
5
- const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
5
+ const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams')
6
6
 
7
7
  class RheaConsumerPlugin extends ConsumerPlugin {
8
8
  static get id () { return 'rhea' }
@@ -2,8 +2,7 @@
2
2
 
3
3
  const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
4
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
5
- const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
6
- const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
5
+ const { getAmqpMessageSize, DsmPathwayCodec } = require('../../dd-trace/src/datastreams')
7
6
 
8
7
  class RheaProducerPlugin extends ProducerPlugin {
9
8
  static get id () { return 'rhea' }
@@ -26,10 +26,10 @@ function copyProperties (original, wrapped) {
26
26
 
27
27
  function wrapFunction (original, wrapper) {
28
28
  if (typeof original === 'function') assertNotClass(original)
29
- // TODO This needs to be re-done so that this and wrapMethod are distinct.
30
- const target = { func: original }
31
- wrapMethod(target, 'func', wrapper, typeof original !== 'function')
32
- let delegate = target.func
29
+
30
+ let delegate = safeMode
31
+ ? safeWrapper(original, wrapper)
32
+ : wrapper(original)
33
33
 
34
34
  const shim = function shim () {
35
35
  return delegate.apply(this, arguments)
@@ -85,98 +85,10 @@ function wrapMethod (target, name, wrapper, noAssert) {
85
85
  }
86
86
 
87
87
  const original = target[name]
88
- let wrapped
89
-
90
- if (safeMode && original) {
91
- // In this mode, we make a best-effort attempt to handle errors that are thrown
92
- // by us, rather than wrapped code. With such errors, we log them, and then attempt
93
- // to return the result as if no wrapping was done at all.
94
- //
95
- // Caveats:
96
- // * If the original function is called in a later iteration of the event loop,
97
- // and we throw _then_, then it won't be caught by this. In practice, we always call
98
- // the original function synchronously, so this is not a problem.
99
- // * While async errors are dealt with here, errors in callbacks are not. This
100
- // is because we don't necessarily know _for sure_ that any function arguments
101
- // are wrapped by us. We could wrap them all anyway and just make that assumption,
102
- // or just assume that the last argument is always a callback set by us if it's a
103
- // function, but those don't seem like things we can rely on. We could add a
104
- // `shimmer.markCallbackAsWrapped()` function that's a no-op outside safe-mode,
105
- // but that means modifying every instrumentation. Even then, the complexity of
106
- // this code increases because then we'd need to effectively do the reverse of
107
- // what we're doing for synchronous functions. This is a TODO.
108
-
109
- // We're going to hold on to current callState in this variable in this scope,
110
- // which is fine because any time we reference it, we're referencing it synchronously.
111
- // We'll use it in the our wrapper (which, again, is called syncrhonously), and in the
112
- // errorHandler, which will already have been bound to this callState.
113
- let currentCallState
114
-
115
- // Rather than calling the original function directly from the shim wrapper, we wrap
116
- // it again so that we can track if it was called and if it returned. This is because
117
- // we need to know if an error was thrown by the original function, or by us.
118
- // We could do this inside the `wrapper` function defined below, which would simplify
119
- // managing the callState, but then we'd be calling `wrapper` on each invocation, so
120
- // instead we do it here, once.
121
- const innerWrapped = wrapper(function (...args) {
122
- // We need to stash the callState here because of recursion.
123
- const callState = currentCallState
124
- callState.startCall()
125
- const retVal = original.apply(this, args)
126
- if (isPromise(retVal)) {
127
- retVal.then(callState.endCall.bind(callState))
128
- } else {
129
- callState.endCall(retVal)
130
- }
131
- return retVal
132
- })
133
-
134
- // This is the crux of what we're doing in safe mode. It handles errors
135
- // that _we_ cause, by logging them, and transparently providing results
136
- // as if no wrapping was done at all. That means detecting (via callState)
137
- // whether the function has already run or not, and if it has, returning
138
- // the result, and otherwise calling the original function unwrapped.
139
- const handleError = function (args, callState, e) {
140
- if (callState.completed) {
141
- // error was thrown after original function returned/resolved, so
142
- // it was us. log it.
143
- log.error('Shimmer error was thrown after original function returned/resolved', e)
144
- // original ran and returned something. return it.
145
- return callState.retVal
146
- }
147
-
148
- if (!callState.called) {
149
- // error was thrown before original function was called, so
150
- // it was us. log it.
151
- log.error('Shimmer error was thrown before original function was called', e)
152
- // original never ran. call it unwrapped.
153
- return original.apply(this, args)
154
- }
155
-
156
- // error was thrown during original function execution, so
157
- // it was them. throw.
158
- throw e
159
- }
88
+ const wrapped = safeMode && original
89
+ ? safeWrapper(original, wrapper)
90
+ : wrapper(original)
160
91
 
161
- // The wrapped function is the one that will be called by the user.
162
- // It calls our version of the original function, which manages the
163
- // callState. That way when we use the errorHandler, it can tell where
164
- // the error originated.
165
- wrapped = function (...args) {
166
- currentCallState = new CallState()
167
- const errorHandler = handleError.bind(this, args, currentCallState)
168
-
169
- try {
170
- const retVal = innerWrapped.apply(this, args)
171
- return isPromise(retVal) ? retVal.catch(errorHandler) : retVal
172
- } catch (e) {
173
- return errorHandler(e)
174
- }
175
- }
176
- } else {
177
- // In non-safe mode, we just wrap the original function directly.
178
- wrapped = wrapper(original)
179
- }
180
92
  const descriptor = Object.getOwnPropertyDescriptor(target, name)
181
93
 
182
94
  const attributes = {
@@ -212,6 +124,94 @@ function wrapMethod (target, name, wrapper, noAssert) {
212
124
  return target
213
125
  }
214
126
 
127
+ function safeWrapper (original, wrapper) {
128
+ // In this mode, we make a best-effort attempt to handle errors that are thrown
129
+ // by us, rather than wrapped code. With such errors, we log them, and then attempt
130
+ // to return the result as if no wrapping was done at all.
131
+ //
132
+ // Caveats:
133
+ // * If the original function is called in a later iteration of the event loop,
134
+ // and we throw _then_, then it won't be caught by this. In practice, we always call
135
+ // the original function synchronously, so this is not a problem.
136
+ // * While async errors are dealt with here, errors in callbacks are not. This
137
+ // is because we don't necessarily know _for sure_ that any function arguments
138
+ // are wrapped by us. We could wrap them all anyway and just make that assumption,
139
+ // or just assume that the last argument is always a callback set by us if it's a
140
+ // function, but those don't seem like things we can rely on. We could add a
141
+ // `shimmer.markCallbackAsWrapped()` function that's a no-op outside safe-mode,
142
+ // but that means modifying every instrumentation. Even then, the complexity of
143
+ // this code increases because then we'd need to effectively do the reverse of
144
+ // what we're doing for synchronous functions. This is a TODO.
145
+
146
+ // We're going to hold on to current callState in this variable in this scope,
147
+ // which is fine because any time we reference it, we're referencing it synchronously.
148
+ // We'll use it in the our wrapper (which, again, is called syncrhonously), and in the
149
+ // errorHandler, which will already have been bound to this callState.
150
+ let currentCallState
151
+
152
+ // Rather than calling the original function directly from the shim wrapper, we wrap
153
+ // it again so that we can track if it was called and if it returned. This is because
154
+ // we need to know if an error was thrown by the original function, or by us.
155
+ // We could do this inside the `wrapper` function defined below, which would simplify
156
+ // managing the callState, but then we'd be calling `wrapper` on each invocation, so
157
+ // instead we do it here, once.
158
+ const innerWrapped = wrapper(function (...args) {
159
+ // We need to stash the callState here because of recursion.
160
+ const callState = currentCallState
161
+ callState.startCall()
162
+ const retVal = original.apply(this, args)
163
+ if (isPromise(retVal)) {
164
+ retVal.then(callState.endCall.bind(callState))
165
+ } else {
166
+ callState.endCall(retVal)
167
+ }
168
+ return retVal
169
+ })
170
+
171
+ // This is the crux of what we're doing in safe mode. It handles errors
172
+ // that _we_ cause, by logging them, and transparently providing results
173
+ // as if no wrapping was done at all. That means detecting (via callState)
174
+ // whether the function has already run or not, and if it has, returning
175
+ // the result, and otherwise calling the original function unwrapped.
176
+ const handleError = function (args, callState, e) {
177
+ if (callState.completed) {
178
+ // error was thrown after original function returned/resolved, so
179
+ // it was us. log it.
180
+ log.error('Shimmer error was thrown after original function returned/resolved', e)
181
+ // original ran and returned something. return it.
182
+ return callState.retVal
183
+ }
184
+
185
+ if (!callState.called) {
186
+ // error was thrown before original function was called, so
187
+ // it was us. log it.
188
+ log.error('Shimmer error was thrown before original function was called', e)
189
+ // original never ran. call it unwrapped.
190
+ return original.apply(this, args)
191
+ }
192
+
193
+ // error was thrown during original function execution, so
194
+ // it was them. throw.
195
+ throw e
196
+ }
197
+
198
+ // The wrapped function is the one that will be called by the user.
199
+ // It calls our version of the original function, which manages the
200
+ // callState. That way when we use the errorHandler, it can tell where
201
+ // the error originated.
202
+ return function (...args) {
203
+ currentCallState = new CallState()
204
+ const errorHandler = handleError.bind(this, args, currentCallState)
205
+
206
+ try {
207
+ const retVal = innerWrapped.apply(this, args)
208
+ return isPromise(retVal) ? retVal.catch(errorHandler) : retVal
209
+ } catch (e) {
210
+ return errorHandler(e)
211
+ }
212
+ }
213
+ }
214
+
215
215
  function wrap (target, name, wrapper) {
216
216
  return typeof name === 'function'
217
217
  ? wrapFn(target, name)
@@ -22,6 +22,7 @@ module.exports = {
22
22
 
23
23
  USER_ID: 'usr.id',
24
24
  USER_LOGIN: 'usr.login',
25
+ USER_SESSION_ID: 'usr.session_id',
25
26
 
26
27
  WAF_CONTEXT_PROCESSOR: 'waf.context.processor',
27
28
 
@@ -15,6 +15,7 @@ module.exports = {
15
15
  incomingHttpRequestEnd: dc.channel('dd-trace:incomingHttpRequestEnd'),
16
16
  passportVerify: dc.channel('datadog:passport:verify:finish'),
17
17
  passportUser: dc.channel('datadog:passport:deserializeUser:finish'),
18
+ expressSession: dc.channel('datadog:express-session:middleware:finish'),
18
19
  queryParser: dc.channel('datadog:query:read:finish'),
19
20
  setCookieChannel: dc.channel('datadog:iast:set-cookie'),
20
21
  nextBodyParsed: dc.channel('apm:next:body-parsed'),
@@ -133,9 +133,9 @@ class Analyzer extends SinkIastPlugin {
133
133
  return {
134
134
  type,
135
135
  evidence,
136
- stackId,
137
136
  location: {
138
137
  spanId: _spanId,
138
+ stackId,
139
139
  ...location
140
140
  },
141
141
  hash: this._createHash(this._createHashSource(type, evidence, location))
@@ -10,14 +10,14 @@ function getIastContext (store, topContext) {
10
10
  }
11
11
 
12
12
  function getIastStackTraceId (iastContext) {
13
- if (!iastContext) return 0
13
+ if (!iastContext) return '0'
14
14
 
15
15
  if (!iastContext.stackTraceId) {
16
16
  iastContext.stackTraceId = 0
17
17
  }
18
18
 
19
19
  iastContext.stackTraceId += 1
20
- return iastContext.stackTraceId
20
+ return String(iastContext.stackTraceId)
21
21
  }
22
22
 
23
23
  /* TODO Fix storage problem when the close event is called without
@@ -22,7 +22,6 @@ const securityControls = require('./security-controls')
22
22
  const requestStart = dc.channel('dd-trace:incomingHttpRequestStart')
23
23
  const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
24
24
  const iastResponseEnd = dc.channel('datadog:iast:response-end')
25
-
26
25
  let isEnabled = false
27
26
 
28
27
  function enable (config, _tracer) {
@@ -81,12 +81,11 @@ class VulnerabilityFormatter {
81
81
  }
82
82
 
83
83
  formatVulnerability (vulnerability, sourcesIndexes, sources) {
84
- const { type, hash, stackId, evidence, location } = vulnerability
84
+ const { type, hash, evidence, location } = vulnerability
85
85
 
86
86
  const formattedVulnerability = {
87
87
  type,
88
88
  hash,
89
- stackId,
90
89
  evidence: this.formatEvidence(type, evidence, sourcesIndexes, sources),
91
90
  location
92
91
  }
@@ -3,11 +3,10 @@
3
3
  const LRU = require('lru-cache')
4
4
  const vulnerabilitiesFormatter = require('./vulnerabilities-formatter')
5
5
  const { IAST_ENABLED_TAG_KEY, IAST_JSON_TAG_KEY } = require('./tags')
6
- const standalone = require('../standalone')
7
- const { SAMPLING_MECHANISM_APPSEC } = require('../../constants')
8
6
  const { keepTrace } = require('../../priority_sampler')
9
7
  const { reportStackTrace, getCallsiteFrames, canReportStackTrace, STACK_TRACE_NAMESPACES } = require('../stack_trace')
10
8
  const { getOriginalPathAndLineFromSourceMap } = require('./taint-tracking/rewriter')
9
+ const { ASM } = require('../../standalone/product')
11
10
 
12
11
  const VULNERABILITIES_KEY = 'vulnerabilities'
13
12
  const VULNERABILITY_HASHES_MAX_SIZE = 1000
@@ -51,15 +50,14 @@ function addVulnerability (iastContext, vulnerability, callSiteFrames) {
51
50
 
52
51
  if (!span) return
53
52
 
54
- keepTrace(span, SAMPLING_MECHANISM_APPSEC)
55
- standalone.sample(span)
53
+ keepTrace(span, ASM)
56
54
 
57
55
  if (stackTraceEnabled && canReportStackTrace(span, maxStackTraces, STACK_TRACE_NAMESPACES.IAST)) {
58
56
  const originalCallSiteList = callSiteFrames.map(callsite => replaceCallSiteFromSourceMap(callsite))
59
57
 
60
58
  reportStackTrace(
61
59
  span,
62
- vulnerability.stackId,
60
+ vulnerability.location.stackId,
63
61
  originalCallSiteList,
64
62
  STACK_TRACE_NAMESPACES.IAST
65
63
  )
@@ -2,7 +2,7 @@
2
2
 
3
3
  const log = require('../log')
4
4
  const RuleManager = require('./rule_manager')
5
- const remoteConfig = require('./remote_config')
5
+ const remoteConfig = require('../remote_config')
6
6
  const {
7
7
  bodyParser,
8
8
  cookieParser,
@@ -11,6 +11,7 @@ const {
11
11
  incomingHttpRequestEnd,
12
12
  passportVerify,
13
13
  passportUser,
14
+ expressSession,
14
15
  queryParser,
15
16
  nextBodyParsed,
16
17
  nextQueryParsed,
@@ -69,6 +70,7 @@ function enable (_config) {
69
70
  incomingHttpRequestEnd.subscribe(incomingHttpEndTranslator)
70
71
  passportVerify.subscribe(onPassportVerify) // possible optimization: only subscribe if collection mode is enabled
71
72
  passportUser.subscribe(onPassportDeserializeUser)
73
+ expressSession.subscribe(onExpressSession)
72
74
  queryParser.subscribe(onRequestQueryParsed)
73
75
  nextBodyParsed.subscribe(onRequestBodyParsed)
74
76
  nextQueryParsed.subscribe(onRequestQueryParsed)
@@ -213,6 +215,25 @@ function onPassportDeserializeUser ({ user, abortController }) {
213
215
  handleResults(results, store.req, store.req.res, rootSpan, abortController)
214
216
  }
215
217
 
218
+ function onExpressSession ({ req, res, sessionId, abortController }) {
219
+ const rootSpan = web.root(req)
220
+ if (!rootSpan) {
221
+ log.warn('[ASM] No rootSpan found in onExpressSession')
222
+ return
223
+ }
224
+
225
+ const isSdkCalled = rootSpan.context()._tags['usr.session_id']
226
+ if (isSdkCalled) return
227
+
228
+ const results = waf.run({
229
+ persistent: {
230
+ [addresses.USER_SESSION_ID]: sessionId
231
+ }
232
+ }, req)
233
+
234
+ handleResults(results, req, res, rootSpan, abortController)
235
+ }
236
+
216
237
  function onRequestQueryParsed ({ req, res, query, abortController }) {
217
238
  if (!query || typeof query !== 'object') return
218
239
 
@@ -327,6 +348,7 @@ function disable () {
327
348
  if (incomingHttpRequestEnd.hasSubscribers) incomingHttpRequestEnd.unsubscribe(incomingHttpEndTranslator)
328
349
  if (passportVerify.hasSubscribers) passportVerify.unsubscribe(onPassportVerify)
329
350
  if (passportUser.hasSubscribers) passportUser.unsubscribe(onPassportDeserializeUser)
351
+ if (expressSession.hasSubscribers) expressSession.unsubscribe(onExpressSession)
330
352
  if (queryParser.hasSubscribers) queryParser.unsubscribe(onRequestQueryParsed)
331
353
  if (nextBodyParsed.hasSubscribers) nextBodyParsed.unsubscribe(onRequestBodyParsed)
332
354
  if (nextQueryParsed.hasSubscribers) nextQueryParsed.unsubscribe(onRequestQueryParsed)
@@ -13,9 +13,8 @@ const {
13
13
  getRequestMetrics
14
14
  } = require('./telemetry')
15
15
  const zlib = require('zlib')
16
- const standalone = require('./standalone')
17
- const { SAMPLING_MECHANISM_APPSEC } = require('../constants')
18
16
  const { keepTrace } = require('../priority_sampler')
17
+ const { ASM } = require('../standalone/product')
19
18
 
20
19
  // default limiter, configurable with setRateLimit()
21
20
  let limiter = new Limiter(100)
@@ -129,9 +128,7 @@ function reportAttack (attackData) {
129
128
  }
130
129
 
131
130
  if (limiter.isAllowed()) {
132
- keepTrace(rootSpan, SAMPLING_MECHANISM_APPSEC)
133
-
134
- standalone.sample(rootSpan)
131
+ keepTrace(rootSpan, ASM)
135
132
  }
136
133
 
137
134
  // TODO: maybe add this to format.js later (to take decision as late as possible)
@@ -186,9 +183,7 @@ function finishRequest (req, res) {
186
183
  if (metricsQueue.size) {
187
184
  rootSpan.addTags(Object.fromEntries(metricsQueue))
188
185
 
189
- keepTrace(rootSpan, SAMPLING_MECHANISM_APPSEC)
190
-
191
- standalone.sample(rootSpan)
186
+ keepTrace(rootSpan, ASM)
192
187
 
193
188
  metricsQueue.clear()
194
189
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs')
4
4
  const waf = require('./waf')
5
- const { ACKNOWLEDGED, ERROR } = require('./remote_config/apply_states')
5
+ const { ACKNOWLEDGED, ERROR } = require('../remote_config/apply_states')
6
6
 
7
7
  const blocking = require('./blocking')
8
8
 
@@ -26,11 +26,15 @@ function setUser (tracer, user) {
26
26
  setUserTags(user, rootSpan)
27
27
  rootSpan.setTag('_dd.appsec.user.collection_mode', 'sdk')
28
28
 
29
- waf.run({
30
- persistent: {
31
- [addresses.USER_ID]: '' + user.id
32
- }
33
- })
29
+ const persistent = {
30
+ [addresses.USER_ID]: '' + user.id
31
+ }
32
+
33
+ if (user.session_id && typeof user.session_id === 'string') {
34
+ persistent[addresses.USER_SESSION_ID] = user.session_id
35
+ }
36
+
37
+ waf.run({ persistent })
34
38
  }
35
39
 
36
40
  module.exports = {
@@ -3,11 +3,10 @@
3
3
  const log = require('../../log')
4
4
  const { getRootSpan } = require('./utils')
5
5
  const { setUserTags } = require('./set_user')
6
- const standalone = require('../standalone')
7
6
  const waf = require('../waf')
8
- const { SAMPLING_MECHANISM_APPSEC } = require('../../constants')
9
7
  const { keepTrace } = require('../../priority_sampler')
10
8
  const addresses = require('../addresses')
9
+ const { ASM } = require('../../standalone/product')
11
10
 
12
11
  function trackUserLoginSuccessEvent (tracer, user, metadata) {
13
12
  // TODO: better user check here and in _setUser() ?
@@ -79,8 +78,7 @@ function trackEvent (eventName, fields, sdkMethodName, rootSpan) {
79
78
 
80
79
  rootSpan.addTags(tags)
81
80
 
82
- keepTrace(rootSpan, SAMPLING_MECHANISM_APPSEC)
83
- standalone.sample(rootSpan)
81
+ keepTrace(rootSpan, ASM)
84
82
  }
85
83
 
86
84
  function runWaf (eventName, user) {
@@ -0,0 +1,24 @@
1
+ 'use strinct'
2
+
3
+ const DD_TELEMETRY_REQUEST_METRICS = Symbol('_dd.appsec.telemetry.request.metrics')
4
+
5
+ const tags = {
6
+ REQUEST_BLOCKED: 'request_blocked',
7
+ RULE_TRIGGERED: 'rule_triggered',
8
+ WAF_TIMEOUT: 'waf_timeout',
9
+ WAF_VERSION: 'waf_version',
10
+ EVENT_RULES_VERSION: 'event_rules_version'
11
+ }
12
+
13
+ function getVersionsTags (wafVersion, rulesVersion) {
14
+ return {
15
+ [tags.WAF_VERSION]: wafVersion,
16
+ [tags.EVENT_RULES_VERSION]: rulesVersion
17
+ }
18
+ }
19
+
20
+ module.exports = {
21
+ tags,
22
+ getVersionsTags,
23
+ DD_TELEMETRY_REQUEST_METRICS
24
+ }