datadog 2.20.0 → 2.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -1
  3. data/README.md +0 -1
  4. data/ext/LIBDATADOG_DEVELOPMENT.md +60 -0
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/libdatadog_api/ddsketch.c +106 -0
  7. data/ext/libdatadog_api/init.c +3 -0
  8. data/ext/libdatadog_api/library_config.c +35 -27
  9. data/ext/libdatadog_api/process_discovery.c +24 -18
  10. data/ext/libdatadog_extconf_helpers.rb +1 -1
  11. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  12. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
  13. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
  14. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  15. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  16. data/lib/datadog/appsec/api_security/route_extractor.rb +6 -2
  17. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  18. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  19. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  20. data/lib/datadog/appsec/autoload.rb +1 -1
  21. data/lib/datadog/appsec/compressed_json.rb +1 -1
  22. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  23. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  24. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +3 -2
  25. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +3 -1
  26. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +3 -1
  27. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +9 -4
  28. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -1
  29. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +7 -2
  30. data/lib/datadog/appsec/contrib/rails/patcher.rb +30 -0
  31. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +3 -1
  32. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +10 -4
  33. data/lib/datadog/appsec/event.rb +12 -14
  34. data/lib/datadog/appsec/metrics/collector.rb +19 -3
  35. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +2 -1
  36. data/lib/datadog/appsec/monitor/gateway/watcher.rb +4 -4
  37. data/lib/datadog/appsec/remote.rb +25 -13
  38. data/lib/datadog/appsec/security_engine/result.rb +28 -9
  39. data/lib/datadog/appsec/security_engine/runner.rb +17 -7
  40. data/lib/datadog/appsec/security_event.rb +5 -7
  41. data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -4
  42. data/lib/datadog/core/configuration/components.rb +22 -8
  43. data/lib/datadog/core/configuration/config_helper.rb +100 -0
  44. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  45. data/lib/datadog/core/configuration/ext.rb +0 -1
  46. data/lib/datadog/core/configuration/option.rb +38 -43
  47. data/lib/datadog/core/configuration/option_definition.rb +0 -9
  48. data/lib/datadog/core/configuration/options.rb +1 -5
  49. data/lib/datadog/core/configuration/settings.rb +10 -6
  50. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  51. data/lib/datadog/core/configuration/supported_configurations.rb +337 -0
  52. data/lib/datadog/core/configuration.rb +2 -2
  53. data/lib/datadog/core/ddsketch.rb +21 -0
  54. data/lib/datadog/core/deprecations.rb +2 -2
  55. data/lib/datadog/core/environment/ext.rb +0 -2
  56. data/lib/datadog/core/environment/git.rb +2 -2
  57. data/lib/datadog/core/environment/variable_helpers.rb +3 -3
  58. data/lib/datadog/core/environment/yjit.rb +2 -1
  59. data/lib/datadog/core/metrics/client.rb +2 -2
  60. data/lib/datadog/core/pin.rb +4 -8
  61. data/lib/datadog/core/process_discovery/tracer_memfd.rb +2 -4
  62. data/lib/datadog/core/process_discovery.rb +48 -23
  63. data/lib/datadog/core/remote/component.rb +4 -6
  64. data/lib/datadog/core/runtime/ext.rb +0 -1
  65. data/lib/datadog/core/telemetry/component.rb +11 -0
  66. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  67. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  68. data/lib/datadog/core/telemetry/event/app_started.rb +2 -2
  69. data/lib/datadog/core/telemetry/event.rb +1 -0
  70. data/lib/datadog/core/transport/response.rb +4 -1
  71. data/lib/datadog/core/utils/network.rb +19 -0
  72. data/lib/datadog/core.rb +2 -0
  73. data/lib/datadog/di/boot.rb +5 -3
  74. data/lib/datadog/di/component.rb +14 -0
  75. data/lib/datadog/di/context.rb +70 -0
  76. data/lib/datadog/di/el/compiler.rb +164 -0
  77. data/lib/datadog/di/el/evaluator.rb +159 -0
  78. data/lib/datadog/di/el/expression.rb +42 -0
  79. data/lib/datadog/di/el.rb +5 -0
  80. data/lib/datadog/di/error.rb +25 -0
  81. data/lib/datadog/di/instrumenter.rb +101 -32
  82. data/lib/datadog/di/probe.rb +35 -15
  83. data/lib/datadog/di/probe_builder.rb +39 -1
  84. data/lib/datadog/di/probe_file_loader.rb +1 -1
  85. data/lib/datadog/di/probe_manager.rb +3 -2
  86. data/lib/datadog/di/probe_notification_builder.rb +50 -51
  87. data/lib/datadog/di/serializer.rb +151 -7
  88. data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
  89. data/lib/datadog/profiling/collectors/info.rb +1 -1
  90. data/lib/datadog/profiling/ext.rb +2 -1
  91. data/lib/datadog/profiling/http_transport.rb +1 -1
  92. data/lib/datadog/profiling/tasks/exec.rb +2 -2
  93. data/lib/datadog/tracing/component.rb +6 -17
  94. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  95. data/lib/datadog/tracing/configuration/ext.rb +0 -3
  96. data/lib/datadog/tracing/configuration/settings.rb +15 -10
  97. data/lib/datadog/tracing/contrib/component.rb +2 -2
  98. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  99. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  100. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +63 -27
  101. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -0
  102. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +7 -1
  103. data/lib/datadog/tracing/contrib/rails/ext.rb +2 -1
  104. data/lib/datadog/tracing/contrib/rails/integration.rb +1 -1
  105. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
  106. data/lib/datadog/tracing/metadata/ext.rb +8 -0
  107. data/lib/datadog/version.rb +1 -1
  108. metadata +25 -9
  109. data/ext/libdatadog_api/macos_development.md +0 -26
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module APISecurity
6
+ module EndpointCollection
7
+ # This module serializes Rails Journey Router routes.
8
+ module RailsRouteSerializer
9
+ FORMAT_SUFFIX = "(.:format)"
10
+
11
+ module_function
12
+
13
+ def serialize(route)
14
+ method = route.verb.empty? ? "*" : route.verb
15
+ path = route.path.spec.to_s.delete_suffix(FORMAT_SUFFIX)
16
+
17
+ {
18
+ type: "REST",
19
+ resource_name: "#{method} #{path}",
20
+ operation_name: "http.request",
21
+ method: method,
22
+ path: path
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module APISecurity
6
+ module EndpointCollection
7
+ # This module serializes Sinatra routes.
8
+ module SinatraRouteSerializer
9
+ module_function
10
+
11
+ def serialize(route, method:, path_prefix: '')
12
+ path = path_prefix + route.safe_string
13
+
14
+ {
15
+ type: "REST",
16
+ resource_name: "#{method} #{path}",
17
+ operation_name: "http.request",
18
+ method: method,
19
+ path: path
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module APISecurity
6
+ module EndpointCollection
7
+ end
8
+ end
9
+ end
10
+ end
@@ -39,9 +39,9 @@ module Datadog
39
39
  # WARNING: This method works only *after* the request has been routed.
40
40
  #
41
41
  # WARNING: In Rails > 7.1 when a route was not found,
42
- # action_dispatch.route_uri_pattern will not be set.
42
+ # `action_dispatch.route_uri_pattern` will not be set.
43
43
  # In Rails < 7.1 it also will not be set even if a route was found,
44
- # but in this case action_dispatch.request.path_parameters won't be empty.
44
+ # but in this case `action_dispatch.request.path_parameters` won't be empty.
45
45
  def self.route_pattern(request)
46
46
  if request.env.key?(GRAPE_ROUTE_KEY)
47
47
  pattern = request.env[GRAPE_ROUTE_KEY][:route_info]&.pattern&.origin
@@ -52,6 +52,10 @@ module Datadog
52
52
  elsif request.env.key?(RAILS_ROUTE_KEY)
53
53
  request.env[RAILS_ROUTE_KEY].delete_suffix(RAILS_FORMAT_SUFFIX)
54
54
  elsif request.env.key?(RAILS_ROUTES_KEY) && !request.env.fetch(RAILS_PATH_PARAMS_KEY, {}).empty?
55
+ # NOTE: Rails mutate HEAD request in order to understand that route is supported.
56
+ # It will assing GET request method and run the route recognition.
57
+ request = request.env[RAILS_ROUTES_KEY].request_class.new(request.env) if request.head?
58
+
55
59
  pattern = request.env[RAILS_ROUTES_KEY].router
56
60
  .recognize(request) { |route, _| break route.path.spec.to_s }
57
61
 
@@ -2,51 +2,45 @@ AppSec WAF rules based on [appsec-event-rules](https://github.com/datadog/appsec
2
2
 
3
3
  ## How to update
4
4
 
5
- > [!WARNING]
6
- > This process is a temporary workaround to maintain compatibility with the existing code structure and will be changed.
5
+ In order to update rules, download `recommended.json` and `strict.json` of the desired version from [appsec-event-rules](https://github.com/datadog/appsec-event-rules) (example: [v1.13.3](https://github.com/DataDog/appsec-event-rules/tree/1.13.3/build))
7
6
 
8
- 1. Download `recommended.json` and `strict.json` of the desired version from [appsec-event-rules](https://github.com/datadog/appsec-event-rules) (example: [v1.13.3](https://github.com/DataDog/appsec-event-rules/tree/1.13.3/build))
9
- 2. Run the script below inside `waf_rules` folder to extract scanners and processors into separate files
7
+ You can store the following code as a `Rakefile` under `lib/datadog/appsec/assets/waf_rules`
10
8
 
11
- ```ruby
12
- require 'json'
9
+ ```ruby
10
+ def download(filename)
11
+ build_path = 'repos/DataDog/appsec-event-rules/contents/build'
13
12
 
14
- recommended_rules = JSON.parse(File.read(File.expand_path('recommended.json', __dir__)))
15
- strict_rules = JSON.parse(File.read(File.expand_path('strict.json', __dir__)))
13
+ system("gh api #{build_path}/#{filename} --jq '.content' | base64 -d > #{filename}")
14
+ end
16
15
 
17
- recommended_processors = recommended_rules.delete('processors')
18
- strict_processors = strict_rules.delete('processors')
16
+ task default: :update
19
17
 
20
- if recommended_processors.sort_by { |processor| processor['id'] } !=
21
- strict_processors.sort_by { |processor| processor['id'] }
22
- raise 'Processors are not the same, unable to extract them'
23
- end
18
+ task :verify_dependencies do
19
+ next if system('which gh 1>/dev/null')
24
20
 
25
- puts 'Extracting processors...'
26
- File.open(File.expand_path('processors.json', __dir__), 'wb') do |file|
27
- file.write(JSON.pretty_generate(recommended_processors))
28
- end
21
+ abort <<~MESSAGE
22
+ \033[0;33mNOTE: To successfully execute that task make sure you have
23
+ GitHub CLI installed and authenticated https://cli.github.com/\033[0m
24
+ MESSAGE
25
+ end
29
26
 
30
- recommended_scanners = recommended_rules.delete('scanners')
31
- strict_scanners = strict_rules.delete('scanners')
27
+ desc 'Update recommended.json and strict.json to the latest version'
28
+ task update: :verify_dependencies do
29
+ download('strict.json')
30
+ download('recommended.json')
32
31
 
33
- if recommended_scanners.sort_by { |processor| processor['id'] } !=
34
- strict_scanners.sort_by { |processor| processor['id'] }
35
- raise 'Scanners are not the same, unable to extract them'
36
- end
32
+ puts "\033[0;32mSuccess!\033[0m"
33
+ end
34
+ ```
37
35
 
38
- puts 'Extracting scanners...'
39
- File.open(File.expand_path('scanners.json', __dir__), 'wb') do |file|
40
- file.write(JSON.pretty_generate(recommended_scanners))
41
- end
36
+ And run the following command
42
37
 
43
- puts 'Updating rules...'
38
+ > [!IMPORTANT]
39
+ > To run that command you will need to install GitHub CLI tool and authenticate it
40
+ > See: https://cli.github.com/ (or ddtool)
44
41
 
45
- File.open(File.expand_path('recommended.json', __dir__), 'wb') do |file|
46
- file.write(JSON.pretty_generate(recommended_rules))
47
- end
48
42
 
49
- File.open(File.expand_path('strict.json', __dir__), 'wb') do |file|
50
- file.write(JSON.pretty_generate(strict_rules))
51
- end
52
- ```
43
+ ```console
44
+ $ bundle exec rake update
45
+ Success!
46
+ ```
@@ -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
+ }
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if %w[1 true].include?((ENV['DD_APPSEC_ENABLED'] || '').downcase)
3
+ if %w[1 true].include?((Datadog::DATADOG_ENV['DD_APPSEC_ENABLED'] || '').downcase)
4
4
  begin
5
5
  require_relative 'contrib/auto_instrument'
6
6
  Datadog::AppSec::Contrib::AutoInstrument.patch_all
@@ -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