dd-trace 4.20.0 → 4.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +29 -0
  3. package/package.json +8 -7
  4. package/packages/datadog-instrumentations/src/aerospike.js +47 -0
  5. package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
  6. package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
  7. package/packages/datadog-instrumentations/src/graphql.js +18 -4
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
  9. package/packages/datadog-instrumentations/src/http/client.js +10 -0
  10. package/packages/datadog-instrumentations/src/jest.js +11 -5
  11. package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
  12. package/packages/datadog-instrumentations/src/next.js +18 -6
  13. package/packages/datadog-instrumentations/src/restify.js +1 -1
  14. package/packages/datadog-instrumentations/src/rhea.js +15 -9
  15. package/packages/datadog-plugin-aerospike/src/index.js +113 -0
  16. package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
  17. package/packages/datadog-plugin-http/src/client.js +19 -2
  18. package/packages/datadog-plugin-kafkajs/src/consumer.js +51 -0
  19. package/packages/datadog-plugin-kafkajs/src/producer.js +55 -0
  20. package/packages/datadog-plugin-next/src/index.js +40 -14
  21. package/packages/dd-trace/src/appsec/activation.js +29 -0
  22. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  23. package/packages/dd-trace/src/appsec/api_security_sampler.js +48 -0
  24. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
  25. package/packages/dd-trace/src/appsec/blocking.js +95 -43
  26. package/packages/dd-trace/src/appsec/channels.js +4 -1
  27. package/packages/dd-trace/src/appsec/graphql.js +146 -0
  28. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  29. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
  30. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
  31. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
  32. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
  33. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
  34. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
  35. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
  36. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
  37. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
  38. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
  39. package/packages/dd-trace/src/appsec/index.js +32 -31
  40. package/packages/dd-trace/src/appsec/recommended.json +1395 -2
  41. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
  42. package/packages/dd-trace/src/appsec/remote_config/index.js +36 -15
  43. package/packages/dd-trace/src/appsec/reporter.js +19 -0
  44. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
  45. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
  46. package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
  47. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +17 -1
  48. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +75 -56
  49. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +15 -9
  50. package/packages/dd-trace/src/config.js +36 -2
  51. package/packages/dd-trace/src/datastreams/processor.js +107 -12
  52. package/packages/dd-trace/src/noop/proxy.js +4 -0
  53. package/packages/dd-trace/src/opentracing/span.js +2 -0
  54. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -1
  55. package/packages/dd-trace/src/plugins/index.js +1 -0
  56. package/packages/dd-trace/src/plugins/util/git.js +2 -2
  57. package/packages/dd-trace/src/plugins/util/test.js +3 -2
  58. package/packages/dd-trace/src/plugins/util/user-provided-git.js +3 -2
  59. package/packages/dd-trace/src/profiler.js +5 -3
  60. package/packages/dd-trace/src/profiling/config.js +8 -0
  61. package/packages/dd-trace/src/profiling/profiler.js +17 -10
  62. package/packages/dd-trace/src/profiling/profilers/events.js +181 -83
  63. package/packages/dd-trace/src/profiling/profilers/shared.js +33 -3
  64. package/packages/dd-trace/src/profiling/profilers/space.js +2 -1
  65. package/packages/dd-trace/src/profiling/profilers/wall.js +17 -12
  66. package/packages/dd-trace/src/proxy.js +25 -1
  67. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
  68. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  69. package/packages/dd-trace/src/spanleak.js +98 -0
  70. package/packages/dd-trace/src/startup-log.js +7 -1
  71. package/packages/dd-trace/src/telemetry/dependencies.js +55 -9
  72. package/packages/dd-trace/src/telemetry/index.js +135 -43
  73. package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
  74. package/packages/dd-trace/src/telemetry/send-data.js +47 -5
  75. package/packages/dd-trace/src/tracer.js +4 -0
  76. package/scripts/install_plugin_modules.js +11 -3
