datadog 2.21.0 → 2.23.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 (205) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +106 -2
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  4. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  5. data/ext/datadog_profiling_native_extension/collectors_stack.c +4 -0
  6. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
  7. data/ext/datadog_profiling_native_extension/extconf.rb +6 -4
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  9. data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
  10. data/ext/libdatadog_api/ddsketch.c +106 -0
  11. data/ext/libdatadog_api/feature_flags.c +554 -0
  12. data/ext/libdatadog_api/feature_flags.h +5 -0
  13. data/ext/libdatadog_api/init.c +5 -0
  14. data/ext/libdatadog_api/library_config.c +34 -25
  15. data/ext/libdatadog_api/process_discovery.c +19 -13
  16. data/ext/libdatadog_extconf_helpers.rb +1 -1
  17. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  18. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
  19. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
  20. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  21. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  22. data/lib/datadog/appsec/api_security/route_extractor.rb +23 -6
  23. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  24. data/lib/datadog/appsec/assets/blocked.html +8 -0
  25. data/lib/datadog/appsec/assets/blocked.json +1 -1
  26. data/lib/datadog/appsec/assets/blocked.text +3 -1
  27. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  28. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  29. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  30. data/lib/datadog/appsec/assets.rb +1 -1
  31. data/lib/datadog/appsec/compressed_json.rb +1 -1
  32. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  33. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  34. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
  35. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
  36. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
  37. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
  38. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
  39. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
  40. data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
  41. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
  42. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
  43. data/lib/datadog/appsec/event.rb +12 -14
  44. data/lib/datadog/appsec/metrics/collector.rb +19 -3
  45. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
  46. data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
  47. data/lib/datadog/appsec/remote.rb +29 -13
  48. data/lib/datadog/appsec/response.rb +18 -4
  49. data/lib/datadog/appsec/security_engine/result.rb +28 -9
  50. data/lib/datadog/appsec/security_engine/runner.rb +17 -7
  51. data/lib/datadog/appsec/security_event.rb +5 -7
  52. data/lib/datadog/core/configuration/components.rb +44 -9
  53. data/lib/datadog/core/configuration/config_helper.rb +1 -1
  54. data/lib/datadog/core/configuration/settings.rb +14 -0
  55. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  56. data/lib/datadog/core/configuration/supported_configurations.rb +330 -299
  57. data/lib/datadog/core/configuration.rb +1 -1
  58. data/lib/datadog/core/ddsketch.rb +19 -0
  59. data/lib/datadog/core/environment/ext.rb +6 -0
  60. data/lib/datadog/core/environment/process.rb +79 -0
  61. data/lib/datadog/core/environment/yjit.rb +2 -1
  62. data/lib/datadog/core/feature_flags.rb +61 -0
  63. data/lib/datadog/core/pin.rb +4 -8
  64. data/lib/datadog/core/process_discovery.rb +4 -2
  65. data/lib/datadog/core/remote/client/capabilities.rb +7 -0
  66. data/lib/datadog/core/remote/component.rb +4 -6
  67. data/lib/datadog/core/remote/transport/config.rb +2 -10
  68. data/lib/datadog/core/remote/transport/http/config.rb +9 -9
  69. data/lib/datadog/core/remote/transport/http/negotiation.rb +17 -8
  70. data/lib/datadog/core/remote/transport/http.rb +2 -0
  71. data/lib/datadog/core/remote/transport/negotiation.rb +2 -18
  72. data/lib/datadog/core/remote/worker.rb +25 -37
  73. data/lib/datadog/core/tag_builder.rb +0 -4
  74. data/lib/datadog/core/tag_normalizer.rb +84 -0
  75. data/lib/datadog/core/telemetry/component.rb +18 -3
  76. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  77. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  78. data/lib/datadog/core/telemetry/event/app_started.rb +52 -49
  79. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +1 -1
  80. data/lib/datadog/core/telemetry/event.rb +1 -0
  81. data/lib/datadog/core/telemetry/logger.rb +2 -2
  82. data/lib/datadog/core/telemetry/logging.rb +2 -8
  83. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +5 -6
  84. data/lib/datadog/core/telemetry/transport/telemetry.rb +1 -2
  85. data/lib/datadog/core/transport/http/client.rb +69 -0
  86. data/lib/datadog/core/transport/response.rb +4 -1
  87. data/lib/datadog/core/utils/array.rb +29 -0
  88. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  89. data/lib/datadog/core/utils/network.rb +22 -1
  90. data/lib/datadog/core/utils/only_once_successful.rb +6 -2
  91. data/lib/datadog/core/utils.rb +2 -0
  92. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  93. data/lib/datadog/data_streams/configuration.rb +11 -0
  94. data/lib/datadog/data_streams/ext.rb +11 -0
  95. data/lib/datadog/data_streams/extensions.rb +16 -0
  96. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  97. data/lib/datadog/data_streams/processor.rb +509 -0
  98. data/lib/datadog/data_streams/transport/http/api.rb +33 -0
  99. data/lib/datadog/data_streams/transport/http/client.rb +21 -0
  100. data/lib/datadog/data_streams/transport/http/stats.rb +87 -0
  101. data/lib/datadog/data_streams/transport/http.rb +41 -0
  102. data/lib/datadog/data_streams/transport/stats.rb +60 -0
  103. data/lib/datadog/data_streams.rb +100 -0
  104. data/lib/datadog/di/boot.rb +1 -0
  105. data/lib/datadog/di/component.rb +14 -16
  106. data/lib/datadog/di/context.rb +70 -0
  107. data/lib/datadog/di/el/compiler.rb +164 -0
  108. data/lib/datadog/di/el/evaluator.rb +159 -0
  109. data/lib/datadog/di/el/expression.rb +42 -0
  110. data/lib/datadog/di/el.rb +5 -0
  111. data/lib/datadog/di/error.rb +29 -0
  112. data/lib/datadog/di/instrumenter.rb +163 -48
  113. data/lib/datadog/di/probe.rb +55 -15
  114. data/lib/datadog/di/probe_builder.rb +39 -1
  115. data/lib/datadog/di/probe_manager.rb +13 -4
  116. data/lib/datadog/di/probe_notification_builder.rb +105 -67
  117. data/lib/datadog/di/proc_responder.rb +32 -0
  118. data/lib/datadog/di/serializer.rb +151 -7
  119. data/lib/datadog/di/transport/diagnostics.rb +2 -2
  120. data/lib/datadog/di/transport/http/diagnostics.rb +2 -4
  121. data/lib/datadog/di/transport/http/input.rb +2 -4
  122. data/lib/datadog/di/transport/http.rb +6 -2
  123. data/lib/datadog/di/transport/input.rb +64 -4
  124. data/lib/datadog/open_feature/component.rb +60 -0
  125. data/lib/datadog/open_feature/configuration.rb +27 -0
  126. data/lib/datadog/open_feature/evaluation_engine.rb +69 -0
  127. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  128. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  129. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  130. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  131. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  132. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  133. data/lib/datadog/open_feature/ext.rb +14 -0
  134. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  135. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  136. data/lib/datadog/open_feature/provider.rb +141 -0
  137. data/lib/datadog/open_feature/remote.rb +74 -0
  138. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  139. data/lib/datadog/open_feature/transport.rb +72 -0
  140. data/lib/datadog/open_feature.rb +19 -0
  141. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  142. data/lib/datadog/opentelemetry/metrics.rb +110 -0
  143. data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
  144. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +38 -0
  145. data/lib/datadog/opentelemetry.rb +3 -0
  146. data/lib/datadog/profiling/collectors/code_provenance.rb +15 -6
  147. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +1 -1
  148. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  149. data/lib/datadog/profiling/profiler.rb +4 -0
  150. data/lib/datadog/profiling/tag_builder.rb +36 -3
  151. data/lib/datadog/profiling.rb +1 -2
  152. data/lib/datadog/single_step_instrument.rb +1 -1
  153. data/lib/datadog/tracing/component.rb +6 -17
  154. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  155. data/lib/datadog/tracing/configuration/ext.rb +9 -0
  156. data/lib/datadog/tracing/configuration/settings.rb +77 -3
  157. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  158. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  159. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  160. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  161. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
  162. data/lib/datadog/tracing/contrib/component.rb +2 -2
  163. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
  164. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
  165. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
  166. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  167. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  168. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  169. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +74 -44
  170. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
  171. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
  172. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
  173. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  174. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  175. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  176. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  177. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  178. data/lib/datadog/tracing/contrib/karafka/patcher.rb +32 -0
  179. data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
  180. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  181. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  182. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  183. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
  184. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
  185. data/lib/datadog/tracing/contrib/status_range_matcher.rb +7 -0
  186. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
  187. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
  188. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
  189. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  190. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  191. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +46 -0
  192. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  193. data/lib/datadog/tracing/contrib/waterdrop.rb +37 -0
  194. data/lib/datadog/tracing/contrib.rb +1 -0
  195. data/lib/datadog/tracing/metadata/ext.rb +9 -1
  196. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  197. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  198. data/lib/datadog/tracing/transport/traces.rb +3 -5
  199. data/lib/datadog/version.rb +2 -2
  200. data/lib/datadog.rb +2 -0
  201. metadata +92 -16
  202. data/ext/libdatadog_api/macos_development.md +0 -26
  203. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  204. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  205. data/lib/datadog/di/transport/http/client.rb +0 -47
