dd-trace 3.26.0 → 3.28.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
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { storage } = require('../../datadog-core')
3
4
  const ClientPlugin = require('../../dd-trace/src/plugins/client')
4
5
  const { TEXT_MAP } = require('../../../ext/formats')
5
6
  const { addMetadataTags, getFilter, getMethodMetadata } = require('./util')
@@ -7,9 +8,20 @@ const { addMetadataTags, getFilter, getMethodMetadata } = require('./util')
7
8
  class GrpcClientPlugin extends ClientPlugin {
8
9
  static get id () { return 'grpc' }
9
10
  static get operation () { return 'client:request' }
11
+ static get prefix () { return `apm:grpc:client:request` }
10
12
  static get peerServicePrecursors () { return ['rpc.service'] }
11
13
 
12
- start ({ metadata, path, type }) {
14
+ constructor (...args) {
15
+ super(...args)
16
+
17
+ this.addTraceBind('emit', ({ parentStore }) => {
18
+ return parentStore
19
+ })
20
+ }
21
+
22
+ bindStart (message) {
23
+ const store = storage.getStore()
24
+ const { metadata, path, type } = message
13
25
  const metadataFilter = this.config.metadataFilter
14
26
  const method = getMethodMetadata(path, type)
15
27
  const span = this.startSpan(this.operationName(), {
@@ -28,7 +40,7 @@ class GrpcClientPlugin extends ClientPlugin {
28
40
  metrics: {
29
41
  'grpc.status.code': 0
30
42
  }
31
- })
43
+ }, false)
32
44
 
33
45
  // needed as precursor for peer.service
34
46
  if (method.service && method.package) {
@@ -39,22 +51,27 @@ class GrpcClientPlugin extends ClientPlugin {
39
51
  addMetadataTags(span, metadata, metadataFilter, 'request')
40
52
  inject(this.tracer, span, metadata)
41
53
  }
42
- }
43
54
 
44
- error (error) {
45
- const span = this.activeSpan
55
+ message.span = span
56
+ message.parentStore = store
57
+ message.currentStore = { ...store, span }
46
58
 
47
- if (!span) return
59
+ return message.currentStore
60
+ }
48
61
 
49
- this.addCode(span, error.code)
50
- this.addError(error)
62
+ bindAsyncStart ({ parentStore }) {
63
+ return parentStore
51
64
  }
52
65
 
53
- finish ({ code, metadata }) {
54
- const span = this.activeSpan
66
+ error ({ span, error }) {
67
+ this.addCode(span, error.code)
68
+ this.addError(error, span)
69
+ }
55
70
 
71
+ finish ({ span, result }) {
56
72
  if (!span) return
57
73
 
74
+ const { code, metadata } = result || {}
58
75
  const metadataFilter = this.config.metadataFilter
59
76
 
60
77
  this.addCode(span, code)
@@ -63,7 +80,8 @@ class GrpcClientPlugin extends ClientPlugin {
63
80
  addMetadataTags(span, metadata, metadataFilter, 'response')
64
81
  }
65
82
 
66
- super.finish()
83
+ this.tagPeerService(span)
84
+ span.finish()
67
85
  }
68
86
 
69
87
  configure (config) {
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { storage } = require('../../datadog-core')
3
4
  const ServerPlugin = require('../../dd-trace/src/plugins/server')
4
5
  const { TEXT_MAP } = require('../../../ext/formats')
5
6
  const { addMetadataTags, getFilter, getMethodMetadata } = require('./util')
@@ -7,6 +8,7 @@ const { addMetadataTags, getFilter, getMethodMetadata } = require('./util')
7
8
  class GrpcServerPlugin extends ServerPlugin {
8
9
  static get id () { return 'grpc' }
9
10
  static get operation () { return 'server:request' }
11
+ static get prefix () { return `apm:grpc:server:request` }
10
12
 
11
13
  constructor (...args) {
12
14
  super(...args)
@@ -18,9 +20,15 @@ class GrpcServerPlugin extends ServerPlugin {
18
20
 
19
21
  this.addCode(span, code)
20
22
  })
23
+
24
+ this.addTraceBind('emit', ({ currentStore }) => {
25
+ return currentStore
26
+ })
21
27
  }
22
28
 
23
- start ({ name, metadata, type }) {
29
+ bindStart (message) {
30
+ const store = storage.getStore()
31
+ const { name, metadata, type } = message
24
32
  const metadataFilter = this.config.metadataFilter
25
33
  const childOf = extract(this.tracer, metadata)
26
34
  const method = getMethodMetadata(name, type)
@@ -44,9 +52,19 @@ class GrpcServerPlugin extends ServerPlugin {
44
52
  })
45
53
 
46
54
  addMetadataTags(span, metadata, metadataFilter, 'request')
55
+
56
+ message.span = span
57
+ message.parentStore = store
58
+ message.currentStore = { ...store, span }
59
+
60
+ return message.currentStore
47
61
  }
48
62
 
49
- error (error) {
63
+ bindAsyncStart ({ parentStore }) {
64
+ return parentStore
65
+ }
66
+
67
+ error ({ error }) {
50
68
  const span = this.activeSpan
51
69
 
52
70
  if (!span) return
@@ -55,9 +73,7 @@ class GrpcServerPlugin extends ServerPlugin {
55
73
  this.addError(error)
56
74
  }
57
75
 
58
- finish ({ code, trailer } = {}) {
59
- const span = this.activeSpan
60
-
76
+ finish ({ span, code, trailer }) {
61
77
  if (!span) return
62
78
 
63
79
  const metadataFilter = this.config.metadataFilter
@@ -68,7 +84,7 @@ class GrpcServerPlugin extends ServerPlugin {
68
84
  addMetadataTags(span, trailer, metadataFilter, 'response')
69
85
  }
70
86
 
71
- super.finish()
87
+ span.finish()
72
88
  }
73
89
 
74
90
  configure (config) {
@@ -8,7 +8,6 @@ const log = require('../../dd-trace/src/log')
8
8
  const tags = require('../../../ext/tags')
9
9
  const kinds = require('../../../ext/kinds')
10
10
  const formats = require('../../../ext/formats')
11
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
12
11
  const { COMPONENT, CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
13
12
  const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
14
13
 
@@ -25,32 +24,11 @@ const HTTP2_HEADER_STATUS = ':status'
25
24
  const HTTP2_METHOD_GET = 'GET'
26
25
 
27
26
  class Http2ClientPlugin extends ClientPlugin {
28
- static get id () {
29
- return 'http2'
30
- }
31
-
32
- constructor (...args) {
33
- super(...args)
34
-
35
- this.addSub('apm:http2:client:response', (headers) => {
36
- const span = storage.getStore().span
37
- const status = headers && headers[HTTP2_HEADER_STATUS]
38
-
39
- span.setTag(HTTP_STATUS_CODE, status)
40
-
41
- if (!this.config.validateStatus(status)) {
42
- this.addError()
43
- }
27
+ static get id () { return 'http2' }
28
+ static get prefix () { return `apm:http2:client:request` }
44
29
 
45
- addHeaderTags(span, headers, HTTP_RESPONSE_HEADERS, this.config)
46
- })
47
- }
48
-
49
- addTraceSub (eventName, handler) {
50
- this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
51
- }
52
-
53
- start ({ authority, options, headers = {} }) {
30
+ bindStart (message) {
31
+ const { authority, options, headers = {} } = message
54
32
  const sessionDetails = extractSessionDetails(authority, options)
55
33
  const path = headers[HTTP2_HEADER_PATH] || '/'
56
34
  const pathname = path.split(/[?#]/)[0]
@@ -75,7 +53,7 @@ class Http2ClientPlugin extends ClientPlugin {
75
53
  metrics: {
76
54
  [CLIENT_PORT_KEY]: parseInt(sessionDetails.port)
77
55
  }
78
- })
56
+ }, false)
79
57
 
80
58
  // TODO: Figure out a better way to do this for any span.
81
59
  if (!allowed) {
@@ -88,14 +66,53 @@ class Http2ClientPlugin extends ClientPlugin {
88
66
  this.tracer.inject(span, HTTP_HEADERS, headers)
89
67
  }
90
68
 
91
- analyticsSampler.sample(span, this.config.measured)
69
+ message.parentStore = store
70
+ message.currentStore = { ...store, span }
71
+
72
+ return message.currentStore
73
+ }
74
+
75
+ bindAsyncStart ({ eventName, eventData, currentStore, parentStore }) {
76
+ switch (eventName) {
77
+ case 'response':
78
+ this._onResponse(currentStore, eventData)
79
+ return parentStore
80
+ case 'error':
81
+ this._onError(currentStore, eventData)
82
+ return parentStore
83
+ case 'close':
84
+ this._onClose(currentStore, eventData)
85
+ return parentStore
86
+ }
92
87
 
93
- this.enter(span, store)
88
+ return storage.getStore()
94
89
  }
95
90
 
96
91
  configure (config) {
97
92
  return super.configure(normalizeConfig(config))
98
93
  }
94
+
95
+ _onResponse (store, headers) {
96
+ const status = headers && headers[HTTP2_HEADER_STATUS]
97
+
98
+ store.span.setTag(HTTP_STATUS_CODE, status)
99
+
100
+ if (!this.config.validateStatus(status)) {
101
+ storage.run(store, () => this.addError())
102
+ }
103
+
104
+ addHeaderTags(store.span, headers, HTTP_RESPONSE_HEADERS, this.config)
105
+ }
106
+
107
+ _onError ({ span }, error) {
108
+ span.setTag('error', error)
109
+ span.finish()
110
+ }
111
+
112
+ _onClose ({ span }) {
113
+ this.tagPeerService(span)
114
+ span.finish()
115
+ }
99
116
  }
100
117
 
101
118
  function extractSessionDetails (authority, options) {
@@ -2,12 +2,14 @@
2
2
 
3
3
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
4
  const { encodePathwayContext } = require('../../dd-trace/src/datastreams/pathway')
5
+ const BOOTSTRAP_SERVERS_KEY = 'messaging.kafka.bootstrap.servers'
5
6
 
6
7
  class KafkajsProducerPlugin extends ProducerPlugin {
7
8
  static get id () { return 'kafkajs' }
8
9
  static get operation () { return 'produce' }
10
+ static get peerServicePrecursors () { return [BOOTSTRAP_SERVERS_KEY] }
9
11
 
10
- start ({ topic, messages }) {
12
+ start ({ topic, messages, bootstrapServers }) {
11
13
  let pathwayCtx
12
14
  if (this.config.dsmEnabled) {
13
15
  const dataStreamsContext = this.tracer
@@ -24,6 +26,9 @@ class KafkajsProducerPlugin extends ProducerPlugin {
24
26
  'kafka.batch_size': messages.length
25
27
  }
26
28
  })
29
+ if (bootstrapServers) {
30
+ span.setTag(BOOTSTRAP_SERVERS_KEY, bootstrapServers)
31
+ }
27
32
  for (const message of messages) {
28
33
  if (typeof message === 'object') {
29
34
  if (this.config.dsmEnabled) message.headers['dd-pathway-ctx'] = pathwayCtx
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const DogStatsDClient = require('../../dd-trace/src/dogstatsd')
3
+ const { DogStatsDClient, NoopDogStatsDClient } = require('../../dd-trace/src/dogstatsd')
4
4
  const ExternalLogger = require('../../dd-trace/src/external-logger/src')
5
5
 
6
6
  const FLUSH_INTERVAL = 10 * 1000
@@ -10,15 +10,19 @@ let logger = null
10
10
  let interval = null
11
11
 
12
12
  module.exports.init = function (tracerConfig) {
13
- metrics = new DogStatsDClient({
14
- host: tracerConfig.dogstatsd.hostname,
15
- port: tracerConfig.dogstatsd.port,
16
- tags: [
17
- `service:${tracerConfig.tags.service}`,
18
- `env:${tracerConfig.tags.env}`,
19
- `version:${tracerConfig.tags.version}`
20
- ]
21
- })
13
+ if (tracerConfig.dogstatsd) {
14
+ metrics = new DogStatsDClient({
15
+ host: tracerConfig.dogstatsd.hostname,
16
+ port: tracerConfig.dogstatsd.port,
17
+ tags: [
18
+ `service:${tracerConfig.tags.service}`,
19
+ `env:${tracerConfig.tags.env}`,
20
+ `version:${tracerConfig.tags.version}`
21
+ ]
22
+ })
23
+ } else {
24
+ metrics = new NoopDogStatsDClient()
25
+ }
22
26
 
23
27
  logger = new ExternalLogger({
24
28
  ddsource: 'openai',
@@ -156,7 +156,7 @@ function isMoreSpecificThan (routeA, routeB) {
156
156
  }
157
157
 
158
158
  function routeIsRegex (route) {
159
- return route.includes('(/') && route.includes('/)')
159
+ return route.includes('(/')
160
160
  }
161
161
 
162
162
  module.exports = RouterPlugin
@@ -5,6 +5,9 @@ const { COMMAND_INJECTION } = require('../vulnerabilities')
5
5
  class CommandInjectionAnalyzer extends InjectionAnalyzer {
6
6
  constructor () {
7
7
  super(COMMAND_INJECTION)
8
+ }
9
+
10
+ onConfigure () {
8
11
  this.addSub('datadog:child_process:execution:start', ({ command }) => this.analyze(command))
9
12
  }
10
13
  }
@@ -9,7 +9,13 @@ class CookieAnalyzer extends Analyzer {
9
9
  constructor (type, propertyToBeSafe) {
10
10
  super(type)
11
11
  this.propertyToBeSafe = propertyToBeSafe.toLowerCase()
12
- this.addSub('datadog:iast:set-cookie', (cookieInfo) => this.analyze(cookieInfo))
12
+ }
13
+
14
+ onConfigure () {
15
+ this.addSub(
16
+ { channelName: 'datadog:iast:set-cookie', moduleName: 'http' },
17
+ (cookieInfo) => this.analyze(cookieInfo)
18
+ )
13
19
  }
14
20
 
15
21
  _isVulnerable ({ cookieProperties, cookieValue }) {
@@ -5,6 +5,9 @@ const { LDAP_INJECTION } = require('../vulnerabilities')
5
5
  class LdapInjectionAnalyzer extends InjectionAnalyzer {
6
6
  constructor () {
7
7
  super(LDAP_INJECTION)
8
+ }
9
+
10
+ onConfigure () {
8
11
  this.addSub('datadog:ldapjs:client:search', ({ base, filter }) => this.analyzeAll(base, filter))
9
12
  }
10
13
  }
@@ -1,9 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const path = require('path')
4
+
5
+ const InjectionAnalyzer = require('./injection-analyzer')
4
6
  const { getIastContext } = require('../iast-context')
5
7
  const { storage } = require('../../../../../datadog-core')
6
- const InjectionAnalyzer = require('./injection-analyzer')
7
8
  const { PATH_TRAVERSAL } = require('../vulnerabilities')
8
9
 
9
10
  const ignoredOperations = ['dir.close', 'close']
@@ -11,7 +12,23 @@ const ignoredOperations = ['dir.close', 'close']
11
12
  class PathTraversalAnalyzer extends InjectionAnalyzer {
12
13
  constructor () {
13
14
  super(PATH_TRAVERSAL)
14
- this.addSub('apm:fs:operation:start', obj => {
15
+
16
+ this.exclusionList = [
17
+ path.join('node_modules', 'send') + path.sep
18
+ ]
19
+
20
+ this.internalExclusionList = [
21
+ 'node:fs',
22
+ 'node:internal/fs',
23
+ 'node:internal\\fs',
24
+ 'fs.js',
25
+ 'internal/fs',
26
+ 'internal\\fs'
27
+ ]
28
+ }
29
+
30
+ onConfigure () {
31
+ this.addSub('apm:fs:operation:start', (obj) => {
15
32
  if (ignoredOperations.includes(obj.operation)) return
16
33
 
17
34
  const pathArguments = []
@@ -44,19 +61,6 @@ class PathTraversalAnalyzer extends InjectionAnalyzer {
44
61
  }
45
62
  this.analyze(pathArguments)
46
63
  })
47
-
48
- this.exclusionList = [
49
- path.join('node_modules', 'send') + path.sep
50
- ]
51
-
52
- this.internalExclusionList = [
53
- 'node:fs',
54
- 'node:internal/fs',
55
- 'node:internal\\fs',
56
- 'fs.js',
57
- 'internal/fs',
58
- 'internal\\fs'
59
- ]
60
64
  }
61
65
 
62
66
  _isExcluded (location) {
@@ -13,6 +13,9 @@ const EXCLUDED_PATHS = getNodeModulesPaths('mysql2', 'sequelize')
13
13
  class SqlInjectionAnalyzer extends InjectionAnalyzer {
14
14
  constructor () {
15
15
  super(SQL_INJECTION)
16
+ }
17
+
18
+ onConfigure () {
16
19
  this.addSub('apm:mysql:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
17
20
  this.addSub('apm:mysql2:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
18
21
  this.addSub('apm:pg:query:start', ({ query }) => this.analyze(query.text, 'POSTGRES'))
@@ -41,10 +44,9 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
41
44
 
42
45
  analyze (value, dialect) {
43
46
  const store = storage.getStore()
44
-
45
47
  if (!(store && store.sqlAnalyzed)) {
46
48
  const iastContext = getIastContext(store)
47
- if (store && !iastContext) return
49
+ if (this._isInvalidContext(store, iastContext)) return
48
50
  this._reportIfVulnerable(value, iastContext, dialect)
49
51
  }
50
52
  }
@@ -66,6 +68,7 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
66
68
  addVulnerability(context, vulnerability)
67
69
  }
68
70
  }
71
+
69
72
  _getExcludedPaths () {
70
73
  return EXCLUDED_PATHS
71
74
  }
@@ -6,7 +6,9 @@ const { SSRF } = require('../vulnerabilities')
6
6
  class SSRFAnalyzer extends InjectionAnalyzer {
7
7
  constructor () {
8
8
  super(SSRF)
9
+ }
9
10
 
11
+ onConfigure () {
10
12
  this.addSub('apm:http:client:request:start', ({ args }) => {
11
13
  if (typeof args.originalUrl === 'string') {
12
14
  this.analyze(args.originalUrl)
@@ -4,14 +4,16 @@ const InjectionAnalyzer = require('./injection-analyzer')
4
4
  const { UNVALIDATED_REDIRECT } = require('../vulnerabilities')
5
5
  const { getNodeModulesPaths } = require('../path-line')
6
6
  const { getRanges } = require('../taint-tracking/operations')
7
- const { HTTP_REQUEST_HEADER_VALUE } = require('../taint-tracking/origin-types')
7
+ const { HTTP_REQUEST_HEADER_VALUE } = require('../taint-tracking/source-types')
8
8
 
9
9
  const EXCLUDED_PATHS = getNodeModulesPaths('express/lib/response.js')
10
10
 
11
11
  class UnvalidatedRedirectAnalyzer extends InjectionAnalyzer {
12
12
  constructor () {
13
13
  super(UNVALIDATED_REDIRECT)
14
+ }
14
15
 
16
+ onConfigure () {
15
17
  this.addSub('datadog:http:server:response:set-header:finish', ({ name, value }) => this.analyze(name, value))
16
18
  }
17
19
 
@@ -1,33 +1,18 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../../../src/plugins/plugin')
4
3
  const { storage } = require('../../../../../datadog-core')
5
- const iastLog = require('../iast-log')
6
4
  const { getFirstNonDDPathAndLine } = require('../path-line')
7
5
  const { addVulnerability } = require('../vulnerability-reporter')
8
6
  const { getIastContext } = require('../iast-context')
9
7
  const overheadController = require('../overhead-controller')
8
+ const { SinkIastPlugin } = require('../iast-plugin')
10
9
 
11
- class Analyzer extends Plugin {
10
+ class Analyzer extends SinkIastPlugin {
12
11
  constructor (type) {
13
12
  super()
14
13
  this._type = type
15
14
  }
16
15
 
17
- _wrapHandler (handler) {
18
- return (message, name) => {
19
- try {
20
- handler(message, name)
21
- } catch (e) {
22
- iastLog.errorAndPublish(e)
23
- }
24
- }
25
- }
26
-
27
- addSub (channelName, handler) {
28
- super.addSub(channelName, this._wrapHandler(handler))
29
- }
30
-
31
16
  _isVulnerable (value, context) {
32
17
  return false
33
18
  }
@@ -64,17 +49,23 @@ class Analyzer extends Plugin {
64
49
 
65
50
  _getExcludedPaths () {}
66
51
 
52
+ _isInvalidContext (store, iastContext) {
53
+ return store && !iastContext
54
+ }
55
+
67
56
  analyze (value) {
68
57
  const store = storage.getStore()
69
58
  const iastContext = getIastContext(store)
70
- if (store && !iastContext) return
59
+ if (this._isInvalidContext(store, iastContext)) return
60
+
71
61
  this._reportIfVulnerable(value, iastContext)
72
62
  }
73
63
 
74
64
  analyzeAll (...values) {
75
65
  const store = storage.getStore()
76
66
  const iastContext = getIastContext(store)
77
- if (store && !iastContext) return
67
+ if (this._isInvalidContext(store, iastContext)) return
68
+
78
69
  for (let i = 0; i < values.length; i++) {
79
70
  const value = values[i]
80
71
  if (this._isVulnerable(value, iastContext)) {
@@ -119,6 +110,14 @@ class Analyzer extends Plugin {
119
110
  }
120
111
  return hash
121
112
  }
113
+
114
+ addSub (iastSubOrChannelName, handler) {
115
+ const iastSub = typeof iastSubOrChannelName === 'string'
116
+ ? { channelName: iastSubOrChannelName }
117
+ : iastSubOrChannelName
118
+
119
+ super.addSub({ tag: this._type, ...iastSub }, handler)
120
+ }
122
121
  }
123
122
 
124
123
  module.exports = Analyzer
@@ -14,6 +14,9 @@ const INSECURE_CIPHERS = new Set([
14
14
  class WeakCipherAnalyzer extends Analyzer {
15
15
  constructor () {
16
16
  super(WEAK_CIPHER)
17
+ }
18
+
19
+ onConfigure () {
17
20
  this.addSub('datadog:crypto:cipher:start', ({ algorithm }) => this.analyze(algorithm))
18
21
  }
19
22
 
@@ -25,6 +25,9 @@ const EXCLUDED_PATHS_FROM_STACK = [
25
25
  class WeakHashAnalyzer extends Analyzer {
26
26
  constructor () {
27
27
  super(WEAK_HASH)
28
+ }
29
+
30
+ onConfigure () {
28
31
  this.addSub('datadog:crypto:hashing:start', ({ algorithm }) => this.analyze(algorithm))
29
32
  }
30
33
 
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const log = require('../../log')
4
- const telemetryLogs = require('./telemetry/logs')
4
+ const telemetryLogs = require('./telemetry/log')
5
5
  const { calculateDDBasePath } = require('../../util')
6
6
 
7
7
  const ddBasePath = calculateDDBasePath(__dirname)