@@ -23,96 +23,90 @@ const NUMERIC_LITERAL =
23
23
  })`
24
24
  const ORACLE_ESCAPED_LITERAL = 'q\'<.*?>\'|q\'\\(.*?\\)\'|q\'\\{.*?\\}\'|q\'\\[.*?\\]\'|q\'(?<ESCAPE>.).*?\\k<ESCAPE>\''
25
25
 
26
- class SqlSensitiveAnalyzer {
27
- constructor () {
28
- this._patterns = {
29
- ANSI: new RegExp( // Default
30
- [
31
- NUMERIC_LITERAL,
32
- STRING_LITERAL,
33
- LINE_COMMENT,
34
- BLOCK_COMMENT
35
- ].join('|'),
36
- 'gmi'
37
- ),
38
- MYSQL: new RegExp(
39
- [
40
- NUMERIC_LITERAL,
41
- MYSQL_STRING_LITERAL,
42
- LINE_COMMENT,
43
- BLOCK_COMMENT
44
- ].join('|'),
45
- 'gmi'
46
- ),
47
- POSTGRES: new RegExp(
48
- [
49
- NUMERIC_LITERAL,
50
- POSTGRESQL_ESCAPED_LITERAL,
51
- STRING_LITERAL,
52
- LINE_COMMENT,
53
- BLOCK_COMMENT
54
- ].join('|'),
55
- 'gmi'
56
- ),
57
- ORACLE: new RegExp([
58
- NUMERIC_LITERAL,
59
- ORACLE_ESCAPED_LITERAL,
60
- STRING_LITERAL,
61
- LINE_COMMENT,
62
- BLOCK_COMMENT
63
- ].join('|'),
64
- 'gmi')
65
- }
66
- this._patterns.SQLITE = this._patterns.MYSQL
67
- this._patterns.MARIADB = this._patterns.MYSQL
68
- }
26
+ const patterns = {
27
+ ANSI: new RegExp( // Default
28
+ [
29
+ NUMERIC_LITERAL,
30
+ STRING_LITERAL,
31
+ LINE_COMMENT,
32
+ BLOCK_COMMENT
33
+ ].join('|'),
34
+ 'gmi'
35
+ ),
36
+ MYSQL: new RegExp(
37
+ [
38
+ NUMERIC_LITERAL,
39
+ MYSQL_STRING_LITERAL,
40
+ LINE_COMMENT,
41
+ BLOCK_COMMENT
42
+ ].join('|'),
43
+ 'gmi'
44
+ ),
45
+ POSTGRES: new RegExp(
46
+ [
47
+ NUMERIC_LITERAL,
48
+ POSTGRESQL_ESCAPED_LITERAL,
49
+ STRING_LITERAL,
50
+ LINE_COMMENT,
51
+ BLOCK_COMMENT
52
+ ].join('|'),
53
+ 'gmi'
54
+ ),
55
+ ORACLE: new RegExp([
56
+ NUMERIC_LITERAL,
57
+ ORACLE_ESCAPED_LITERAL,
58
+ STRING_LITERAL,
59
+ LINE_COMMENT,
60
+ BLOCK_COMMENT
61
+ ].join('|'),
62
+ 'gmi')
63
+ }
64
+ patterns.SQLITE = patterns.MYSQL
65
+ patterns.MARIADB = patterns.MYSQL
69
66
 
70
- extractSensitiveRanges (evidence) {
71
- try {
72
- let pattern = this._patterns[evidence.dialect]
73
- if (!pattern) {
74
- pattern = this._patterns['ANSI']
75
- }
76
- pattern.lastIndex = 0
77
- const tokens = []
67
+ module.exports = function extractSensitiveRanges (evidence) {
68
+ try {
69
+ let pattern = patterns[evidence.dialect]
70
+ if (!pattern) {
71
+ pattern = patterns['ANSI']
72
+ }
73
+ pattern.lastIndex = 0
74
+ const tokens = []
78
75
 
79
- let regexResult = pattern.exec(evidence.value)
80
- while (regexResult != null) {
81
- let start = regexResult.index
82
- let end = regexResult.index + regexResult[0].length
83
- const startChar = evidence.value.charAt(start)
84
- if (startChar === '\'' || startChar === '"') {
85
- start++
86
- end--
87
- } else if (end > start + 1) {
88
- const nextChar = evidence.value.charAt(start + 1)
89
- if (startChar === '/' && nextChar === '*') {
90
- start += 2
91
- end -= 2
92
- } else if (startChar === '-' && startChar === nextChar) {
93
- start += 2
94
- } else if (startChar.toLowerCase() === 'q' && nextChar === '\'') {
95
- start += 3
96
- end -= 2
97
- } else if (startChar === '$') {
98
- const match = regexResult[0]
99
- const size = match.indexOf('$', 1) + 1
100
- if (size > 1) {
101
- start += size
102
- end -= size
103
- }
76
+ let regexResult = pattern.exec(evidence.value)
77
+ while (regexResult != null) {
78
+ let start = regexResult.index
79
+ let end = regexResult.index + regexResult[0].length
80
+ const startChar = evidence.value.charAt(start)
81
+ if (startChar === '\'' || startChar === '"') {
82
+ start++
83
+ end--
84
+ } else if (end > start + 1) {
85
+ const nextChar = evidence.value.charAt(start + 1)
86
+ if (startChar === '/' && nextChar === '*') {
87
+ start += 2
88
+ end -= 2
89
+ } else if (startChar === '-' && startChar === nextChar) {
90
+ start += 2
91
+ } else if (startChar.toLowerCase() === 'q' && nextChar === '\'') {
92
+ start += 3
93
+ end -= 2
94
+ } else if (startChar === '$') {
95
+ const match = regexResult[0]
96
+ const size = match.indexOf('$', 1) + 1
97
+ if (size > 1) {
98
+ start += size
99
+ end -= size
104
100
  }
105
101
  }
106
-
107
- tokens.push({ start, end })
108
- regexResult = pattern.exec(evidence.value)
109
102
  }
110
- return tokens
111
- } catch (e) {
112
- iastLog.debug(e)
103
+
104
+ tokens.push({ start, end })
105
+ regexResult = pattern.exec(evidence.value)
113
106
  }
114
- return []
107
+ return tokens
108
+ } catch (e) {
109
+ iastLog.debug(e)
115
110
  }
111
+ return []
116
112
  }
117
-
118
- module.exports = SqlSensitiveAnalyzer
@@ -4,46 +4,37 @@ const iastLog = require('../../../iast-log')
4
4
 
5
5
  const AUTHORITY = '^(?:[^:]+:)?//([^@]+)@'
6
6
  const QUERY_FRAGMENT = '[?#&]([^=&;]+)=([^?#&]+)'
7
+ const pattern = new RegExp([AUTHORITY, QUERY_FRAGMENT].join('|'), 'gmi')
8
+
9
+ module.exports = function extractSensitiveRanges (evidence) {
10
+ try {
11
+ const ranges = []
12
+ let regexResult = pattern.exec(evidence.value)
13
+
14
+ while (regexResult != null) {
15
+ if (typeof regexResult[1] === 'string') {
16
+ // AUTHORITY regex match always ends by group + @
17
+ // it means that the match last chars - 1 are always the group
18
+ const end = regexResult.index + (regexResult[0].length - 1)
19
+ const start = end - regexResult[1].length
20
+ ranges.push({ start, end })
21
+ }
7
22
 
8
- class UrlSensitiveAnalyzer {
9
- constructor () {
10
- this._pattern = new RegExp([AUTHORITY, QUERY_FRAGMENT].join('|'), 'gmi')
11
- }
12
-
13
- extractSensitiveRanges (evidence) {
14
- try {
15
- const pattern = this._pattern
16
-
17
- const ranges = []
18
- let regexResult = pattern.exec(evidence.value)
19
-
20
- while (regexResult != null) {
21
- if (typeof regexResult[1] === 'string') {
22
- // AUTHORITY regex match always ends by group + @
23
- // it means that the match last chars - 1 are always the group
24
- const end = regexResult.index + (regexResult[0].length - 1)
25
- const start = end - regexResult[1].length
26
- ranges.push({ start, end })
27
- }
28
-
29
- if (typeof regexResult[3] === 'string') {
30
- // QUERY_FRAGMENT regex always ends with the group
31
- // it means that the match last chars are always the group
32
- const end = regexResult.index + regexResult[0].length
33
- const start = end - regexResult[3].length
34
- ranges.push({ start, end })
35
- }
36
-
37
- regexResult = pattern.exec(evidence.value)
23
+ if (typeof regexResult[3] === 'string') {
24
+ // QUERY_FRAGMENT regex always ends with the group
25
+ // it means that the match last chars are always the group
26
+ const end = regexResult.index + regexResult[0].length
27
+ const start = end - regexResult[3].length
28
+ ranges.push({ start, end })
38
29
  }
39
30
 
40
- return ranges
41
- } catch (e) {
42
- iastLog.debug(e)
31
+ regexResult = pattern.exec(evidence.value)
43
32
  }
44
33
 
45
- return []
34
+ return ranges
35
+ } catch (e) {
36
+ iastLog.debug(e)
46
37
  }
47
- }
48
38
 
49
- module.exports = UrlSensitiveAnalyzer
39
+ return []
40
+ }
@@ -5,11 +5,12 @@ const vulnerabilities = require('../../vulnerabilities')
5
5
 
6
6
  const { contains, intersects, remove } = require('./range-utils')
7
7
 
8
- const CommandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
9
- const JsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
10
- const LdapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
11
- const SqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
12
- const UrlSensitiveAnalyzer = require('./sensitive-analyzers/url-sensitive-analyzer')
8
+ const commandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
9
+ const headerSensitiveAnalyzer = require('./sensitive-analyzers/header-sensitive-analyzer')
10
+ const jsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
11
+ const ldapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
12
+ const sqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
13
+ const urlSensitiveAnalyzer = require('./sensitive-analyzers/url-sensitive-analyzer')
13
14
 
14
15
  const { DEFAULT_IAST_REDACTION_NAME_PATTERN, DEFAULT_IAST_REDACTION_VALUE_PATTERN } = require('./sensitive-regex')
15
16
 
@@ -21,13 +22,15 @@ class SensitiveHandler {
21
22
  this._valuePattern = new RegExp(DEFAULT_IAST_REDACTION_VALUE_PATTERN, 'gmi')
22
23
 
23
24
  this._sensitiveAnalyzers = new Map()
24
- this._sensitiveAnalyzers.set(vulnerabilities.COMMAND_INJECTION, new CommandSensitiveAnalyzer())
25
- this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, new JsonSensitiveAnalyzer())
26
- this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, new LdapSensitiveAnalyzer())
27
- this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION, new SqlSensitiveAnalyzer())
28
- const urlSensitiveAnalyzer = new UrlSensitiveAnalyzer()
25
+ this._sensitiveAnalyzers.set(vulnerabilities.COMMAND_INJECTION, commandSensitiveAnalyzer)
26
+ this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, jsonSensitiveAnalyzer)
27
+ this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, ldapSensitiveAnalyzer)
28
+ this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION, sqlSensitiveAnalyzer)
29
29
  this._sensitiveAnalyzers.set(vulnerabilities.SSRF, urlSensitiveAnalyzer)
30
30
  this._sensitiveAnalyzers.set(vulnerabilities.UNVALIDATED_REDIRECT, urlSensitiveAnalyzer)
31
+ this._sensitiveAnalyzers.set(vulnerabilities.HEADER_INJECTION, (evidence) => {
32
+ return headerSensitiveAnalyzer(evidence, this._namePattern, this._valuePattern)
33
+ })
31
34
  }
32
35
 
33
36
  isSensibleName (name) {
@@ -47,7 +50,7 @@ class SensitiveHandler {
47
50
  scrubEvidence (vulnerabilityType, evidence, sourcesIndexes, sources) {
48
51
  const sensitiveAnalyzer = this._sensitiveAnalyzers.get(vulnerabilityType)
49
52
  if (sensitiveAnalyzer) {
50
- const sensitiveRanges = sensitiveAnalyzer.extractSensitiveRanges(evidence)
53
+ const sensitiveRanges = sensitiveAnalyzer(evidence)
51
54
  return this.toRedactedJson(evidence, sensitiveRanges, sourcesIndexes, sources)
52
55
  }
53
56
  return null
@@ -1,6 +1,7 @@
1
1
  module.exports = {
2
2
  COMMAND_INJECTION: 'COMMAND_INJECTION',
3
3
  HARDCODED_SECRET: 'HARDCODED_SECRET',
4
+ HEADER_INJECTION: 'HEADER_INJECTION',
4
5
  HSTS_HEADER_MISSING: 'HSTS_HEADER_MISSING',
5
6
  INSECURE_COOKIE: 'INSECURE_COOKIE',
6
7
  LDAP_INJECTION: 'LDAP_INJECTION',
@@ -6,7 +6,6 @@ const remoteConfig = require('./remote_config')
6
6
  const {
7
7
  bodyParser,
8
8
  cookieParser,
9
- graphqlFinishExecute,
10
9
  incomingHttpRequestStart,
11
10
  incomingHttpRequestEnd,
12
11
  passportVerify,
@@ -18,12 +17,14 @@ const waf = require('./waf')
18
17
  const addresses = require('./addresses')
19
18
  const Reporter = require('./reporter')
20
19
  const appsecTelemetry = require('./telemetry')
20
+ const apiSecuritySampler = require('./api_security_sampler')
21
21
  const web = require('../plugins/util/web')
22
22
  const { extractIp } = require('../plugins/util/ip_extractor')
23
23
  const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
24
24
  const { block, setTemplates } = require('./blocking')
25
25
  const { passportTrackEvent } = require('./passport')
26
26
  const { storage } = require('../../../datadog-core')
27
+ const graphql = require('./graphql')
27
28
 
28
29
  let isEnabled = false
29
30
  let config
@@ -33,6 +34,7 @@ function enable (_config) {
33
34
 
34
35
  try {
35
36
  appsecTelemetry.enable(_config.telemetry)
37
+ graphql.enable()
36
38
 
37
39
  setTemplates(_config)
38
40
 
@@ -42,6 +44,8 @@ function enable (_config) {
42
44
 
43
45
  Reporter.setRateLimit(_config.appsec.rateLimit)
44
46
 
47
+ apiSecuritySampler.configure(_config.appsec)
48
+
45
49
  incomingHttpRequestStart.subscribe(incomingHttpStartTranslator)
46
50
  incomingHttpRequestEnd.subscribe(incomingHttpEndTranslator)
47
51
  bodyParser.subscribe(onRequestBodyParsed)
@@ -49,7 +53,6 @@ function enable (_config) {
49
53
  nextQueryParsed.subscribe(onRequestQueryParsed)
50
54
  queryParser.subscribe(onRequestQueryParsed)
51
55
  cookieParser.subscribe(onRequestCookieParser)
52
- graphqlFinishExecute.subscribe(onGraphqlFinishExecute)
53
56
 
54
57
  if (_config.appsec.eventTracking.enabled) {
55
58
  passportVerify.subscribe(onPassportVerify)
@@ -80,17 +83,21 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
80
83
  const requestHeaders = Object.assign({}, req.headers)
81
84
  delete requestHeaders.cookie
82
85
 
83
- const payload = {
86
+ const persistent = {
84
87
  [addresses.HTTP_INCOMING_URL]: req.url,
85
88
  [addresses.HTTP_INCOMING_HEADERS]: requestHeaders,
86
89
  [addresses.HTTP_INCOMING_METHOD]: req.method
87
90
  }
88
91
 
89
92
  if (clientIp) {
90
- payload[addresses.HTTP_CLIENT_IP] = clientIp
93
+ persistent[addresses.HTTP_CLIENT_IP] = clientIp
94
+ }
95
+
96
+ if (apiSecuritySampler.sampleRequest()) {
97
+ persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
91
98
  }
92
99
 
93
- const actions = waf.run(payload, req)
100
+ const actions = waf.run({ persistent }, req)
94
101
 
95
102
  handleResults(actions, req, res, rootSpan, abortController)
96
103
  }
@@ -100,32 +107,32 @@ function incomingHttpEndTranslator ({ req, res }) {
100
107
  const responseHeaders = Object.assign({}, res.getHeaders())
101
108
  delete responseHeaders['set-cookie']
102
109
 
103
- const payload = {
104
- [addresses.HTTP_INCOMING_RESPONSE_CODE]: res.statusCode,
110
+ const persistent = {
111
+ [addresses.HTTP_INCOMING_RESPONSE_CODE]: '' + res.statusCode,
105
112
  [addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders
106
113
  }
107
114
 
108
115
  // we need to keep this to support other body parsers
109
116
  // TODO: no need to analyze it if it was already done by the body-parser hook
110
117
  if (req.body !== undefined && req.body !== null) {
111
- payload[addresses.HTTP_INCOMING_BODY] = req.body
118
+ persistent[addresses.HTTP_INCOMING_BODY] = req.body
112
119
  }
113
120
 
114
121
  // TODO: temporary express instrumentation, will use express plugin later
115
122
  if (req.params && typeof req.params === 'object') {
116
- payload[addresses.HTTP_INCOMING_PARAMS] = req.params
123
+ persistent[addresses.HTTP_INCOMING_PARAMS] = req.params
117
124
  }
118
125
 
119
126
  // we need to keep this to support other cookie parsers
120
127
  if (req.cookies && typeof req.cookies === 'object') {
121
- payload[addresses.HTTP_INCOMING_COOKIES] = req.cookies
128
+ persistent[addresses.HTTP_INCOMING_COOKIES] = req.cookies
122
129
  }
123
130
 
124
131
  if (req.query && typeof req.query === 'object') {
125
- payload[addresses.HTTP_INCOMING_QUERY] = req.query
132
+ persistent[addresses.HTTP_INCOMING_QUERY] = req.query
126
133
  }
127
134
 
128
- waf.run(payload, req)
135
+ waf.run({ persistent }, req)
129
136
 
130
137
  waf.disposeContext(req)
131
138
 
@@ -144,7 +151,9 @@ function onRequestBodyParsed ({ req, res, body, abortController }) {
144
151
  if (!rootSpan) return
145
152
 
146
153
  const results = waf.run({
147
- [addresses.HTTP_INCOMING_BODY]: body
154
+ persistent: {
155
+ [addresses.HTTP_INCOMING_BODY]: body
156
+ }
148
157
  }, req)
149
158
 
150
159
  handleResults(results, req, res, rootSpan, abortController)
@@ -162,7 +171,9 @@ function onRequestQueryParsed ({ req, res, query, abortController }) {
162
171
  if (!rootSpan) return
163
172
 
164
173
  const results = waf.run({
165
- [addresses.HTTP_INCOMING_QUERY]: query
174
+ persistent: {
175
+ [addresses.HTTP_INCOMING_QUERY]: query
176
+ }
166
177
  }, req)
167
178
 
168
179
  handleResults(results, req, res, rootSpan, abortController)
@@ -175,7 +186,9 @@ function onRequestCookieParser ({ req, res, abortController, cookies }) {
175
186
  if (!rootSpan) return
176
187
 
177
188
  const results = waf.run({
178
- [addresses.HTTP_INCOMING_COOKIES]: cookies
189
+ persistent: {
190
+ [addresses.HTTP_INCOMING_COOKIES]: cookies
191
+ }
179
192
  }, req)
180
193
 
181
194
  handleResults(results, req, res, rootSpan, abortController)
@@ -183,7 +196,7 @@ function onRequestCookieParser ({ req, res, abortController, cookies }) {
183
196
 
184
197
  function onPassportVerify ({ credentials, user }) {
185
198
  const store = storage.getStore()
186
- const rootSpan = store && store.req && web.root(store.req)
199
+ const rootSpan = store?.req && web.root(store.req)
187
200
 
188
201
  if (!rootSpan) {
189
202
  log.warn('No rootSpan found in onPassportVerify')
@@ -193,20 +206,6 @@ function onPassportVerify ({ credentials, user }) {
193
206
  passportTrackEvent(credentials, user, rootSpan, config.appsec.eventTracking.mode)
194
207
  }
195
208
 
196
- function onGraphqlFinishExecute ({ context }) {
197
- const store = storage.getStore()
198
- const req = store?.req
199
-
200
- if (!req) return
201
-
202
- const resolvers = context?.resolvers
203
-
204
- if (!resolvers || typeof resolvers !== 'object') return
205
-
206
- // Don't collect blocking result because it only works in monitor mode.
207
- waf.run({ [addresses.HTTP_INCOMING_GRAPHQL_RESOLVERS]: resolvers }, req)
208
- }
209
-
210
209
  function handleResults (actions, req, res, rootSpan, abortController) {
211
210
  if (!actions || !req || !res || !rootSpan || !abortController) return
212
211
 
@@ -222,12 +221,14 @@ function disable () {
222
221
  RuleManager.clearAllRules()
223
222
 
224
223
  appsecTelemetry.disable()
224
+ graphql.disable()
225
225
 
226
226
  remoteConfig.disableWafUpdate()
227
227
 
228
+ apiSecuritySampler.disable()
229
+
228
230
  // Channel#unsubscribe() is undefined for non active channels
229
231
  if (bodyParser.hasSubscribers) bodyParser.unsubscribe(onRequestBodyParsed)
230
- if (graphqlFinishExecute.hasSubscribers) graphqlFinishExecute.unsubscribe(onGraphqlFinishExecute)
231
232
  if (incomingHttpRequestStart.hasSubscribers) incomingHttpRequestStart.unsubscribe(incomingHttpStartTranslator)
232
233
  if (incomingHttpRequestEnd.hasSubscribers) incomingHttpRequestEnd.unsubscribe(incomingHttpEndTranslator)
233
234
  if (queryParser.hasSubscribers) queryParser.unsubscribe(onRequestQueryParsed)