@@ -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.1"
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
@@ -5539,6 +5539,7 @@
5539
5539
  "confidence": "0",
5540
5540
  "module": "waf"
5541
5541
  },
5542
+ "max_version": "1.24.9",
5542
5543
  "conditions": [
5543
5544
  {
5544
5545
  "parameters": {
@@ -5656,6 +5657,52 @@
5656
5657
  ],
5657
5658
  "transformers": []
5658
5659
  },
5660
+ {
5661
+ "id": "dog-932-110",
5662
+ "name": "Python: Subprocess-based command injection",
5663
+ "tags": {
5664
+ "type": "command_injection",
5665
+ "category": "attack_attempt",
5666
+ "confidence": "0",
5667
+ "module": "waf"
5668
+ },
5669
+ "conditions": [
5670
+ {
5671
+ "parameters": {
5672
+ "inputs": [
5673
+ {
5674
+ "address": "server.request.query"
5675
+ },
5676
+ {
5677
+ "address": "server.request.body"
5678
+ },
5679
+ {
5680
+ "address": "server.request.path_params"
5681
+ },
5682
+ {
5683
+ "address": "server.request.headers.no_cookies"
5684
+ },
5685
+ {
5686
+ "address": "grpc.server.request.message"
5687
+ },
5688
+ {
5689
+ "address": "graphql.server.all_resolvers"
5690
+ },
5691
+ {
5692
+ "address": "graphql.server.resolver"
5693
+ }
5694
+ ],
5695
+ "regex": "(?s)\\bsubprocess\\b.*\\b(?:check_output|run|Popen|call|check_call)\\b",
5696
+ "options": {
5697
+ "case_sensitive": true,
5698
+ "min_length": 14
5699
+ }
5700
+ },
5701
+ "operator": "match_regex"
5702
+ }
5703
+ ],
5704
+ "transformers": []
5705
+ },
5659
5706
  {
5660
5707
  "id": "dog-934-001",
5661
5708
  "name": "XXE - XML file loads external entity",
@@ -6625,7 +6672,10 @@
6625
6672
  {
6626
6673
  "address": "graphql.server.resolver"
6627
6674
  }
6628
- ]
6675
+ ],
6676
+ "options": {
6677
+ "path-inspection": true
6678
+ }
6629
6679
  },
