diff --git a/.github/workflows/BundlerAudit.yml b/.github/workflows/BundlerAudit.yml index 38d6fb42..c256f867 100644 --- a/.github/workflows/BundlerAudit.yml +++ b/.github/workflows/BundlerAudit.yml @@ -10,9 +10,12 @@ jobs: audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: 'Bundler Audit' - # uses: andrewmcodes/bundler-audit-action@main - uses: laicuRoot/bundler-audit-action@use-ruby-3.2.2 # Temporarily fixes Ruby 3 issue: andrewmcodes/bundler-audit-action#6 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v5 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + - name: Run bundler-audit + run: | + gem install bundler-audit + bundle-audit check --update diff --git a/.github/workflows/DockerLint.yml b/.github/workflows/DockerLint.yml index df4e5c30..ac196422 100644 --- a/.github/workflows/DockerLint.yml +++ b/.github/workflows/DockerLint.yml @@ -45,7 +45,7 @@ jobs: # Checkout the code base # ########################## - name: Checkout Code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: # super-linter needs the full git history to get the # list of files that changed across commits diff --git a/.github/workflows/nativeruby.yml b/.github/workflows/nativeruby.yml index b269a23f..b88870fd 100644 --- a/.github/workflows/nativeruby.yml +++ b/.github/workflows/nativeruby.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Toolkit Repo - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ac98ab5c..6398a4ef 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2023-01-09 23:31:25 UTC using RuboCop version 1.42.0. +# on 2026-03-28 00:33:27 UTC using RuboCop version 1.86.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -12,46 +12,63 @@ Layout/EmptyLineAfterGuardClause: Exclude: - 'tasks/connectors/cobaltio/lib/cobaltio_helper.rb' +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +Layout/EmptyLinesAroundMethodBody: + Exclude: + - 'tasks/utilities/csv2kdi/lib/csv2kdi_helper.rb' + # Offense count: 1 +# Configuration parameters: AllowedParentClasses. Lint/MissingSuper: Exclude: - 'tasks/base.rb' -# Offense count: 1 +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). Lint/UselessAssignment: Exclude: - 'tasks/connectors/cobaltio/lib/cobaltio_helper.rb' + - 'tasks/connectors/digital_footprint/riskiq/lib/riskiq_helper.rb' + - 'tasks/connectors/ms_defender_atp/ms_defender_atp.rb' -# Offense count: 179 -# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, CountRepeatedAttributes. +# Offense count: 4 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: CheckForMethodsWithNoSideEffects. +Lint/Void: + Exclude: + - 'tasks/connectors/edgescan/lib/edgescan_vulnerability.rb' + - 'tasks/connectors/insight_appsec/lib/insight_appsec_client.rb' + - 'tasks/utilities/csv2kdi/lib/csv2kdi_helper.rb' + +# Offense count: 195 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: Max: 585 -# Offense count: 46 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods. +# Offense count: 102 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. # AllowedMethods: refine Metrics/BlockLength: - Max: 233 - Exclude: - - 'spec/**/*' + Max: 393 -# Offense count: 14 -# Configuration parameters: CountBlocks. +# Offense count: 7 +# Configuration parameters: CountBlocks, CountModifierForms. Metrics/BlockNesting: Max: 5 -# Offense count: 55 +# Offense count: 60 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: Max: 417 -# Offense count: 76 -# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods. +# Offense count: 79 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: Max: 107 -# Offense count: 316 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods. +# Offense count: 333 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Max: 325 @@ -60,18 +77,18 @@ Metrics/MethodLength: Metrics/ModuleLength: Max: 438 -# Offense count: 28 +# Offense count: 30 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: Max: 22 -# Offense count: 65 -# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods. +# Offense count: 69 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: Max: 119 # Offense count: 66 -# Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns. +# Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns, ForbiddenIdentifiers, ForbiddenPatterns. # SupportedStyles: snake_case, camelCase Naming/VariableName: Exclude: @@ -84,16 +101,25 @@ Style/ClassVars: Exclude: - 'tasks/connectors/cobaltio/lib/cobaltio_helper.rb' -# Offense count: 132 +# Offense count: 138 # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false -# Offense count: 169 +# Offense count: 174 # Configuration parameters: AllowedVariables. Style/GlobalVars: Enabled: false +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowedReceivers. +# AllowedReceivers: Thread.current +Style/HashEachMethods: + Exclude: + - 'tasks/base.rb' + - 'tasks/connectors/contrast/contrast.rb' + # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). Style/Not: @@ -102,14 +128,14 @@ Style/Not: # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns, IgnoredMethods. +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: - 'spec/**/*' - 'tasks/connectors/cobaltio/lib/cobaltio_helper.rb' -# Offense count: 9 +# Offense count: 12 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: @@ -120,6 +146,36 @@ Style/OptionalBooleanParameter: - 'lib/http.rb' - 'lib/kdi/kdi_helpers.rb' +# Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowedMethods. +# AllowedMethods: infinite?, nonzero? +Style/RedundantCondition: + Exclude: + - 'lib/data/mapping/digi_footprint_finding_mapper.rb' + - 'tasks/utilities/csv2kdi/csv2kdi.rb' + - 'tasks/utilities/csv2kdi/lib/csv2kdi_helper.rb' + +# Offense count: 37 +# This cop supports safe autocorrection (--autocorrect). +Style/RedundantParentheses: + Exclude: + - 'lib/data/mapping/digi_footprint_finding_mapper.rb' + - 'tasks/base.rb' + - 'tasks/connectors/aqua/aqua.rb' + - 'tasks/connectors/asimily/lib/asimily_client.rb' + - 'tasks/connectors/bugcrowd/bugcrowd_task.rb' + - 'tasks/connectors/contrast/contrast.rb' + - 'tasks/connectors/digital_footprint/bitsight/bitsight.rb' + - 'tasks/connectors/digital_footprint/bitsight/lib/bitsight_helpers.rb' + - 'tasks/connectors/digital_footprint/riskiq/lib/riskiq_helper.rb' + - 'tasks/connectors/digital_footprint/security_scorecard/security_scorecard.rb' + - 'tasks/connectors/lacework/lacework.rb' + - 'tasks/connectors/lacework/lib/lacework_helper.rb' + - 'tasks/utilities/asset_upload_tag/add_assets.rb' + - 'tasks/utilities/csv2kdi/csv2kdi.rb' + - 'toolkit.rb' + # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. @@ -149,7 +205,7 @@ Style/SoleNestedConditional: - 'tasks/connectors/snyk/snyk.rb' - 'tasks/connectors/snyk_findings/snyk_findings.rb' -# Offense count: 7968 +# Offense count: 9276 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -159,12 +215,12 @@ Style/StringLiterals: # Offense count: 5 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma +# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInHashLiteral: Exclude: - 'tasks/connectors/cobaltio/cobaltio.rb' -# Offense count: 2 +# Offense count: 14 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: WordRegex. # SupportedStyles: percent, brackets @@ -172,7 +228,7 @@ Style/WordArray: EnforcedStyle: percent MinSize: 6 -# Offense count: 20 +# Offense count: 14 # This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: Exclude: @@ -180,11 +236,10 @@ Style/ZeroLengthPredicate: - 'tasks/connectors/nozomi/nozomi.rb' - 'tasks/connectors/snyk/snyk.rb' - 'tasks/connectors/snyk_findings/snyk_findings.rb' - - 'tasks/connectors/snyk_v2/snyk_v2_task.rb' -# Offense count: 419 +# Offense count: 452 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns. +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: Max: 834 diff --git a/.ruby-version b/.ruby-version index be94e6f5..7bcbb380 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.4.9 diff --git a/Containerfile b/Containerfile index 83b11f62..e1fa8a54 100644 --- a/Containerfile +++ b/Containerfile @@ -1,8 +1,8 @@ -FROM ruby:3.2.2 +FROM ruby:3.4 HEALTHCHECK NONE # Update the base image. -RUN apt-get update -y && apt-get upgrade -y +RUN apt-get update -y && apt-get upgrade -y # Copy Files To Container. COPY . "/opt/app/toolkit/" @@ -10,10 +10,6 @@ COPY . "/opt/app/toolkit/" # Run Bundle Install WORKDIR "/opt/app/toolkit/" RUN gem install bundler && \ - # CVE-2023-36617 - gem install uri -v 0.12.2 && \ - # CVE-2023-28756 - gem install time -v 0.2.2 && \ bundle install # Set Entrypoint diff --git a/Gemfile b/Gemfile index 0fa58308..3dfd6ddf 100644 --- a/Gemfile +++ b/Gemfile @@ -2,46 +2,39 @@ source "https://rubygems.org" -ruby "3.2.2" -# git_source(:github) do |repo_name| -# repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") -# "https://github.com/#{repo_name}.git" -# end +ruby "~> 3.4.0" -# Only required for file upload types (Guardium and Qualys to Kenna Direct), comment out if unneeded: -# gem 'nokogiri' - -gem "activesupport" -gem "addressable" -gem "aws-sdk-guardduty" -gem "aws-sdk-inspector" -gem "aws-sdk-inspector2" -gem "faraday", "~> 2.13" -gem 'faraday-multipart' +gem "activesupport", "~> 7.2" +gem "addressable", "~> 2.8" +gem "aws-sdk-guardduty", "~> 1.62" +gem "aws-sdk-inspector", "~> 1.44" +gem "aws-sdk-inspector2", "~> 1.10" +gem "faraday", "~> 2.14" +gem "faraday-multipart", "~> 1.2" gem "faraday-retry", "~> 2.3" -gem "httparty" -gem "ipaddress" -gem "rest-client" -gem "rexml", ">= 3.3.6" -gem "ruby-limiter" -gem "sanitize" -gem "strscan" -gem "tty-pager" +gem "httparty", "~> 0.22" +gem "ipaddress", "~> 0.8" +gem "rest-client", "~> 2.1" +gem "rexml", "~> 3.4" +gem "ruby-limiter", "~> 2.2" +gem "sanitize", "~> 6.1" +gem "strscan", "~> 3.1" +gem "tty-pager", "~> 0.14" group :development, :test do - gem "pry" - gem "pry-byebug" - gem "rspec" - gem "rubocop", require: false - gem 'simplecov' - gem 'simplecov-cobertura' - gem "solargraph", require: false - gem "timecop" - gem "vcr", "~> 6.1" - gem "webmock", "~> 3.18" - gem 'yard', '>= 0.9.36' + gem "pry", "~> 0.14" + gem "pry-byebug", "~> 3.10" + gem "rspec", "~> 3.13" + gem "rubocop", "~> 1.69", require: false + gem "simplecov", "~> 0.22" + gem "simplecov-cobertura", "~> 3.1" + gem "solargraph", "~> 0.50", require: false + gem "timecop", "~> 0.9" + gem "vcr", "~> 6.3" + gem "webmock", "~> 3.24" + gem "yard", "~> 0.9", ">= 0.9.37" end group :test do - gem 'rspec-github', require: false + gem "rspec-github", "~> 2.4", require: false end diff --git a/Gemfile.lock b/Gemfile.lock index ca0c417f..5aa33d23 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,142 +13,165 @@ GEM minitest (>= 5.1, < 6) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) - ast (2.4.2) - aws-eventstream (1.2.0) - aws-partitions (1.690.0) - aws-sdk-core (3.168.4) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) + ast (2.4.3) + aws-eventstream (1.4.0) + aws-partitions (1.1231.0) + aws-sdk-core (3.244.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 + bigdecimal jmespath (~> 1, >= 1.6.1) - aws-sdk-guardduty (1.62.0) - aws-sdk-core (~> 3, >= 3.165.0) - aws-sigv4 (~> 1.1) - aws-sdk-inspector (1.44.0) - aws-sdk-core (~> 3, >= 3.165.0) - aws-sigv4 (~> 1.1) - aws-sdk-inspector2 (1.10.0) - aws-sdk-core (~> 3, >= 3.165.0) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.5.2) + logger + aws-sdk-guardduty (1.145.0) + aws-sdk-core (~> 3, >= 3.244.0) + aws-sigv4 (~> 1.5) + aws-sdk-inspector (1.88.0) + aws-sdk-core (~> 3, >= 3.244.0) + aws-sigv4 (~> 1.5) + aws-sdk-inspector2 (1.70.0) + aws-sdk-core (~> 3, >= 3.244.0) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) backport (1.2.0) base64 (0.3.0) benchmark (0.5.0) - bigdecimal (4.0.1) - byebug (11.1.3) + bigdecimal (4.1.0) + byebug (13.0.0) + reline (>= 0.6.0) coderay (1.1.3) concurrent-ruby (1.3.6) connection_pool (3.0.2) - crack (0.4.5) + crack (1.0.1) + bigdecimal rexml crass (1.0.6) - diff-lcs (1.5.0) + csv (3.3.5) + diff-lcs (1.6.2) docile (1.4.1) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) + domain_name (0.6.20240107) drb (2.2.3) - e2mmap (0.1.0) - faraday (2.13.1) + faraday (2.14.1) faraday-net_http (>= 2.0, < 3.5) json logger faraday-multipart (1.2.0) multipart-post (~> 2.0) - faraday-net_http (3.4.0) - net-http (>= 0.5.0) - faraday-retry (2.3.1) + faraday-net_http (3.4.2) + net-http (~> 0.5) + faraday-retry (2.4.0) faraday (~> 2.0) - hashdiff (1.0.1) + hashdiff (1.2.1) http-accept (1.7.0) - http-cookie (1.0.5) + http-cookie (1.1.0) domain_name (~> 0.5) - httparty (0.21.0) + httparty (0.24.2) + csv mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) i18n (1.14.8) concurrent-ruby (~> 1.0) + io-console (0.8.2) ipaddress (0.8.3) - jaro_winkler (1.5.4) + jaro_winkler (1.7.0) jmespath (1.6.2) - json (2.6.3) - kramdown (2.4.0) - rexml + json (2.19.3) + kramdown (2.5.2) + rexml (>= 3.4.4) kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) logger (1.7.0) - method_source (1.0.0) - mime-types (3.4.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2022.0105) - mini_mime (1.1.2) + method_source (1.1.0) + mime-types (3.7.0) + logger + mime-types-data (~> 3.2025, >= 3.2025.0507) + mime-types-data (3.2026.0317) + mini_mime (1.1.5) minitest (5.27.0) - multi_xml (0.6.0) + multi_xml (0.8.1) + bigdecimal (>= 3.1, < 5) multipart-post (2.4.1) - net-http (0.6.0) - uri + net-http (0.9.1) + uri (>= 0.11.1) netrc (0.11.0) - nokogiri (1.19.1-aarch64-linux-gnu) + nokogiri (1.19.2-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.1-arm64-darwin) + nokogiri (1.19.2-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.1-x86_64-darwin) + nokogiri (1.19.2-x86_64-darwin) racc (~> 1.4) - nokogiri (1.19.1-x86_64-linux-gnu) + nokogiri (1.19.2-x86_64-linux-gnu) racc (~> 1.4) - parallel (1.22.1) - parser (3.2.0.0) + observer (0.1.2) + open3 (0.2.1) + ostruct (0.6.3) + parallel (1.27.0) + parser (3.3.11.1) ast (~> 2.4.1) - pry (0.14.2) + racc + prism (1.9.0) + pry (0.16.0) coderay (~> 1.1) method_source (~> 1.0) - pry-byebug (3.10.1) - byebug (~> 11.0) - pry (>= 0.13, < 0.15) - public_suffix (5.0.1) + reline (>= 0.6.0) + pry-byebug (3.12.0) + byebug (~> 13.0) + pry (>= 0.13, < 0.17) + public_suffix (7.0.5) racc (1.8.1) rainbow (3.1.1) - regexp_parser (2.6.1) + rbs (3.10.4) + logger + tsort + regexp_parser (2.11.3) + reline (0.6.3) + io-console (~> 0.5) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - reverse_markdown (2.1.1) + reverse_markdown (3.0.2) nokogiri - rexml (3.3.9) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-core (3.12.0) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.2) + rexml (3.4.4) + rspec (3.13.2) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-github (2.4.0) rspec-core (~> 3.0) - rspec-mocks (3.12.2) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-support (3.12.0) - rubocop (1.42.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.7) + rubocop (1.86.0) json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.24.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.24.1) - parser (>= 3.1.1.0) - ruby-limiter (2.2.2) - ruby-progressbar (1.11.0) - sanitize (6.0.2) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.49.1) + parser (>= 3.3.7.2) + prism (~> 1.7) + ruby-limiter (2.3.0) + ruby-progressbar (1.13.0) + sanitize (6.1.3) crass (~> 1.0.2) nokogiri (>= 1.12.0) securerandom (0.4.1) @@ -156,93 +179,104 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-cobertura (2.1.0) + simplecov-cobertura (3.1.0) rexml simplecov (~> 0.19) - simplecov-html (0.13.1) + simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) - solargraph (0.48.0) + solargraph (0.58.3) + ast (~> 2.4.3) backport (~> 1.2) - benchmark - bundler (>= 1.17.2) + benchmark (~> 0.4) + bundler (>= 2.0) diff-lcs (~> 1.4) - e2mmap - jaro_winkler (~> 1.5) + jaro_winkler (~> 1.6, >= 1.6.1) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.1) + logger (~> 1.6) + observer (~> 0.1) + open3 (~> 0.2.1) + ostruct (~> 0.6) parser (~> 3.0) - reverse_markdown (>= 1.0.5, < 3) - rubocop (>= 0.52) + prism (~> 1.4) + rbs (>= 3.6.1, <= 4.0.0.dev.4) + reverse_markdown (~> 3.0) + rubocop (~> 1.76) thor (~> 1.0) tilt (~> 2.0) yard (~> 0.9, >= 0.9.24) + yard-activesupport-concern (~> 0.0) + yard-solargraph (~> 0.1) strings (0.2.1) strings-ansi (~> 0.2) unicode-display_width (>= 1.5, < 3.0) unicode_utils (~> 1.4) strings-ansi (0.2.0) - strscan (3.1.0) - thor (1.2.1) - tilt (2.0.11) - timecop (0.9.6) + strscan (3.1.7) + thor (1.5.0) + tilt (2.7.0) + timecop (0.9.10) + tsort (0.2.0) tty-pager (0.14.0) strings (~> 0.2.0) tty-screen (~> 0.8) - tty-screen (0.8.1) + tty-screen (0.8.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) - unicode-display_width (2.4.2) + unicode-display_width (2.6.0) unicode_utils (1.4.0) - uri (1.0.4) - vcr (6.1.0) - webmock (3.18.1) + uri (1.1.1) + vcr (6.4.0) + webmock (3.26.2) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - yard (0.9.36) + yard (0.9.38) + yard-activesupport-concern (0.0.1) + yard (>= 0.8) + yard-solargraph (0.1.0) + yard (~> 0.9) PLATFORMS aarch64-linux arm64-darwin-23 + arm64-darwin-25 x86_64-darwin-22 x86_64-darwin-23 x86_64-linux DEPENDENCIES - activesupport - addressable - aws-sdk-guardduty - aws-sdk-inspector - aws-sdk-inspector2 - faraday (~> 2.13) - faraday-multipart + activesupport (~> 7.2) + addressable (~> 2.8) + aws-sdk-guardduty (~> 1.62) + aws-sdk-inspector (~> 1.44) + aws-sdk-inspector2 (~> 1.10) + faraday (~> 2.14) + faraday-multipart (~> 1.2) faraday-retry (~> 2.3) - httparty - ipaddress - pry - pry-byebug - rest-client - rexml (>= 3.3.6) - rspec - rspec-github - rubocop - ruby-limiter - sanitize - simplecov - simplecov-cobertura - solargraph - strscan - timecop - tty-pager - vcr (~> 6.1) - webmock (~> 3.18) - yard (>= 0.9.36) + httparty (~> 0.22) + ipaddress (~> 0.8) + pry (~> 0.14) + pry-byebug (~> 3.10) + rest-client (~> 2.1) + rexml (~> 3.4) + rspec (~> 3.13) + rspec-github (~> 2.4) + rubocop (~> 1.69) + ruby-limiter (~> 2.2) + sanitize (~> 6.1) + simplecov (~> 0.22) + simplecov-cobertura (~> 3.1) + solargraph (~> 0.50) + strscan (~> 3.1) + timecop (~> 0.9) + tty-pager (~> 0.14) + vcr (~> 6.3) + webmock (~> 3.24) + yard (~> 0.9, >= 0.9.37) RUBY VERSION - ruby 3.2.2p53 + ruby 3.4.9 BUNDLED WITH - 2.5.15 + 4.0.9 diff --git a/lib/helpers.rb b/lib/helpers.rb index f2cc8409..57c84ea8 100644 --- a/lib/helpers.rb +++ b/lib/helpers.rb @@ -111,10 +111,8 @@ def print_readme(task_name) ### Helper to write a file consistently ### def write_file(directory, filename, output) - FileUtils.mkdir_p directory - - # create full output path - output_path = "#{directory}/#{filename}" + output_path = safe_output_path(directory, filename) + FileUtils.mkdir_p File.dirname(output_path) # write it, char by char to avoid large mem issues File.open(output_path, "wb") do |file| @@ -123,8 +121,8 @@ def write_file(directory, filename, output) end def write_file_stream(directory, filename, autoclose, assets, vuln_defs, version = 1) - output_path = "#{directory}/#{filename}" # FIXME: The method should just take a path, - FileUtils.mkdir_p directory # FIXME: then this could be File.basename(path) + output_path = safe_output_path(directory, filename) + FileUtils.mkdir_p File.dirname(output_path) obj = { "skip_autoclose" => autoclose, @@ -133,9 +131,17 @@ def write_file_stream(directory, filename, autoclose, assets, vuln_defs, version "vuln_defs" => vuln_defs } - File.open(output_path, 'w') do |file| - JSON.dump(obj, file) - end + File.write(output_path, JSON.generate(obj)) + end + + def safe_output_path(directory, filename) + sanitized_filename = File.basename(filename) + resolved = File.expand_path(sanitized_filename, directory) + expected_dir = File.expand_path(directory) + + raise ArgumentError, "Path traversal detected: #{filename} resolves outside #{directory}" unless resolved.start_with?(expected_dir) # :nocov: + + resolved end def run_files_on_kenna_connector(connector_id, api_host, api_token, upload_ids, max_retries = 3) diff --git a/spec/lib/helpers_spec.rb b/spec/lib/helpers_spec.rb index adaaed64..dde50647 100644 --- a/spec/lib/helpers_spec.rb +++ b/spec/lib/helpers_spec.rb @@ -30,5 +30,53 @@ }.to_json ) end + + it 'sanitizes path traversal in filename' do + dir = Dir.mktmpdir + example_class.write_file_stream( + dir, + "../../etc/passwd", + autoclose, + assets, + vuln_defs, + version + ) + expect(File.exist?(File.join(dir, "passwd"))).to be true + expect(File.exist?("/etc/passwd.json")).to be false + FileUtils.rm_rf(dir) + end + end + + describe "#write_file" do + it 'writes content to the file' do + dir = Dir.mktmpdir + example_class.write_file(dir, "test.txt", "hello world") + expect(File.read(File.join(dir, "test.txt"))).to eq("hello world") + FileUtils.rm_rf(dir) + end + + it 'sanitizes path traversal in filename' do + dir = Dir.mktmpdir + example_class.write_file(dir, "../../etc/evil", "content") + expect(File.exist?(File.join(dir, "evil"))).to be true + FileUtils.rm_rf(dir) + end + end + + describe "#safe_output_path" do + it 'returns resolved path for safe inputs' do + path = example_class.safe_output_path("/tmp/output", "report.json") + expect(path).to eq("/tmp/output/report.json") + end + + it 'strips directory components from filename' do + path = example_class.safe_output_path("/tmp/output", "subdir/report.json") + expect(path).to eq("/tmp/output/report.json") + end + + it 'strips traversal sequences from filename' do + path = example_class.safe_output_path("/tmp/output", "../../etc/passwd") + expect(path).to eq("/tmp/output/passwd") + end end end