dd-trace 5.58.0 → 5.60.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 (179) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/ci/cypress/after-run.js +2 -0
  3. package/ci/cypress/after-spec.js +2 -0
  4. package/ci/cypress/plugin.js +2 -0
  5. package/ci/cypress/polyfills.js +2 -0
  6. package/ci/cypress/support.js +2 -0
  7. package/ci/init.js +2 -0
  8. package/index.d.ts +7 -0
  9. package/init.js +0 -2
  10. package/initialize.mjs +2 -0
  11. package/package.json +40 -8
  12. package/packages/datadog-code-origin/index.js +14 -9
  13. package/packages/datadog-instrumentations/src/apollo-server.js +14 -3
  14. package/packages/datadog-instrumentations/src/apollo.js +7 -10
  15. package/packages/datadog-instrumentations/src/avsc.js +2 -0
  16. package/packages/datadog-instrumentations/src/child_process.js +21 -42
  17. package/packages/datadog-instrumentations/src/cucumber.js +10 -8
  18. package/packages/datadog-instrumentations/src/cypress.js +2 -0
  19. package/packages/datadog-instrumentations/src/fastify.js +19 -1
  20. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  21. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  22. package/packages/datadog-instrumentations/src/hono.js +102 -0
  23. package/packages/datadog-instrumentations/src/langchain.js +21 -0
  24. package/packages/datadog-instrumentations/src/mocha/common.js +2 -0
  25. package/packages/datadog-instrumentations/src/mocha.js +2 -0
  26. package/packages/datadog-instrumentations/src/nyc.js +2 -0
  27. package/packages/datadog-instrumentations/src/openai.js +13 -114
  28. package/packages/datadog-instrumentations/src/orchestrion-config/index.js +32 -0
  29. package/packages/datadog-instrumentations/src/playwright.js +5 -1
  30. package/packages/datadog-instrumentations/src/protobufjs.js +2 -0
  31. package/packages/datadog-instrumentations/src/selenium.js +2 -0
  32. package/packages/datadog-instrumentations/src/vitest.js +2 -0
  33. package/packages/datadog-plugin-avsc/src/index.js +2 -0
  34. package/packages/datadog-plugin-avsc/src/schema_iterator.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +2 -0
  36. package/packages/datadog-plugin-child_process/src/index.js +30 -10
  37. package/packages/datadog-plugin-cypress/src/after-run.js +2 -0
  38. package/packages/datadog-plugin-cypress/src/after-spec.js +2 -0
  39. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +8 -3
  40. package/packages/datadog-plugin-cypress/src/index.js +2 -0
  41. package/packages/datadog-plugin-cypress/src/plugin.js +2 -0
  42. package/packages/datadog-plugin-cypress/src/support.js +4 -2
  43. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +3 -155
  44. package/packages/datadog-plugin-google-cloud-vertexai/src/utils.js +2 -0
  45. package/packages/datadog-plugin-graphql/src/utils.js +2 -0
  46. package/packages/datadog-plugin-hono/src/index.js +28 -0
  47. package/packages/datadog-plugin-jest/src/index.js +2 -0
  48. package/packages/datadog-plugin-jest/src/util.js +2 -0
  49. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -0
  50. package/packages/datadog-plugin-langchain/src/tracing.js +36 -4
  51. package/packages/datadog-plugin-nyc/src/index.js +2 -0
  52. package/packages/datadog-plugin-openai/src/stream-helpers.js +114 -0
  53. package/packages/datadog-plugin-openai/src/tracing.js +38 -0
  54. package/packages/datadog-plugin-oracledb/src/connection-parser.js +2 -0
  55. package/packages/datadog-plugin-protobufjs/src/index.js +2 -0
  56. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +2 -0
  57. package/packages/datadog-plugin-selenium/src/index.js +2 -0
  58. package/packages/datadog-plugin-vitest/src/index.js +2 -0
  59. package/packages/dd-trace/src/appsec/iast/iast-context.js +5 -1
  60. package/packages/dd-trace/src/appsec/iast/index.js +2 -0
  61. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  62. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +0 -2
  63. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -0
  64. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -0
  65. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
  66. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -3
  67. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +18 -11
  68. package/packages/dd-trace/src/appsec/rasp/utils.js +1 -1
  69. package/packages/dd-trace/src/appsec/recommended.json +88 -2
  70. package/packages/dd-trace/src/appsec/reporter.js +7 -19
  71. package/packages/dd-trace/src/appsec/stack_trace.js +11 -11
  72. package/packages/dd-trace/src/appsec/telemetry/common.js +1 -1
  73. package/packages/dd-trace/src/appsec/waf/index.js +20 -1
  74. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -2
  75. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -4
  76. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -0
  77. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -1
  78. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -0
  79. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -0
  80. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -0
  81. package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -0
  82. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +2 -0
  83. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +7 -3
  84. package/packages/dd-trace/src/config.js +4 -16
  85. package/packages/dd-trace/src/config_stable.js +2 -0
  86. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -0
  87. package/packages/dd-trace/src/datastreams/context.js +2 -0
  88. package/packages/dd-trace/src/datastreams/encoding.js +2 -0
  89. package/packages/dd-trace/src/datastreams/fnv.js +2 -0
  90. package/packages/dd-trace/src/datastreams/pathway.js +11 -9
  91. package/packages/dd-trace/src/datastreams/processor.js +8 -7
  92. package/packages/dd-trace/src/datastreams/schemas/schema.js +2 -0
  93. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +45 -36
  94. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +2 -0
  95. package/packages/dd-trace/src/datastreams/writer.js +2 -0
  96. package/packages/dd-trace/src/debugger/config.js +16 -0
  97. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -1
  98. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -6
  99. package/packages/dd-trace/src/debugger/devtools_client/index.js +13 -5
  100. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
  101. package/packages/dd-trace/src/debugger/devtools_client/log.js +19 -0
  102. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +9 -6
  103. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -1
  104. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +1 -1
  105. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +1 -1
  106. package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
  107. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  108. package/packages/dd-trace/src/debugger/index.js +48 -11
  109. package/packages/dd-trace/src/encode/tags-processors.js +2 -0
  110. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -0
  111. package/packages/dd-trace/src/exporters/common/util.js +2 -0
  112. package/packages/dd-trace/src/exporters/span-stats/index.js +2 -0
  113. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -0
  114. package/packages/dd-trace/src/external-logger/src/index.js +2 -0
  115. package/packages/dd-trace/src/git_metadata_tagger.js +2 -0
  116. package/packages/dd-trace/src/git_properties.js +2 -0
  117. package/packages/dd-trace/src/guardrails/index.js +3 -4
  118. package/packages/dd-trace/src/guardrails/log.js +2 -2
  119. package/packages/dd-trace/src/guardrails/telemetry.js +16 -14
  120. package/packages/dd-trace/src/guardrails/util.js +0 -2
  121. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +2 -0
  122. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +5 -0
  123. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/tool.js +15 -0
  124. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +36 -0
  125. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +47 -4
  126. package/packages/dd-trace/src/llmobs/tagger.js +10 -1
  127. package/packages/dd-trace/src/noop/dogstatsd.js +2 -0
  128. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -0
  129. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -0
  130. package/packages/dd-trace/src/payload-tagging/index.js +2 -0
  131. package/packages/dd-trace/src/payload-tagging/tagging.js +2 -0
  132. package/packages/dd-trace/src/plugins/apollo.js +2 -0
  133. package/packages/dd-trace/src/plugins/ci_plugin.js +8 -3
  134. package/packages/dd-trace/src/plugins/index.js +1 -0
  135. package/packages/dd-trace/src/plugins/util/ci.js +17 -7
  136. package/packages/dd-trace/src/plugins/util/env.js +2 -0
  137. package/packages/dd-trace/src/plugins/util/git.js +40 -5
  138. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +2 -0
  139. package/packages/dd-trace/src/plugins/util/llm.js +2 -0
  140. package/packages/dd-trace/src/plugins/util/serverless.js +2 -0
  141. package/packages/dd-trace/src/plugins/util/stacktrace.js +178 -50
  142. package/packages/dd-trace/src/plugins/util/tags.js +19 -1
  143. package/packages/dd-trace/src/plugins/util/test.js +9 -4
  144. package/packages/dd-trace/src/plugins/util/url.js +2 -0
  145. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -0
  146. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +4 -0
  147. package/packages/dd-trace/src/profiling/profiler.js +89 -70
  148. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -0
  149. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +2 -0
  150. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +2 -0
  151. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -0
  152. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +2 -0
  153. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +2 -0
  154. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +2 -0
  155. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +2 -0
  156. package/packages/dd-trace/src/profiling/profilers/events.js +2 -0
  157. package/packages/dd-trace/src/profiling/webspan-utils.js +2 -0
  158. package/packages/dd-trace/src/remote_config/capabilities.js +4 -1
  159. package/packages/dd-trace/src/remote_config/index.js +6 -0
  160. package/packages/dd-trace/src/service-naming/index.js +2 -0
  161. package/packages/dd-trace/src/service-naming/schemas/definition.js +2 -0
  162. package/packages/dd-trace/src/service-naming/schemas/util.js +2 -0
  163. package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +2 -0
  164. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -0
  165. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -0
  166. package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +2 -0
  167. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +2 -0
  168. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +2 -0
  169. package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +2 -0
  170. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -0
  171. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -0
  172. package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +2 -0
  173. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +2 -0
  174. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +2 -0
  175. package/packages/dd-trace/src/span_stats.js +2 -0
  176. package/packages/dd-trace/src/supported-configurations.json +2 -0
  177. package/packages/dd-trace/src/telemetry/send-data.js +2 -0
  178. package/register.js +4 -0
  179. package/version.js +0 -3
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  function extractModel (instance) {
2
4
  const model = instance.model || instance.resourcePath || instance.publisherModelEndpoint
3
5
  return model?.split('/').pop()
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  function extractErrorIntoSpanEvent (config, span, exc) {
2
4
  const attributes = {}
3
5
 
@@ -0,0 +1,28 @@
1
+ 'use strict'
2
+
3
+ const RouterPlugin = require('../../datadog-plugin-router/src')
4
+ const web = require('../../dd-trace/src/plugins/util/web')
5
+
6
+ class HonoPlugin extends RouterPlugin {
7
+ static get id () {
8
+ return 'hono'
9
+ }
10
+
11
+ constructor (...args) {
12
+ super(...args)
13
+
14
+ this.addSub('apm:hono:request:handle', ({ req }) => {
15
+ this.setFramework(req, 'hono', this.config)
16
+ })
17
+
18
+ this.addSub('apm:hono:request:route', ({ req, route }) => {
19
+ web.setRoute(req, route)
20
+ })
21
+
22
+ this.addSub('apm:hono:request:error', ({ req, error }) => {
23
+ web.addError(req, error)
24
+ })
25
+ }
26
+ }
27
+
28
+ module.exports = HonoPlugin
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
4
  const { storage } = require('../../datadog-core')
3
5
  const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { readFileSync } = require('fs')
2
4
  const { parse, extract } = require('jest-docblock')
3
5
 
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
2
4
  const { getMessageSize } = require('../../dd-trace/src/datastreams')
3
5
  const { convertToTextMap } = require('./utils')
@@ -40,9 +40,14 @@ class BaseLangChainTracingPlugin extends TracingPlugin {
40
40
 
41
41
  // Runnable interfaces have an `lc_namespace` property
42
42
  const ns = ctx.self.lc_namespace || ctx.namespace
43
- const resource = ctx.resource = [...ns, ctx.self.constructor.name].join('.')
44
43
 
45
- const handler = this.handlers[type]
44
+ const resourceParts = [...ns, ctx.self.constructor.name]
45
+ if (type === 'tool') {
46
+ resourceParts.push(ctx.instance.name)
47
+ }
48
+ const resource = ctx.resource = resourceParts.join('.')
49
+
50
+ const handler = this.handlers[type] || this.handlers.default
46
51
 
47
52
  const instance = ctx.instance
48
53
  const apiKey = handler.extractApiKey(instance)
@@ -78,7 +83,7 @@ class BaseLangChainTracingPlugin extends TracingPlugin {
78
83
 
79
84
  const { type } = ctx
80
85
 
81
- const handler = this.handlers[type]
86
+ const handler = this.handlers[type] || this.handlers.default
82
87
  const tags = handler.getSpanEndTags(ctx, span) || {}
83
88
 
84
89
  span.addTags(tags)
@@ -139,11 +144,38 @@ class EmbeddingsEmbedDocumentsPlugin extends BaseLangChainTracingPlugin {
139
144
  }
140
145
  }
141
146
 
147
+ class ToolInvokePlugin extends BaseLangChainTracingPlugin {
148
+ static get id () { return 'langchain_tool_invoke' }
149
+ static get lcType () { return 'tool' }
150
+ static get prefix () {
151
+ return 'tracing:orchestrion:@langchain/core:Tool_invoke'
152
+ }
153
+ }
154
+
155
+ class VectorStoreSimilaritySearchPlugin extends BaseLangChainTracingPlugin {
156
+ static get id () { return 'langchain_vectorstore_similarity_search' }
157
+ static get lcType () { return 'similarity_search' }
158
+ static get prefix () {
159
+ return 'tracing:orchestrion:@langchain/core:VectorStore_similaritySearch'
160
+ }
161
+ }
162
+
163
+ class VectorStoreSimilaritySearchWithScorePlugin extends BaseLangChainTracingPlugin {
164
+ static get id () { return 'langchain_vectorstore_similarity_search_with_score' }
165
+ static get lcType () { return 'similarity_search' }
166
+ static get prefix () {
167
+ return 'tracing:orchestrion:@langchain/core:VectorStore_similaritySearchWithScore'
168
+ }
169
+ }
170
+
142
171
  module.exports = [
143
172
  RunnableSequenceInvokePlugin,
144
173
  RunnableSequenceBatchPlugin,
145
174
  BaseChatModelGeneratePlugin,
146
175
  BaseLLMGeneratePlugin,
147
176
  EmbeddingsEmbedQueryPlugin,
148
- EmbeddingsEmbedDocumentsPlugin
177
+ EmbeddingsEmbedDocumentsPlugin,
178
+ ToolInvokePlugin,
179
+ VectorStoreSimilaritySearchPlugin,
180
+ VectorStoreSimilaritySearchWithScorePlugin
149
181
  ]
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
4
 
3
5
  class NycPlugin extends CiPlugin {
@@ -0,0 +1,114 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Combines legacy OpenAI streamed chunks into a single object.
5
+ * These legacy chunks are returned as buffers instead of individual objects.
6
+ * @param {readonly Uint8Array[]} chunks
7
+ * @returns {Array<Record<string, any>>}
8
+ */
9
+ function convertBuffersToObjects (chunks) {
10
+ return Buffer
11
+ .concat(chunks) // combine the buffers
12
+ .toString() // stringify
13
+ .split(/(?=data:)/) // split on "data:"
14
+ .map(chunk => chunk.replaceAll('\n', '').slice(6)) // remove newlines and 'data: ' from the front
15
+ .slice(0, -1) // remove the last [DONE] message
16
+ .map(JSON.parse) // parse all of the returned objects
17
+ }
18
+
19
+ /**
20
+ * Common function for combining chunks with n choices into a single response body.
21
+ * The shared logic will add a new choice index entry if it doesn't exist, and otherwise
22
+ * hand off to a onChoice handler to add that choice to the previously stored choice.
23
+ *
24
+ * @param {Array<Record<string, any>>} chunks
25
+ * @param {number} n
26
+ * @param {function(Record<string, any>, Record<string, any>): void} onChoice
27
+ * @returns {Record<string, any>}
28
+ */
29
+ function constructResponseFromStreamedChunks (chunks, n, onChoice) {
30
+ const body = { ...chunks[0], choices: Array.from({ length: n }) }
31
+
32
+ for (const chunk of chunks) {
33
+ body.usage = chunk.usage
34
+ for (const choice of chunk.choices) {
35
+ const choiceIdx = choice.index
36
+ const oldChoice = body.choices.find(choice => choice?.index === choiceIdx)
37
+
38
+ if (!oldChoice) {
39
+ body.choices[choiceIdx] = choice
40
+ continue
41
+ }
42
+
43
+ if (!oldChoice.finish_reason) {
44
+ oldChoice.finish_reason = choice.finish_reason
45
+ }
46
+
47
+ onChoice(choice, oldChoice)
48
+ }
49
+ }
50
+
51
+ return body
52
+ }
53
+
54
+ /**
55
+ * Constructs the entire response from a stream of OpenAI completion chunks,
56
+ * mainly combining the text choices of each chunk into a single string per choice.
57
+ * @param {Array<Record<string, any>>} chunks
58
+ * @param {number} n the number of choices to expect in the response
59
+ * @returns {Record<string, any>}
60
+ */
61
+ function constructCompletionResponseFromStreamedChunks (chunks, n) {
62
+ return constructResponseFromStreamedChunks(chunks, n, (choice, oldChoice) => {
63
+ const text = choice.text
64
+ if (text) {
65
+ if (oldChoice.text) {
66
+ oldChoice.text += text
67
+ } else {
68
+ oldChoice.text = text
69
+ }
70
+ }
71
+ })
72
+ }
73
+
74
+ /**
75
+ * Constructs the entire response from a stream of OpenAI chat completion chunks,
76
+ * mainly combining the text choices of each chunk into a single string per choice.
77
+ * @param {Array<Record<string, any>>} chunks
78
+ * @param {number} n the number of choices to expect in the response
79
+ * @returns {Record<string, any>}
80
+ */
81
+ function constructChatCompletionResponseFromStreamedChunks (chunks, n) {
82
+ return constructResponseFromStreamedChunks(chunks, n, (choice, oldChoice) => {
83
+ const delta = choice.delta
84
+ if (!delta) return
85
+
86
+ const content = delta.content
87
+ if (content) {
88
+ if (oldChoice.delta.content) {
89
+ oldChoice.delta.content += content
90
+ } else {
91
+ oldChoice.delta.content = content
92
+ }
93
+ }
94
+
95
+ const tools = delta.tool_calls
96
+ if (!tools) return
97
+
98
+ oldChoice.delta.tool_calls = tools.map((newTool, toolIdx) => {
99
+ const oldTool = oldChoice.delta.tool_calls?.[toolIdx]
100
+ if (oldTool) {
101
+ oldTool.function.arguments += newTool.function.arguments
102
+ return oldTool
103
+ }
104
+
105
+ return newTool
106
+ })
107
+ })
108
+ }
109
+
110
+ module.exports = {
111
+ convertBuffersToObjects,
112
+ constructCompletionResponseFromStreamedChunks,
113
+ constructChatCompletionResponseFromStreamedChunks
114
+ }
@@ -10,6 +10,11 @@ const { MEASURED } = require('../../../ext/tags')
10
10
  const { estimateTokens } = require('./token-estimator')
11
11
 
12
12
  const makeUtilities = require('../../dd-trace/src/plugins/util/llm')
13
+ const {
14
+ convertBuffersToObjects,
15
+ constructCompletionResponseFromStreamedChunks,
16
+ constructChatCompletionResponseFromStreamedChunks
17
+ } = require('./stream-helpers')
13
18
 
14
19
  let normalize
15
20
 
@@ -48,6 +53,39 @@ class OpenAiTracingPlugin extends TracingPlugin {
48
53
 
49
54
  normalize = utilities.normalize
50
55
  }
56
+
57
+ this.addSub('apm:openai:request:chunk', ({ ctx, chunk, done }) => {
58
+ if (!ctx.chunks) ctx.chunks = []
59
+
60
+ if (chunk) ctx.chunks.push(chunk)
61
+ if (!done) return
62
+
63
+ let chunks = ctx.chunks
64
+ if (chunks.length === 0) return
65
+
66
+ const firstChunk = chunks[0]
67
+ // OpenAI in legacy versions returns chunked buffers instead of objects.
68
+ // These buffers will need to be combined and coalesced into a list of object chunks.
69
+ if (firstChunk instanceof Buffer) {
70
+ chunks = convertBuffersToObjects(chunks)
71
+ }
72
+
73
+ const methodName = ctx.currentStore.normalizedMethodName
74
+ let n = 1
75
+ const prompt = ctx.args[0].prompt
76
+ if (Array.isArray(prompt) && typeof prompt[0] !== 'number') {
77
+ n *= prompt.length
78
+ }
79
+
80
+ let response = {}
81
+ if (methodName === 'createCompletion') {
82
+ response = constructCompletionResponseFromStreamedChunks(chunks, n)
83
+ } else if (methodName === 'createChatCompletion') {
84
+ response = constructChatCompletionResponseFromStreamedChunks(chunks, n)
85
+ }
86
+
87
+ ctx.result = { data: response }
88
+ })
51
89
  }
52
90
 
53
91
  configure (config) {
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { URL } = require('url')
2
4
  const log = require('../../dd-trace/src/log')
3
5
 
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const SchemaPlugin = require('../../dd-trace/src/plugins/schema')
2
4
  const SchemaExtractor = require('./schema_iterator')
3
5
 
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const PROTOBUF = 'protobuf'
2
4
  const {
3
5
  SCHEMA_DEFINITION,
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
4
  const { storage } = require('../../datadog-core')
3
5
 
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
4
  const { storage } = require('../../datadog-core')
3
5
  const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const IAST_CONTEXT_KEY = Symbol('_dd.iast.context')
2
4
  const IAST_TRANSACTION_ID = Symbol('_dd.iast.transactionId')
3
5
 
@@ -52,7 +54,9 @@ function cleanIastContext (store, context, iastContext) {
52
54
  context[IAST_CONTEXT_KEY] = null
53
55
  }
54
56
  if (iastContext) {
55
- Object.keys(iastContext).forEach(key => delete iastContext[key])
57
+ if (typeof iastContext === 'object') { // eslint-disable-line eslint-rules/eslint-safe-typeof-object
58
+ Object.keys(iastContext).forEach(key => delete iastContext[key])
59
+ }
56
60
  return true
57
61
  }
58
62
  return false
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const vulnerabilityReporter = require('./vulnerability-reporter')
2
4
  const { enableAllAnalyzers, disableAllAnalyzers } = require('./analyzers')
3
5
  const web = require('../../plugins/util/web')
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const LRUCache = require('lru-cache')
3
+ const { LRUCache } = require('lru-cache')
4
4
  const web = require('../../plugins/util/web')
5
5
  const vulnerabilities = require('./vulnerabilities')
6
6
 
@@ -1,5 +1,3 @@
1
- 'use strict'
2
-
3
1
  import path from 'path'
4
2
  import { URL } from 'url'
5
3
  import { getName } from '../telemetry/verbosity.js'
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ /* eslint n/no-unsupported-features/node-builtins: ['error', { ignores: ['module.register'] }] */
4
+
3
5
  const Module = require('module')
4
6
  const { pathToFileURL } = require('url')
5
7
  const { MessageChannel } = require('worker_threads')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  // eslint-disable-next-line @stylistic/max-len
2
4
  const DEFAULT_IAST_REDACTION_NAME_PATTERN = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|(?:sur|last)name|user(?:name)?|address|e?mail)'
3
5
  // eslint-disable-next-line @stylistic/max-len
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  module.exports = {
2
4
  COMMAND_INJECTION: 'COMMAND_INJECTION',
3
5
  CODE_INJECTION: 'CODE_INJECTION',
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const LRU = require('lru-cache')
3
+ const { LRUCache } = require('lru-cache')
4
4
  const vulnerabilitiesFormatter = require('./vulnerabilities-formatter')
5
5
  const { IAST_ENABLED_TAG_KEY, IAST_JSON_TAG_KEY } = require('./tags')
6
6
  const { keepTrace } = require('../../priority_sampler')
@@ -10,7 +10,7 @@ const { ASM } = require('../../standalone/product')
10
10
 
11
11
  const VULNERABILITIES_KEY = 'vulnerabilities'
12
12
  const VULNERABILITY_HASHES_MAX_SIZE = 1000
13
- const VULNERABILITY_HASHES = new LRU({ max: VULNERABILITY_HASHES_MAX_SIZE })
13
+ const VULNERABILITY_HASHES = new LRUCache({ max: VULNERABILITY_HASHES_MAX_SIZE })
14
14
  const RESET_VULNERABILITY_CACHE_INTERVAL = 60 * 60 * 1000 // 1 hour
15
15
 
16
16
  let tracer
@@ -114,7 +114,7 @@ function isDuplicatedVulnerability (vulnerability) {
114
114
  }
115
115
 
116
116
  function getVulnerabilityCallSiteFrames () {
117
- return getCallsiteFrames(stackTraceMaxDepth)
117
+ return getCallsiteFrames(stackTraceMaxDepth, getVulnerabilityCallSiteFrames)
118
118
  }
119
119
 
120
120
  function replaceCallSiteFromSourceMap (callsite) {
@@ -14,25 +14,31 @@ const enabledFor = {
14
14
 
15
15
  let fsPlugin
16
16
 
17
- function enterWith (fsProps, store = storage('legacy').getStore()) {
17
+ function getStoreToStart (fsProps, store = storage('legacy').getStore()) {
18
18
  if (store && !store.fs?.opExcluded) {
19
- storage('legacy').enterWith({
19
+ return {
20
20
  ...store,
21
21
  fs: {
22
22
  ...store.fs,
23
23
  ...fsProps,
24
24
  parentStore: store
25
25
  }
26
- })
26
+ }
27
27
  }
28
+
29
+ return store
28
30
  }
29
31
 
30
32
  class AppsecFsPlugin extends Plugin {
31
33
  enable () {
32
- this.addSub('apm:fs:operation:start', this._onFsOperationStart)
33
- this.addSub('apm:fs:operation:finish', this._onFsOperationFinishOrRenderEnd)
34
- this.addSub('tracing:datadog:express:response:render:start', this._onResponseRenderStart)
35
- this.addSub('tracing:datadog:express:response:render:end', this._onFsOperationFinishOrRenderEnd)
34
+ this.addBind('apm:fs:operation:start', this._onFsOperationStart)
35
+ this.addBind('apm:fs:operation:finish', this._onFsOperationFinishOrRenderEnd)
36
+ this.addBind('tracing:datadog:express:response:render:start', this._onResponseRenderStart)
37
+ this.addBind('tracing:datadog:express:response:render:end', this._onFsOperationFinishOrRenderEnd)
38
+ // TODO Remove this when dc-polyfill is fixed&updated
39
+ // hack to node 18 and early 20.x
40
+ // with dc-polyfill addBind is not enough to force a channel.hasSubscribers === true
41
+ this.addSub('tracing:datadog:express:response:render:start', () => {})
36
42
 
37
43
  super.configure(true)
38
44
  }
@@ -44,19 +50,20 @@ class AppsecFsPlugin extends Plugin {
44
50
  _onFsOperationStart () {
45
51
  const store = storage('legacy').getStore()
46
52
  if (store) {
47
- enterWith({ root: store.fs?.root === undefined }, store)
53
+ return getStoreToStart({ root: store.fs?.root === undefined }, store)
48
54
  }
49
55
  }
50
56
 
51
57
  _onResponseRenderStart () {
52
- enterWith({ opExcluded: true })
58
+ return getStoreToStart({ opExcluded: true })
53
59
  }
54
60
 
55
61
  _onFsOperationFinishOrRenderEnd () {
56
62
  const store = storage('legacy').getStore()
57
- if (store?.fs?.parentStore) {
58
- storage('legacy').enterWith(store.fs.parentStore)
63
+ if (store?.fs) {
64
+ return store.fs.parentStore
59
65
  }
66
+ return store
60
67
  }
61
68
  }
62
69
 
@@ -41,7 +41,7 @@ function handleResult (result, req, res, abortController, config, raspRule) {
41
41
  const ruleTriggered = !!result?.events?.length
42
42
 
43
43
  if (generateStackTraceAction && enabled && canReportStackTrace(rootSpan, maxStackTraces)) {
44
- const frames = getCallsiteFrames(maxDepth)
44
+ const frames = getCallsiteFrames(maxDepth, handleResult)
45
45
 
46
46
  reportStackTrace(
47
47
  rootSpan,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "2.2",
3
3
  "metadata": {
4
- "rules_version": "1.14.2"
4
+ "rules_version": "1.15.0"
5
5
  },
6
6
  "rules": [
7
7
  {
@@ -2985,7 +2985,7 @@
2985
2985
  "address": "graphql.server.resolver"
2986
2986
  }
2987
2987
  ],
2988
- "regex": "\\b(?:(?:l(?:(?:utimes|chmod)(?:Sync)?|(?:stat|ink)Sync)|w(?:rite(?:(?:File|v)(?:Sync)?|Sync)|atchFile)|u(?:n(?:watchFile|linkSync)|times(?:Sync)?)|s(?:(?:ymlink|tat)Sync|pawn(?:File|Sync))|ex(?:ec(?:File(?:Sync)?|Sync)|istsSync)|a(?:ppendFile|ccess)(?:Sync)?|(?:Caveat|Inode)s|open(?:dir)?Sync|new\\s+Function|Availability|\\beval)\\s*\\(|m(?:ain(?:Module\\s*(?:\\W*\\s*(?:constructor|require)|\\[)|\\s*(?:\\W*\\s*(?:constructor|require)|\\[))|kd(?:temp(?:Sync)?|irSync)\\s*\\(|odule\\.exports\\s*=)|c(?:(?:(?:h(?:mod|own)|lose)Sync|reate(?:Write|Read)Stream|p(?:Sync)?)\\s*\\(|o(?:nstructor\\s*(?:\\W*\\s*_load|\\[)|pyFile(?:Sync)?\\s*\\())|f(?:(?:(?:s(?:(?:yncS)?|tatS)|datas(?:yncS)?)ync|ch(?:mod|own)(?:Sync)?)\\s*\\(|u(?:nction\\s*\\(\\s*\\)\\s*{|times(?:Sync)?\\s*\\())|r(?:e(?:(?:ad(?:(?:File|link|dir)?Sync|v(?:Sync)?)|nameSync)\\s*\\(|quire\\s*(?:\\W*\\s*main|\\[))|m(?:Sync)?\\s*\\()|process\\s*(?:\\W*\\s*(?:mainModule|binding)|\\[)|t(?:his\\.constructor|runcateSync\\s*\\()|_(?:\\$\\$ND_FUNC\\$\\$_|_js_function)|global\\s*(?:\\W*\\s*process|\\[)|String\\s*\\.\\s*fromCharCode|binding\\s*\\[)",
2988
+ "regex": "\\b(?:(?:l(?:(?:utimes|chmod)(?:Sync)?|(?:stat|ink)Sync)|w(?:rite(?:(?:File|v)(?:Sync)?|Sync)|atchFile)|u(?:n(?:watchFile|linkSync)|times(?:Sync)?)|s(?:(?:ymlink|tat)Sync|pawn(?:File|Sync))|ex(?:ec(?:File(?:Sync)?|Sync)|istsSync)|a(?:ppendFile|ccess)(?:Sync)?|(?:Caveat|Inode)s|open(?:dir)?Sync|new\\s+Function|Availability|\\beval)\\s*\\(|m(?:ain(?:Module\\s*(?:\\W*\\s*(?:constructor|require)|\\[)|\\s*(?:\\W*\\s*(?:constructor|require)|\\[))|kd(?:temp(?:Sync)?|irSync)\\s*\\(|odule\\.exports\\s*=)|c(?:(?:(?:h(?:mod|own)|lose)Sync|reate(?:Write|Read)Stream|p(?:Sync)?)\\s*\\(|o(?:nstructor\\s*(?:\\W*\\s*_load|\\[)|pyFile(?:Sync)?\\s*\\())|f(?:(?:(?:s(?:(?:yncS)?|tatS)|datas(?:yncS)?)ync|ch(?:mod|own)(?:Sync)?)\\s*\\(|u(?:nction\\s*\\(\\s*\\)\\s*{|times(?:Sync)?\\s*\\())|r(?:e(?:(?:ad(?:(?:File|link|dir)?Sync|v(?:Sync)?)|nameSync)\\s*\\(|quire\\s*(?:\\W*\\s*main\\b|\\[))|m(?:Sync)?\\s*\\()|process\\s*(?:\\W*\\s*(?:mainModule|binding)|\\[)|t(?:his\\.constructor|runcateSync\\s*\\()|_(?:\\$\\$ND_FUNC\\$\\$_|_js_function)|global\\s*(?:\\W*\\s*process|\\[)|String\\s*\\.\\s*fromCharCode|binding\\s*\\[)",
2989
2989
  "options": {
2990
2990
  "case_sensitive": true,
2991
2991
  "min_length": 3
@@ -5656,6 +5656,52 @@
5656
5656
  ],
5657
5657
  "transformers": []
5658
5658
  },
5659
+ {
5660
+ "id": "dog-932-110",
5661
+ "name": "Python: Subprocess-based command injection",
5662
+ "tags": {
5663
+ "type": "command_injection",
5664
+ "category": "attack_attempt",
5665
+ "confidence": "0",
5666
+ "module": "waf"
5667
+ },
5668
+ "conditions": [
5669
+ {
5670
+ "parameters": {
5671
+ "inputs": [
5672
+ {
5673
+ "address": "server.request.query"
5674
+ },
5675
+ {
5676
+ "address": "server.request.body"
5677
+ },
5678
+ {
5679
+ "address": "server.request.path_params"
5680
+ },
5681
+ {
5682
+ "address": "server.request.headers.no_cookies"
5683
+ },
5684
+ {
5685
+ "address": "grpc.server.request.message"
5686
+ },
5687
+ {
5688
+ "address": "graphql.server.all_resolvers"
5689
+ },
5690
+ {
5691
+ "address": "graphql.server.resolver"
5692
+ }
5693
+ ],
5694
+ "regex": "(?s)\\bsubprocess\\b.*\\b(?:check_output|run|Popen|call|check_call)\\b",
5695
+ "options": {
5696
+ "case_sensitive": true,
5697
+ "min_length": 14
5698
+ }
5699
+ },
5700
+ "operator": "match_regex"
5701
+ }
5702
+ ],
5703
+ "transformers": []
5704
+ },
5659
5705
  {
5660
5706
  "id": "dog-934-001",
5661
5707
  "name": "XXE - XML file loads external entity",
@@ -9074,6 +9120,28 @@
9074
9120
  "evaluate": true,
9075
9121
  "output": true
9076
9122
  },
9123
+ {
9124
+ "id": "decode-auth-jwt",
9125
+ "generator": "jwt_decode",
9126
+ "min_version": "1.25.0",
9127
+ "parameters": {
9128
+ "mappings": [
9129
+ {
9130
+ "inputs": [
9131
+ {
9132
+ "address": "server.request.headers.no_cookies",
9133
+ "key_path": [
9134
+ "authorization"
9135
+ ]
9136
+ }
9137
+ ],
9138
+ "output": "server.request.jwt"
9139
+ }
9140
+ ]
9141
+ },
9142
+ "evaluate": true,
9143
+ "output": false
9144
+ },
9077
9145
  {
9078
9146
  "id": "http-network-fingerprint",
9079
9147
  "generator": "http_network_fingerprint",
@@ -9918,6 +9986,24 @@
9918
9986
  "category": "payment"
9919
9987
  }
9920
9988
  },
9989
+ {
9990
+ "id": "c542c147-3883-43d6-a067-178e4a7bd65d",
9991
+ "name": "Password",
9992
+ "key": {
9993
+ "operator": "match_regex",
9994
+ "parameters": {
9995
+ "regex": "\\bpass(?:[_-]?word|wd)?\\b|\\bpwd\\b",
9996
+ "options": {
9997
+ "case_sensitive": false,
9998
+ "min_length": 3
9999
+ }
10000
+ }
10001
+ },
10002
+ "tags": {
10003
+ "type": "password",
10004
+ "category": "credentials"
10005
+ }
10006
+ },
9921
10007
  {
9922
10008
  "id": "18b608bd7a764bff5b2344c0",
9923
10009
  "name": "Phone number",