6630
6680
  "operator": "ssrf_detector"
6631
6681
  }
@@ -8870,6 +8920,271 @@
8870
8920
  "transformers": []
8871
8921
  }
8872
8922
  ],
8923
+ "rules_compat": [
8924
+ {
8925
+ "id": "api-001-100",
8926
+ "name": "JWT: No expiry is present",
8927
+ "tags": {
8928
+ "type": "jwt",
8929
+ "category": "api_security",
8930
+ "confidence": "0",
8931
+ "module": "business-logic"
8932
+ },
8933
+ "min_version": "1.25.0",
8934
+ "conditions": [
8935
+ {
8936
+ "parameters": {
8937
+ "inputs": [
8938
+ {
8939
+ "address": "server.request.jwt",
8940
+ "key_path": [
8941
+ "payload",
8942
+ "exp"
8943
+ ]
8944
+ }
8945
+ ]
8946
+ },
8947
+ "operator": "!exists"
8948
+ }
8949
+ ],
8950
+ "transformers": [],
8951
+ "output": {
8952
+ "event": false,
8953
+ "keep": false,
8954
+ "attributes": {
8955
+ "_dd.appsec.api.jwt.no_expiry": {
8956
+ "value": 1
8957
+ }
8958
+ }
8959
+ }
8960
+ },
8961
+ {
8962
+ "id": "api-001-110",
8963
+ "name": "JWT: Collect algorithm used",
8964
+ "tags": {
8965
+ "type": "jwt",
8966
+ "category": "api_security",
8967
+ "confidence": "0",
8968
+ "module": "business-logic"
8969
+ },
8970
+ "min_version": "1.25.0",
8971
+ "conditions": [
8972
+ {
8973
+ "parameters": {
8974
+ "inputs": [
8975
+ {
8976
+ "address": "server.request.jwt",
8977
+ "key_path": [
8978
+ "header",
8979
+ "alg"
8980
+ ]
8981
+ }
8982
+ ]
8983
+ },
8984
+ "operator": "exists"
8985
+ }
8986
+ ],
8987
+ "transformers": [],
8988
+ "output": {
8989
+ "event": false,
8990
+ "keep": false,
8991
+ "attributes": {
8992
+ "_dd.appsec.api.jwt_alg": {
8993
+ "address": "server.request.jwt",
8994
+ "key_path": [
8995
+ "header",
8996
+ "alg"
8997
+ ]
8998
+ }
8999
+ }
9000
+ }
9001
+ },
9002
+ {
9003
+ "id": "api-001-120",
9004
+ "name": "JWT: No audience is specified",
9005
+ "tags": {
9006
+ "type": "jwt",
9007
+ "category": "api_security",
9008
+ "confidence": "0",
9009
+ "module": "business-logic"
9010
+ },
9011
+ "min_version": "1.25.0",
9012
+ "conditions": [
9013
+ {
9014
+ "parameters": {
9015
+ "inputs": [
9016
+ {
9017
+ "address": "server.request.jwt",
9018
+ "key_path": [
9019
+ "payload",
9020
+ "aud"
9021
+ ]
9022
+ }
9023
+ ]
9024
+ },
9025
+ "operator": "!exists"
9026
+ }
9027
+ ],
9028
+ "transformers": [],
9029
+ "output": {
9030
+ "event": false,
9031
+ "keep": false,
9032
+ "attributes": {
9033
+ "_dd.appsec.api.jwt.no_audience": {
9034
+ "value": 1
9035
+ }
9036
+ }
9037
+ }
9038
+ },
9039
+ {
9040
+ "id": "api-001-130",
9041
+ "name": "JWT: None algorithm used",
9042
+ "tags": {
9043
+ "type": "jwt",
9044
+ "category": "api_security",
9045
+ "confidence": "0",
9046
+ "module": "business-logic"
9047
+ },
9048
+ "min_version": "1.25.0",
9049
+ "conditions": [
9050
+ {
9051
+ "parameters": {
9052
+ "inputs": [
9053
+ {
9054
+ "address": "server.request.jwt",
9055
+ "key_path": [
9056
+ "header",
9057
+ "alg"
9058
+ ]
9059
+ }
9060
+ ],
9061
+ "list": [
9062
+ "none",
9063
+ "nonE",
9064
+ "noNe",
9065
+ "noNE",
9066
+ "nOne",
9067
+ "nOnE",
9068
+ "nONe",
9069
+ "nONE",
9070
+ "None",
9071
+ "NonE",
9072
+ "NoNe",
9073
+ "NoNE",
9074
+ "NOne",
9075
+ "NOnE",
9076
+ "NONe",
9077
+ "NONE"
9078
+ ]
9079
+ },
9080
+ "operator": "exact_match"
9081
+ }
9082
+ ],
9083
+ "transformers": [],
9084
+ "output": {
9085
+ "event": false,
9086
+ "keep": true,
9087
+ "attributes": {
9088
+ "_dd.appsec.api.jwt.none_alg": {
9089
+ "value": 1
9090
+ }
9091
+ }
9092
+ }
9093
+ },
9094
+ {
9095
+ "id": "ua0-600-551",
9096
+ "name": "Datadog test scanner - scalar trace-tagging version: user-agent",
9097
+ "tags": {
9098
+ "type": "security_scanner",
9099
+ "category": "attack_attempt",
9100
+ "cwe": "200",
9101
+ "capec": "1000/118/169",
9102
+ "tool_name": "Datadog Canary Test",
9103
+ "confidence": "1",
9104
+ "module": "waf"
9105
+ },
9106
+ "min_version": "1.25.0",
9107
+ "conditions": [
9108
+ {
9109
+ "parameters": {
9110
+ "inputs": [
9111
+ {
9112
+ "address": "server.request.headers.no_cookies",
9113
+ "key_path": [
9114
+ "user-agent"
9115
+ ]
9116
+ },
9117
+ {
9118
+ "address": "grpc.server.request.metadata",
9119
+ "key_path": [
9120
+ "dd-canary"
9121
+ ]
9122
+ }
9123
+ ],
9124
+ "regex": "^dd-test-scanner-tag-scalar(?:$|/|\\s)"
9125
+ },
9126
+ "operator": "match_regex"
9127
+ }
9128
+ ],
9129
+ "transformers": [],
9130
+ "output": {
9131
+ "event": false,
9132
+ "attributes": {
9133
+ "_dd.appsec.test.scanner.scalar": {
9134
+ "value": 1
9135
+ }
9136
+ }
9137
+ }
9138
+ },
9139
+ {
9140
+ "id": "ua0-600-552",
9141
+ "name": "Datadog test scanner - reference trace-tagging version: user-agent",
9142
+ "tags": {
9143
+ "type": "security_scanner",
9144
+ "category": "attack_attempt",
9145
+ "cwe": "200",
9146
+ "capec": "1000/118/169",
9147
+ "tool_name": "Datadog Canary Test",
9148
+ "confidence": "1",
9149
+ "module": "waf"
9150
+ },
9151
+ "min_version": "1.25.0",
9152
+ "conditions": [
9153
+ {
9154
+ "parameters": {
9155
+ "inputs": [
9156
+ {
9157
+ "address": "server.request.headers.no_cookies",
9158
+ "key_path": [
9159
+ "user-agent"
9160
+ ]
9161
+ },
9162
+ {
9163
+ "address": "grpc.server.request.metadata",
9164
+ "key_path": [
9165
+ "dd-canary"
9166
+ ]
9167
+ }
9168
+ ],
9169
+ "regex": "^dd-test-scanner-tag-ref(?:$|/|\\s)"
9170
+ },
9171
+ "operator": "match_regex"
9172
+ }
9173
+ ],
9174
+ "transformers": [],
9175
+ "output": {
9176
+ "event": false,
9177
+ "attributes": {
9178
+ "_dd.appsec.test.scanner.reference": {
9179
+ "address": "server.request.headers.no_cookies",
9180
+ "key_path": [
9181
+ "user-agent"
9182
+ ]
9183
+ }
9184
+ }
9185
+ }
9186
+ }
9187
+ ],
8873
9188
  "processors": [
8874
9189
  {
8875
9190
  "id": "http-endpoint-fingerprint",
@@ -9074,6 +9389,28 @@
9074
9389
  "evaluate": true,
9075
9390
  "output": true
9076
9391
  },
9392
+ {
9393
+ "id": "decode-auth-jwt",
9394
+ "generator": "jwt_decode",
9395
+ "min_version": "1.25.0",
9396
+ "parameters": {
9397
+ "mappings": [
9398
+ {
9399
+ "inputs": [
9400
+ {
9401
+ "address": "server.request.headers.no_cookies",
9402
+ "key_path": [
9403
+ "authorization"
9404
+ ]
9405
+ }
9406
+ ],
9407
+ "output": "server.request.jwt"
9408
+ }
9409
+ ]
9410
+ },
9411
+ "evaluate": true,
9412
+ "output": false
9413
+ },
9077
9414
  {
9078
9415
  "id": "http-network-fingerprint",
9079
9416
  "generator": "http_network_fingerprint",
@@ -9918,6 +10255,24 @@
9918
10255
  "category": "payment"
9919
10256
  }
9920
10257
  },
10258
+ {
10259
+ "id": "c542c147-3883-43d6-a067-178e4a7bd65d",
10260
+ "name": "Password",
10261
+ "key": {
10262
+ "operator": "match_regex",
10263
+ "parameters": {
10264
+ "regex": "\\bpass(?:[_-]?word|wd)?\\b|\\bpwd\\b",
10265
+ "options": {
10266
+ "case_sensitive": false,
10267
+ "min_length": 3
10268
+ }
10269
+ }
10270
+ },
10271
+ "tags": {
10272
+ "type": "password",
10273
+ "category": "credentials"
10274
+ }
10275
+ },
9921
10276
  {
9922
10277
  "id": "18b608bd7a764bff5b2344c0",
9923
10278
  "name": "Phone number",
@@ -10146,4 +10501,4 @@
10146
10501
  }
10147
10502
  }
10148
10503
  ]
10149
- }
10504
+ }
@@ -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.1"
5
5
  },
6
6
  "rules": [
7
7
  {
@@ -1746,6 +1746,7 @@
1746
1746
  "transformers": []
1747
1747
  }
1748
1748
  ],
1749
+ "rules_compat": [],
1749
1750
  "processors": [
1750
1751
  {
1751
1752
  "id": "http-endpoint-fingerprint",
@@ -1950,6 +1951,28 @@
1950
1951
  "evaluate": true,
1951
1952
  "output": true
1952
1953
  },
1954
+ {
1955
+ "id": "decode-auth-jwt",
1956
+ "generator": "jwt_decode",
1957
+ "min_version": "1.25.0",
1958
+ "parameters": {
1959
+ "mappings": [
1960
+ {
1961
+ "inputs": [
1962
+ {
1963
+ "address": "server.request.headers.no_cookies",
1964
+ "key_path": [
1965
+ "authorization"
1966
+ ]
1967
+ }
1968
+ ],
1969
+ "output": "server.request.jwt"
1970
+ }
1971
+ ]
1972
+ },
1973
+ "evaluate": true,
1974
+ "output": false
1975
+ },
1953
1976
  {
1954
1977
  "id": "http-network-fingerprint",
1955
1978
  "generator": "http_network_fingerprint",
@@ -2794,6 +2817,24 @@
2794
2817
  "category": "payment"
2795
2818
  }
2796
2819
  },
2820
+ {
2821
+ "id": "c542c147-3883-43d6-a067-178e4a7bd65d",
2822
+ "name": "Password",
2823
+ "key": {
2824
+ "operator": "match_regex",
2825
+ "parameters": {
2826
+ "regex": "\\bpass(?:[_-]?word|wd)?\\b|\\bpwd\\b",
2827
+ "options": {
2828
+ "case_sensitive": false,
2829
+ "min_length": 3
2830
+ }
2831
+ }
2832
+ },
2833
+ "tags": {
2834
+ "type": "password",
2835
+ "category": "credentials"
2836
+ }
2837
+ },
2797
2838
  {
2798
2839
  "id": "18b608bd7a764bff5b2344c0",
2799
2840
  "name": "Phone number",
@@ -3022,4 +3063,4 @@
3022
3063
  }
3023
3064
  }
3024
3065
  ]
3025
- }
3066
+ }
@@ -21,7 +21,7 @@ module Datadog
21
21
  end
22
22
 
23
23
  def blocked(format: :html)
24
- (@blocked ||= {})[format] ||= read("blocked.#{format}")
24
+ (@blocked ||= {})[format] ||= read("blocked.#{format}").freeze
25
25
  end
26
26
 
27
27
  def path
@@ -8,7 +8,7 @@ require_relative '../core/utils/base64'
8
8
 
9
9
  module Datadog
10
10
  module AppSec
11
- # Converts derivative schema payloads into JSON and compresses them into a
11
+ # Converts complex schema payloads into JSON and compresses them into a
12
12
  # base64 encoded string if the payload is worth compressing.
13
13
  #
14
14
  # See: https://github.com/DataDog/dd-trace-rb/pull/3177#issuecomment-1747221082
@@ -352,6 +352,15 @@ module Datadog
352
352
  o.default true
353
353
  end
354
354
 
355
+ settings :endpoint_collection do
356
+ # Enables reporting of application routes at application start via telemetry
357
+ option :enabled do |o|
358
+ o.type :bool, nilable: true
359
+ o.env 'DD_API_SECURITY_ENDPOINT_COLLECTION_ENABLED'
360
+ o.default true
361
+ end
362
+ end
363
+
355
364
  # NOTE: Unfortunately, we have to go with Float due to other libs
356
365
  # setup, even tho we don't plan to support sub-second delays.
357
366
  #
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../event'
4
+ require_relative '../../trace_keeper'
4
5
  require_relative '../../security_event'
5
6
 
6
7
  module Datadog
@@ -31,7 +32,8 @@ module Datadog
31
32
  result = context.run_rasp(Ext::RASP_SQLI, {}, ephemeral_data, waf_timeout)
32
33
 
33
34
  if result.match?
34
- AppSec::Event.tag_and_keep!(context, result)
35
+ AppSec::Event.tag(context, result)
36
+ TraceKeeper.keep!(context.trace) if result.keep?
35
37
 
36
38
  context.events.push(
37
39
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -3,6 +3,7 @@
3
3
  require 'excon'
4
4
 
5
5
  require_relative '../../event'
6
+ require_relative '../../trace_keeper'
6
7
  require_relative '../../security_event'
7
8
 
8
9
  module Datadog
@@ -22,7 +23,8 @@ module Datadog
22
23
  result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
23
24
 
24
25
  if result.match?
25
- AppSec::Event.tag_and_keep!(context, result)
26
+ AppSec::Event.tag(context, result)
27
+ TraceKeeper.keep!(context.trace) if result.keep?
26
28
 
27
29
  context.events.push(
28
30
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -38,4 +40,3 @@ module Datadog
38
40
  end
39
41
  end
40
42
  end
41
- # rubocop:enable Naming/FileName
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../event'
4
+ require_relative '../../trace_keeper'
4
5
  require_relative '../../security_event'
5
6
 
6
7
  module Datadog
@@ -21,7 +22,8 @@ module Datadog
21
22
  result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
22
23
 
23
24
  if result.match?
24
- AppSec::Event.tag_and_keep!(context, result)
25
+ AppSec::Event.tag(context, result)
26
+ TraceKeeper.keep!(context.trace) if result.keep?
25
27
 
26
28
  context.events.push(
27
29
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -3,6 +3,7 @@
3
3
  require 'json'
4
4
 
5
5
  require_relative '../../../event'
6
+ require_relative '../../../trace_keeper'
6
7
  require_relative '../../../security_event'
7
8
  require_relative '../../../instrumentation/gateway'
8
9
 
@@ -32,7 +33,8 @@ module Datadog
32
33
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
33
34
 
34
35
  if result.match?
35
- AppSec::Event.tag_and_keep!(context, result)
36
+ AppSec::Event.tag(context, result)
37
+ TraceKeeper.keep!(context.trace) if result.keep?
36
38
 
37
39
  context.events.push(
38
40
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../ext'
4
4
  require_relative '../../../event'
5
+ require_relative '../../../trace_keeper'
5
6
  require_relative '../../../security_event'
6
7
  require_relative '../../../instrumentation/gateway'
7
8
 
@@ -38,14 +39,16 @@ module Datadog
38
39
 
39
40
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
40
41
 
41
- if result.match? || !result.derivatives.empty?
42
+ if result.match? || !result.attributes.empty?
42
43
  context.events.push(
43
44
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
44
45
  )
45
46
  end
46
47
 
47
48
  if result.match?
48
- AppSec::Event.tag_and_keep!(context, result)
49
+ AppSec::Event.tag(context, result)
50
+ TraceKeeper.keep!(context.trace) if result.keep?
51
+
49
52
  AppSec::ActionsHandler.handle(result.actions)
50
53
  end
51
54
 
@@ -66,7 +69,8 @@ module Datadog
66
69
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
67
70
 
68
71
  if result.match?
69
- AppSec::Event.tag_and_keep!(context, result)
72
+ AppSec::Event.tag(context, result)
73
+ TraceKeeper.keep!(context.trace) if result.keep?
70
74
 
71
75
  context.events.push(
72
76
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -90,7 +94,8 @@ module Datadog
90
94
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
91
95
 
92
96
  if result.match?
93
- AppSec::Event.tag_and_keep!(context, result)
97
+ AppSec::Event.tag(context, result)
98
+ TraceKeeper.keep!(context.trace) if result.keep?
94
99
 
95
100
  context.events.push(
96
101
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -161,7 +161,7 @@ module Datadog
161
161
  if context.waf_runner_ruleset_version
162
162
  span.set_tag('_dd.appsec.event_rules.version', context.waf_runner_ruleset_version)
163
163
 
164
- unless @oneshot_tags_sent
164
+ unless oneshot_tags_sent?
165
165
  # Small race condition, but it's inoccuous: worst case the tags
166
166
  # are sent a couple of times more than expected
167
167
  @oneshot_tags_sent = true
@@ -204,6 +204,10 @@ module Datadog
204
204
  end
205
205
  # standard:enable Metrics/MethodLength
206
206
 
207
+ def oneshot_tags_sent?
208
+ @oneshot_tags_sent
209
+ end
210
+
207
211
  def to_rack_header(header)
208
212
  @rack_headers[header] ||= Datadog::Tracing::Contrib::Rack::Header.to_rack_header(header)
209
213
  end