From 0e89405e14fc48eb49f774014941754b51061b69 Mon Sep 17 00:00:00 2001 From: Roeland van Batenburg Date: Mon, 30 Dec 2024 15:25:43 +1300 Subject: [PATCH 01/17] fix possible KeyError --- lib/sobelow/finding_log.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sobelow/finding_log.ex b/lib/sobelow/finding_log.ex index 702ec696..eb74f380 100644 --- a/lib/sobelow/finding_log.ex +++ b/lib/sobelow/finding_log.ex @@ -110,7 +110,7 @@ defmodule Sobelow.FindingLog do [mod, _] = String.split(finding.type, ":", parts: 2) %{ - ruleId: Sobelow.get_mod(mod).id, + ruleId: Sobelow.get_mod(mod) |> get_in([:id]), message: %{ text: finding.type }, From adf482f59c021ff2869b69d6bab3ccc56744c966 Mon Sep 17 00:00:00 2001 From: Miguel Toyas Pernichi <168015510+mitoperni@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:25:38 +0000 Subject: [PATCH 02/17] Fixed typespec-warning --- lib/sobelow/finding_log.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sobelow/finding_log.ex b/lib/sobelow/finding_log.ex index 702ec696..a9d4cd1c 100644 --- a/lib/sobelow/finding_log.ex +++ b/lib/sobelow/finding_log.ex @@ -108,6 +108,8 @@ defmodule Sobelow.FindingLog do defp format_sarif(finding) do [mod, _] = String.split(finding.type, ":", parts: 2) + mod_struct = Sobelow.get_mod(mod) + rule_id = if is_struct(mod_struct), do: mod_struct.id, else: nil %{ ruleId: Sobelow.get_mod(mod).id, From c1ddd3242eb79f8785eba4b9ffb39472c63aead0 Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Thu, 8 May 2025 18:46:08 -0600 Subject: [PATCH 03/17] Minor tweaks (#1) * Bumped developer dependencies and added ex_coveralls * Actually fixed the typesec error and in a way that passes test * Bumped ubuntu runner vsn and added Elixir 1.17 and 1.18 to the test matrix --------- Co-authored-by: Holden Oullette --- .github/workflows/elixir.yml | 74 +++++++++++++++++++----------------- lib/sobelow/finding_log.ex | 14 ++++++- mix.exs | 15 ++++++-- mix.lock | 19 ++++----- 4 files changed, 73 insertions(+), 49 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 9d1c766f..12a1d6e8 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -12,61 +12,65 @@ env: jobs: mix_test: name: mix test (Elixir ${{matrix.elixir}} | OTP ${{matrix.otp}}) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - - elixir: '1.7.x' + - elixir: "1.7.x" otp: 22.3.4.26 - - elixir: '1.8.x' + - elixir: "1.8.x" otp: 22.3.4.26 - - elixir: '1.9.x' + - elixir: "1.9.x" otp: 22.3.4.26 - - elixir: '1.10.x' + - elixir: "1.10.x" otp: 22.3.4.26 - - elixir: '1.11.x' + - elixir: "1.11.x" otp: 23.3.4.18 - - elixir: '1.12.x' + - elixir: "1.12.x" otp: 24 - - elixir: '1.13.x' + - elixir: "1.13.x" otp: 25.1 - - elixir: '1.14.x' + - elixir: "1.14.x" otp: 25.1 - - elixir: '1.15.x' + - elixir: "1.15.x" otp: 26.0 - - elixir: '1.16.x' + - elixir: "1.16.x" otp: 26.2 + - elixir: "1.17.x" + otp: 27 + - elixir: "1.18.x" + otp: 27 steps: - - name: Setup Elixir - uses: erlef/setup-beam@v1 - with: - otp-version: ${{ matrix.otp }} - elixir-version: ${{ matrix.elixir }} + - name: Setup Elixir + uses: erlef/setup-beam@v1 + with: + otp-version: ${{ matrix.otp }} + elixir-version: ${{ matrix.elixir }} - - name: Checkout Code - uses: actions/checkout@v3 + - name: Checkout Code + uses: actions/checkout@v3 - - name: Install Dependencies - run: | - mix local.hex --force - mix local.rebar --force - mix deps.get --only test + - name: Install Dependencies + run: | + mix local.hex --force + mix local.rebar --force + mix deps.get --only test - - name: Hex Audit - run: mix hex.audit + - name: Hex Audit + run: mix hex.audit - - name: Check Formatting - if: ${{ matrix.elixir == '1.16.x' }} # we only care about formatting for latest version of Elixir - run: mix format --check-formatted + - name: Check Formatting + if: ${{ matrix.elixir == '1.16.x' }} # we only care about formatting for latest version of Elixir + run: mix format --check-formatted - - name: Compiles w/o Warnings - if: ${{ matrix.elixir == '1.16.x' }} # we only care about warnings for latest version of Elixir - run: mix compile --warnings-as-errors + - name: Compiles w/o Warnings + if: ${{ matrix.elixir == '1.16.x' }} # we only care about warnings for latest version of Elixir + run: mix compile --warnings-as-errors - - name: Credo - run: mix credo --all --strict + - name: Credo + run: mix credo --all --strict - - name: Run Tests - run: mix test + - name: Run Tests + run: mix test diff --git a/lib/sobelow/finding_log.ex b/lib/sobelow/finding_log.ex index 678314fd..2d9322c2 100644 --- a/lib/sobelow/finding_log.ex +++ b/lib/sobelow/finding_log.ex @@ -109,10 +109,20 @@ defmodule Sobelow.FindingLog do defp format_sarif(finding) do [mod, _] = String.split(finding.type, ":", parts: 2) mod_struct = Sobelow.get_mod(mod) - rule_id = if is_struct(mod_struct), do: mod_struct.id, else: nil + + # 1) We got a module and exports id/0 ─ call it via apply/3 + rule_id = + if is_atom(mod_struct) and + Code.ensure_loaded?(mod_struct) and + function_exported?(mod_struct, :id, 0) do + apply(mod_struct, :id, []) + else + # 2) Anything else – we have no id + nil + end %{ - ruleId: Sobelow.get_mod(mod) |> get_in([:id]), + ruleId: rule_id, message: %{ text: finding.type }, diff --git a/mix.exs b/mix.exs index 4bbf6418..4890aae8 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Sobelow.Mixfile do use Mix.Project - @source_url "https://github.com/nccgroup/sobelow" + @source_url "https://github.com/sobelow/sobelow" @version "0.13.0" def project do @@ -12,6 +12,14 @@ defmodule Sobelow.Mixfile do build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, deps: deps(), + test_coverage: [tool: ExCoveralls], + preferred_cli_env: [ + coveralls: :test, + "coveralls.detail": :test, + "coveralls.post": :test, + "coveralls.html": :test, + "coveralls.cobertura": :test + ], package: package(), description: "Security-focused static analysis for Elixir & the Phoenix framework", name: "Sobelow", @@ -32,8 +40,9 @@ defmodule Sobelow.Mixfile do {:jason, "~> 1.0"}, # Dev / Test Dependencies - {:ex_doc, "~> 0.20", only: :dev}, - {:credo, "~> 1.6 or ~> 1.7", only: [:dev, :test], runtime: false} + {:ex_doc, "~> 0.37", only: :dev}, + {:credo, "~> 1.7.12", only: [:dev, :test], runtime: false}, + {:excoveralls, "~> 0.18", only: :test} ] end diff --git a/mix.lock b/mix.lock index 9517bce7..8cd47a8f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,12 +1,13 @@ %{ "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "credo": {:hex, :credo, "1.7.4", "68ca5cf89071511c12fd9919eb84e388d231121988f6932756596195ccf7fd35", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9cf776d062c78bbe0f0de1ecaee183f18f2c3ec591326107989b054b7dddefc2"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, - "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, - "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, - "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, + "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, + "ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"}, + "excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"}, + "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, + "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, } From 6ff224478a348130a6fbccc4c6b43542baf3feb7 Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Thu, 8 May 2025 19:05:30 -0600 Subject: [PATCH 04/17] Removed deprecated OTP versions and bumped minimum supported Sobelow version (#2) --- .github/workflows/elixir.yml | 12 +----------- mix.exs | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 12a1d6e8..95bd1ec3 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -12,21 +12,11 @@ env: jobs: mix_test: name: mix test (Elixir ${{matrix.elixir}} | OTP ${{matrix.otp}}) - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: include: - - elixir: "1.7.x" - otp: 22.3.4.26 - - elixir: "1.8.x" - otp: 22.3.4.26 - - elixir: "1.9.x" - otp: 22.3.4.26 - - elixir: "1.10.x" - otp: 22.3.4.26 - - elixir: "1.11.x" - otp: 23.3.4.18 - elixir: "1.12.x" otp: 24 - elixir: "1.13.x" diff --git a/mix.exs b/mix.exs index 4890aae8..9d5b6acb 100644 --- a/mix.exs +++ b/mix.exs @@ -8,7 +8,7 @@ defmodule Sobelow.Mixfile do [ app: :sobelow, version: @version, - elixir: "~> 1.7", + elixir: "~> 1.12", build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, deps: deps(), From db26dcd636cb8828ee8f31343dcdaab4fefe0778 Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Thu, 8 May 2025 19:11:22 -0600 Subject: [PATCH 05/17] Updated default branch to 'main' (#3) --- .github/workflows/elixir.yml | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 95bd1ec3..57cc9332 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -4,7 +4,7 @@ on: pull_request: push: branches: - - master + - main env: MIX_ENV: test diff --git a/mix.exs b/mix.exs index 9d5b6acb..b12050ef 100644 --- a/mix.exs +++ b/mix.exs @@ -51,7 +51,7 @@ defmodule Sobelow.Mixfile do licenses: ["Apache-2.0"], maintainers: ["Griffin Byatt", "Holden Oullette"], links: %{ - "Changelog" => "#{@source_url}/blob/master/CHANGELOG.md", + "Changelog" => "#{@source_url}/blob/main/CHANGELOG.md", "GitHub" => @source_url } ] From 527d1c5420c50eb0a0d14c802f583e6015944b4f Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Thu, 8 May 2025 19:37:23 -0600 Subject: [PATCH 06/17] Merge upstream pr 175 (#4) Co-authored-by: dt <98478153+realcorvus@users.noreply.github.com> --- lib/sobelow/ci/system.ex | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/sobelow/ci/system.ex b/lib/sobelow/ci/system.ex index be029ebe..f3c5c269 100644 --- a/lib/sobelow/ci/system.ex +++ b/lib/sobelow/ci/system.ex @@ -1,6 +1,6 @@ defmodule Sobelow.CI.System do @moduledoc """ - # Command Injection in `System.cmd` + # Command Injection via `System` This submodule of the `CI` module checks for Command Injection vulnerabilities through usage of the `System.cmd` function. @@ -12,7 +12,7 @@ defmodule Sobelow.CI.System do $ mix sobelow -i CI.System """ @uid 2 - @finding_type "CI.System: Command Injection in `System.cmd`" + @finding_type "CI.System: Command Injection via `System` function" use Sobelow.Finding @@ -22,9 +22,17 @@ defmodule Sobelow.CI.System do Finding.init(@finding_type, meta_file.filename, confidence) |> Finding.multi_from_def(fun, parse_def(fun)) |> Enum.each(&Print.add_finding(&1)) + + Finding.init(@finding_type, meta_file.filename, confidence) + |> Finding.multi_from_def(fun, parse_def_shell(fun)) + |> Enum.each(&Print.add_finding(&1)) end def parse_def(fun) do Parse.get_fun_vars_and_meta(fun, 0, :cmd, [:System]) end + + def parse_def_shell(fun) do + Parse.get_fun_vars_and_meta(fun, 0, :shell, [:System]) + end end From d1ba5432c56fb7674d91f7b4852cb1269c0047f8 Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Thu, 8 May 2025 19:56:02 -0600 Subject: [PATCH 07/17] version bump - 0.14.0 (#5) Co-authored-by: Holden Oullette --- CHANGELOG.md | 53 ++++++++++++++++++++++++++++++++++------------------ mix.exs | 2 +- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7877f36c..5bf14749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## v0.14.0 + * Removed + * Support for minimum Elixir versions 1.7 - 1.11 (**POTENTIALLY BREAKING** - only applies if you relied on Elixir 1.7 through 1.11, 1.12+ is still supported) + * Enhancements + * Added support for multiple variations of `SQL.query()` + * Added support for `System.shell' command introduced in Elixir v1.12 + * Ignore runtime config during `Config.HSTS` + * Updated developer dependencies (`ex_doc` & `credo`) + * Bug fixes + * Fixed `is_endpoint?` error in main + * Fixed findings normalization bug + * Fixed truncation error + * Misc + * GitHub Actions test matrix updated (hence the large drop in support for old Elixir versions) + * Addressed compiler warnings from Elixir v1.18.x + * Moved from `master` branch to `main` + ## v0.13.0 * Removed * Support for minimum Elixir versions 1.5 & 1.6 (**POTENTIALLY BREAKING** - only applies if you relied on Elixir 1.5 or 1.6, 1.7+ is still supported) @@ -18,7 +35,7 @@ * Compiler Warnings as Errors * Checks Formatting * Added helper `mix test.all` alias - + ## v0.12.2 * Bug fixes * Removed `:castore` and introduced `:verify_none` to quiet warning and unblock escript usage, see [#133](https://github.com/nccgroup/sobelow/issues/133) for more context on why this is necessary @@ -55,19 +72,19 @@ ## v0.11.1 * Enhancements * Sarif output with `--out` flag - * `--strict` flag, which throws compilation errors instead of suppressing them. + * `--strict` flag, which throws compilation errors instead of suppressing them. ## v0.11.0 * Enhancements * Sarif output for GitHub integration * `--flycheck` flag, which reverses output of `--compact` * Bug fixes - * Non-compiling files now return an empty syntax tree instead of + * Non-compiling files now return an empty syntax tree instead of causing Sobelow errors. * Command Injection finding description are properly formatted * Misc - * If you use Sobelow as a standalone utility (i.e. not as part of - a Phoenix application), you now need to install as an escript with + * If you use Sobelow as a standalone utility (i.e. not as part of + a Phoenix application), you now need to install as an escript with `mix escript.install hex sobelow`. * Custom JSON serialization replaced with Jason. @@ -105,7 +122,7 @@ ## v0.9.3 * Enhancements * Improved checks for all aliased functions - + * Bug Fixes * JSON output for Raw findings is now properly normalized * `send_download` correctly flags aliased function calls @@ -124,7 +141,7 @@ * Add `--mark-skip-all` and `--clear-skip` flags * New CSRF via action reuse checks * Sobelow can now be run in umbrella apps - + * Bug Fixes * Fix an error when printing some kinds of variables @@ -134,26 +151,26 @@ * All JSON findings contain `type`, `file`, and `line` keys * "Line" output now refers directly to the vulnerable line * Default output headers have been normalized - - **Note:** If you depend on the structure of the output, this - may be a breaking change. More information can be found at + + **Note:** If you depend on the structure of the output, this + may be a breaking change. More information can be found at [https://sobelow.io](https://sobelow.io). ## v0.7.8 * Enhancements * Add `--threshold` flag * Add module names to finding output - + * Deprecations - * File/Path check has been deprecated - + * File/Path check has been deprecated + * Bug Fixes * Fix inaccurate CSRF details ## v0.7.7 * Enhancements * Add check for insecure websocket settings - + * Bug Fixes * Accept module attributes for application name @@ -231,7 +248,7 @@ * Bug Fixes * Allow RCE module to be appropriately ignored. - + ## v0.6.4 * Enhancements @@ -241,8 +258,8 @@ * Enhancements * Add RCE module to check for code execution via `Code` and `EEx`. - + * Deprecations - * The `--with-code` flag has been changed to `--verbose`. The `--with-code` - flag will continue to work as expected until v1.0.0, but will print a + * The `--with-code` flag has been changed to `--verbose`. The `--with-code` + flag will continue to work as expected until v1.0.0, but will print a warning message. diff --git a/mix.exs b/mix.exs index b12050ef..9101cc44 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule Sobelow.Mixfile do use Mix.Project @source_url "https://github.com/sobelow/sobelow" - @version "0.13.0" + @version "0.14.0" def project do [ From 921420d18cfa905be4f2e4e977968a7ec8f1fa95 Mon Sep 17 00:00:00 2001 From: Kian-Meng Ang Date: Sat, 10 May 2025 00:55:46 +0800 Subject: [PATCH 08/17] Fix typo, comapring -> comparing (#6) --- lib/mix/tasks/sobelow.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mix/tasks/sobelow.ex b/lib/mix/tasks/sobelow.ex index 34cf37fa..d28fee11 100644 --- a/lib/mix/tasks/sobelow.ex +++ b/lib/mix/tasks/sobelow.ex @@ -198,7 +198,7 @@ defmodule Mix.Tasks.Sobelow do # This diff check is strictly used for testing/debugging and # isn't meant for general use. # - # Useful for comapring the output of two different runs of Sobelow + # Useful for comparing the output of two different runs of Sobelow def run_diff(argv) do diff_idx = Enum.find_index(argv, fn i -> i === "--diff" end) {_, list} = List.pop_at(argv, diff_idx) From ed6e7cf9fad2f60228de61efedc2fa9ed7027c3b Mon Sep 17 00:00:00 2001 From: Mike Zornek Date: Sun, 18 May 2025 00:54:42 -0400 Subject: [PATCH 09/17] Update README.md (#8) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c38bfb28..602cd172 100644 --- a/README.md +++ b/README.md @@ -68,10 +68,10 @@ from the command line: $ mix escript.install hex sobelow -To install from the master branch, rather than the latest release, +To install from the `main` branch, rather than the latest release, the following command can be used: - $ mix escript.install github nccgroup/sobelow + $ mix escript.install github sobelow/sobelow ### To Use From 80e731c797678fad0b14af19220bc7e001017bfd Mon Sep 17 00:00:00 2001 From: Holden Oullette <6202965+houllette@users.noreply.github.com> Date: Sun, 25 May 2025 14:03:43 -0600 Subject: [PATCH 10/17] Handle Release Config (#7) (#10) --- CHANGELOG.md | 4 ++++ lib/sobelow/utils.ex | 3 ++- test/fixtures/utils/mix_with_releases.exs | 18 ++++++++++++++++++ .../utils/mix_with_releases_my_app.exs | 18 ++++++++++++++++++ test/fixtures/utils/mix_with_releases_test.exs | 18 ++++++++++++++++++ test/utils_test.exs | 14 ++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/utils/mix_with_releases.exs create mode 100644 test/fixtures/utils/mix_with_releases_my_app.exs create mode 100644 test/fixtures/utils/mix_with_releases_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bf14749..51a30211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.14.1 (Unreleased) + * Bug fixes + * Handled extra config options for app releases in mix.exs + ## v0.14.0 * Removed * Support for minimum Elixir versions 1.7 - 1.11 (**POTENTIALLY BREAKING** - only applies if you relied on Elixir 1.7 through 1.11, 1.12+ is still supported) diff --git a/lib/sobelow/utils.ex b/lib/sobelow/utils.ex index 59f58778..19113633 100644 --- a/lib/sobelow/utils.ex +++ b/lib/sobelow/utils.ex @@ -94,7 +94,8 @@ defmodule Sobelow.Utils do end defp extract_app_name(ast, acc) do - if Keyword.keyword?(ast) && Keyword.get(ast, :app) do + # Only extract the first app name found, don't overwrite with subsequent ones + if acc == [] && Keyword.keyword?(ast) && Keyword.get(ast, :app) do {ast, Keyword.get(ast, :app)} else {ast, acc} diff --git a/test/fixtures/utils/mix_with_releases.exs b/test/fixtures/utils/mix_with_releases.exs new file mode 100644 index 00000000..d413f301 --- /dev/null +++ b/test/fixtures/utils/mix_with_releases.exs @@ -0,0 +1,18 @@ +defmodule App.Mixfile do + use Mix.Project + + def project do + [ + app: :app, + version: "0.1.0", + releases: [ + app: [ + applications: [ + opentelemetry_exporter: :permanent, + opentelemetry: :temporary + ] + ] + ] + ] + end +end diff --git a/test/fixtures/utils/mix_with_releases_my_app.exs b/test/fixtures/utils/mix_with_releases_my_app.exs new file mode 100644 index 00000000..6a9eb53e --- /dev/null +++ b/test/fixtures/utils/mix_with_releases_my_app.exs @@ -0,0 +1,18 @@ +defmodule MyApp.Mixfile do + use Mix.Project + + def project do + [ + app: :my_app, + version: "0.1.0", + releases: [ + my_app: [ + applications: [ + opentelemetry_exporter: :permanent, + opentelemetry: :temporary + ] + ] + ] + ] + end +end diff --git a/test/fixtures/utils/mix_with_releases_test.exs b/test/fixtures/utils/mix_with_releases_test.exs new file mode 100644 index 00000000..4e016d76 --- /dev/null +++ b/test/fixtures/utils/mix_with_releases_test.exs @@ -0,0 +1,18 @@ +defmodule Test.Mixfile do + use Mix.Project + + def project do + [ + app: :test, + version: "0.1.0", + releases: [ + test: [ + applications: [ + opentelemetry_exporter: :permanent, + opentelemetry: :temporary + ] + ] + ] + ] + end +end diff --git a/test/utils_test.exs b/test/utils_test.exs index fe64a682..dedf5e76 100644 --- a/test/utils_test.exs +++ b/test/utils_test.exs @@ -4,4 +4,18 @@ defmodule SobelowTest.UtilsTest do test "Utils.get_app_name/1 understands module attributes" do assert Sobelow.Utils.get_app_name("./test/fixtures/utils/mix.exs") == "foo_bar" end + + test "Utils.get_app_name/1 handles releases config correctly for app named :app" do + assert Sobelow.Utils.get_app_name("./test/fixtures/utils/mix_with_releases.exs") == "app" + end + + test "Utils.get_app_name/1 handles releases config correctly for app named :my_app" do + assert Sobelow.Utils.get_app_name("./test/fixtures/utils/mix_with_releases_my_app.exs") == + "my_app" + end + + test "Utils.get_app_name/1 handles releases config correctly for app named :test" do + assert Sobelow.Utils.get_app_name("./test/fixtures/utils/mix_with_releases_test.exs") == + "test" + end end From f70522aaeb9be634263a88c723f838ce09f55147 Mon Sep 17 00:00:00 2001 From: Michael Lubas <98478153+realcorvus@users.noreply.github.com> Date: Mon, 13 Oct 2025 20:28:56 -0400 Subject: [PATCH 11/17] Fix skips (#17) --- lib/sobelow.ex | 68 +++++++++++++++++++++++++++++++++++++----- lib/sobelow/finding.ex | 21 +++++++++++-- lib/sobelow/print.ex | 8 ++--- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/lib/sobelow.ex b/lib/sobelow.ex index e7860564..97096a2c 100644 --- a/lib/sobelow.ex +++ b/lib/sobelow.ex @@ -209,14 +209,17 @@ defmodule Sobelow do end def log_finding(details, %Finding{} = finding) do - if loggable?(finding.fingerprint, finding.confidence) do + if loggable?(finding, finding.confidence) do Fingerprint.put(finding.fingerprint) FindingLog.add({details, finding}, finding.confidence) end end - def loggable?(fingerprint, severity) do - !(get_env(:skip) && Fingerprint.member?(fingerprint)) && + def loggable?(%Finding{} = finding, severity) do + legacy_skip = finding.legacy_fingerprint && Fingerprint.member?(finding.legacy_fingerprint) + new_skip = finding.fingerprint && Fingerprint.member?(finding.fingerprint) + + !(get_env(:skip) && (new_skip || legacy_skip)) && meets_threshold?(severity) end @@ -474,10 +477,41 @@ defmodule Sobelow do [] -> nil - fingerprints -> + new_fingerprints -> + # Get all findings from the log to match fingerprints to finding details + %{high: highs, medium: meds, low: lows} = FindingLog.log() + all_findings = highs ++ meds ++ lows + + # Create a map of fingerprint -> finding for quick lookup + fingerprint_to_finding = + all_findings + |> Enum.map(fn {_details, finding} -> {finding.fingerprint, finding} end) + |> Map.new() + + # Build skip entries in new format: type,filename_line_n,hash + skip_entries = + new_fingerprints + |> Enum.map(fn fingerprint -> + case Map.get(fingerprint_to_finding, fingerprint) do + %Finding{} = finding -> + # Get relative filename (remove project root) + filename = + Utils.get_root() + |> Utils.normalize_path() + |> (&String.replace_prefix(finding.filename, &1, "")).() + |> Utils.normalize_path() + + "#{finding.type},#{filename}:#{finding.vuln_line_no},#{fingerprint}" + + nil -> + # Should not happen, each fingerprint should have a corresponding finding + fingerprint + end + end) + {:ok, iofile} = :file.open(cfile, [:append]) - fingerprints = Enum.join(fingerprints, "\n") - :file.write(iofile, ["\n", fingerprints]) + entries_str = Enum.join(skip_entries, "\n") + :file.write(iofile, ["\n", entries_str]) :file.close(iofile) end end @@ -493,8 +527,26 @@ defmodule Sobelow do end end - defp load_ignored_fingerprints({:ok, fingerprint}, iofile) do - to_string(fingerprint) |> String.trim() |> Fingerprint.put_ignore() + defp load_ignored_fingerprints({:ok, line}, iofile) do + line_str = to_string(line) |> String.trim() + + # Parse line - could be old format (just hash) or new format (type,filename_line_n,hash) + fingerprint = + case String.split(line_str, ",") do + [fingerprint] when fingerprint != "" -> + # Old format: just the fingerprint hash + fingerprint + + [_type, _filename_line_n, fingerprint] when fingerprint != "" -> + # New format: type,filename_line_n,phash2 - extract phash2 + fingerprint + + _ -> + # Invalid line, skip it + nil + end + + if fingerprint, do: Fingerprint.put_ignore(fingerprint) :file.read_line(iofile) |> load_ignored_fingerprints(iofile) end diff --git a/lib/sobelow/finding.ex b/lib/sobelow/finding.ex index 69e7b4c7..025a329f 100644 --- a/lib/sobelow/finding.ex +++ b/lib/sobelow/finding.ex @@ -12,7 +12,8 @@ defmodule Sobelow.Finding do :fun_name, :fun_line_no, :fun_source, - :fingerprint + :fingerprint, + :legacy_fingerprint ] alias Sobelow.Utils @@ -42,7 +43,11 @@ defmodule Sobelow.Finding do end def fetch_fingerprint(%Sobelow.Finding{} = finding) do - %{finding | fingerprint: fingerprint(finding)} + %{ + finding + | fingerprint: fingerprint(finding), + legacy_fingerprint: legacy_fingerprint(finding) + } end def fingerprint(%Sobelow.Finding{} = finding) do @@ -52,6 +57,18 @@ defmodule Sobelow.Finding do |> (&String.replace_prefix(finding.filename, &1, "")).() |> Utils.normalize_path() + [finding.type, finding.vuln_source, filename, finding.vuln_line_no] + |> :erlang.phash2() + |> Integer.to_string(16) + end + + def legacy_fingerprint(%Sobelow.Finding{} = finding) do + filename = + Utils.get_root() + |> Utils.normalize_path() + |> (&String.replace_prefix(finding.filename, &1, "")).() + |> Utils.normalize_path() + [finding.type, finding.vuln_source, filename, finding.vuln_line_no] |> :erlang.term_to_binary() |> :erlang.md5() diff --git a/lib/sobelow/print.ex b/lib/sobelow/print.ex index 6d8d501a..75de649a 100644 --- a/lib/sobelow/print.ex +++ b/lib/sobelow/print.ex @@ -25,7 +25,7 @@ defmodule Sobelow.Print do end def print_finding_metadata(%Finding{} = finding) do - if Sobelow.loggable?(finding.fingerprint, finding.confidence) do + if Sobelow.loggable?(finding, finding.confidence) do do_print_finding_metadata(finding) end end @@ -41,7 +41,7 @@ defmodule Sobelow.Print do end def print_custom_finding_metadata(%Finding{} = finding, headers) do - if Sobelow.loggable?(finding.fingerprint, finding.confidence) do + if Sobelow.loggable?(finding, finding.confidence) do do_print_custom_finding_metadata(finding, headers) end end @@ -65,7 +65,7 @@ defmodule Sobelow.Print do end defp print_compact_finding(finding, details) do - if Sobelow.loggable?(finding.fingerprint, finding.confidence) do + if Sobelow.loggable?(finding, finding.confidence) do do_print_compact_finding(details, finding.confidence) end end @@ -89,7 +89,7 @@ defmodule Sobelow.Print do end defp print_flycheck_finding(finding, details) do - if Sobelow.loggable?(finding.fingerprint, finding.confidence) do + if Sobelow.loggable?(finding, finding.confidence) do do_print_flycheck_finding(details, finding.confidence) end end From 8af1d2f7d9e8b64f4ea2b55a6cf4faaeb5618ec6 Mon Sep 17 00:00:00 2001 From: Eksperimental Date: Mon, 13 Oct 2025 19:30:01 -0500 Subject: [PATCH 12/17] Use `warn_if_outdated` option in Mix deps (#16) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 602cd172..84453474 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ To use Sobelow, you can add it to your application's dependencies. ```elixir def deps do [ - {:sobelow, "~> 0.13", only: [:dev, :test], runtime: false} + {:sobelow, "~> 0.14", only: [:dev, :test], runtime: false, warn_if_outdated: true} ] end ``` From 0c03e81ac6827eb89ce55f20ea54b5d7c53e532c Mon Sep 17 00:00:00 2001 From: AJ Foster <2789166+aj-foster@users.noreply.github.com> Date: Mon, 13 Oct 2025 20:32:29 -0400 Subject: [PATCH 13/17] Fix Format & Warnings Check in CI (#12) Co-authored-by: Holden Oullette <6202965+houllette@users.noreply.github.com> --- .github/workflows/elixir.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 57cc9332..bb044143 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -31,6 +31,8 @@ jobs: otp: 27 - elixir: "1.18.x" otp: 27 + # We only care about formatting and warnings for the latest version of Elixir + checkFormatAndWarnings: true steps: - name: Setup Elixir @@ -52,11 +54,11 @@ jobs: run: mix hex.audit - name: Check Formatting - if: ${{ matrix.elixir == '1.16.x' }} # we only care about formatting for latest version of Elixir + if: ${{ matrix.checkFormatAndWarnings }} run: mix format --check-formatted - name: Compiles w/o Warnings - if: ${{ matrix.elixir == '1.16.x' }} # we only care about warnings for latest version of Elixir + if: ${{ matrix.checkFormatAndWarnings }} run: mix compile --warnings-as-errors - name: Credo From 005d24c8e0654df7a1112b292369206919a8fe0c Mon Sep 17 00:00:00 2001 From: Jon Carstens Date: Mon, 13 Oct 2025 18:35:41 -0600 Subject: [PATCH 14/17] Support options from task and config (#9) --- CHANGELOG.md | 8 ++++++++ README.md | 11 +++++------ lib/mix/tasks/sobelow.ex | 39 ++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51a30211..90a13d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Changelog ## v0.14.1 (Unreleased) + * Enhancements + * Implicitly use `.sobelow-conf` if detected in the root directory rather than + require `--config` switch. The `--no-config` switch is still supported to + prevent any settings from being read in from the file if needed. + * Bug fixes * Handled extra config options for app releases in mix.exs + * Properly handle the use of CLI switches and config file settings in the same run. + These would previously clobber each other in unapparent ways leading to + confusing behavior. CLI switch take precedence. ## v0.14.0 * Removed diff --git a/README.md b/README.md index 84453474..eb470901 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ relative to the application root. line options. See [Configuration Files](#configuration-files) for more information. - * `--config` - Run Sobelow with configuration file. See [Configuration Files](#configuration-files) + * `--[no-]config` - Run Sobelow with or without configuration file. See [Configuration Files](#configuration-files) for more information. * `--mark-skip-all` - Mark all displayed findings as skippable. @@ -170,10 +170,9 @@ when you first start out using this package - the generated configuration file will be populated with the default values for each option. (This helps in quickly incorporating this package into a pre-existing codebase.) -Now if you want to run Sobelow with the saved configuration, -you can run Sobelow with the `--config` flag. - - $ mix sobelow --config +The `.sobelow-conf` file is automatically used if detected. CLI switches will +take precedence over options in the config file. You can also specify +`--no-config` to prevent any config file settings being used if needed. ## False Positives Sobelow favors over-reporting versus under-reporting. As such, @@ -226,7 +225,7 @@ defp aliases do end ``` -If you wish to use configuration files in an umbrella app, create a `.sobelow-conf` in each child application and use the `--config` flag. +If you wish to use configuration files in an umbrella app, create a `.sobelow-conf` in each child application. ## Updates When scanning a project, Sobelow will occasionally check for diff --git a/lib/mix/tasks/sobelow.ex b/lib/mix/tasks/sobelow.ex index d28fee11..bd170c05 100644 --- a/lib/mix/tasks/sobelow.ex +++ b/lib/mix/tasks/sobelow.ex @@ -30,7 +30,7 @@ defmodule Mix.Tasks.Sobelow do * `--quiet` - Return no output if there are no findings * `--compact` - Minimal, single-line findings * `--save-config` - Generates a configuration file based on command line options - * `--config` - Run Sobelow with configuration file + * `--[no-]config` - Run Sobelow with or without the configuration file. * `--version` - Output current version of Sobelow ## Ignoring modules @@ -121,7 +121,7 @@ defmodule Mix.Tasks.Sobelow do {opts, _, _} = OptionParser.parse(argv, aliases: @aliases, switches: @switches) root = Keyword.get(opts, :root, ".") - config = Keyword.get(opts, :config, false) + config = Keyword.get(opts, :config, true) conf_file = root <> "/.sobelow-conf" conf_file? = config && File.exists?(conf_file) @@ -134,15 +134,15 @@ defmodule Mix.Tasks.Sobelow do opts = if conf_file? do - {:ok, opts} = File.read!(conf_file) |> Code.string_to_quoted() - opts + {:ok, file_opts} = File.read!(conf_file) |> Code.string_to_quoted() + # CLI args take precedence + Keyword.merge(file_opts, opts) else opts end {verbose, diff, details, private, strict, skip, mark_skip_all, clear_skip, router, exit_on, - format, ignored, ignored_files, all_details, out, threshold, - version} = get_opts(opts, root, conf_file?) + format, ignored, ignored_files, all_details, out, threshold, version} = get_opts(opts, root) set_env(:verbose, verbose) @@ -214,7 +214,7 @@ defmodule Mix.Tasks.Sobelow do Application.put_env(:sobelow, key, value) end - defp get_opts(opts, root, conf_file?) do + defp get_opts(opts, root) do verbose = Keyword.get(opts, :verbose, false) details = Keyword.get(opts, :details, nil) all_details = Keyword.get(opts, :all_details) @@ -249,22 +249,19 @@ defmodule Mix.Tasks.Sobelow do format = out_format(out, format) - {ignored, ignored_files} = - if conf_file? do - {Keyword.get(opts, :ignore, []), - Keyword.get(opts, :ignore_files, []) |> Enum.map(&Path.expand(&1, root))} - else - ignored = - Keyword.get(opts, :ignore, "") - |> String.split(",") + ignored = + case Keyword.get(opts, :ignore, []) do + ignore_str when is_binary(ignore_str) -> String.split(ignore_str, ",") + ignore -> ignore + end - ignored_files = - Keyword.get(opts, :ignore_files, "") - |> String.split(",") - |> Enum.reject(fn file -> file == "" end) - |> Enum.map(&Path.expand(&1, root)) + ignored_files = + case Keyword.get(opts, :ignore_files, []) do + ignore_files when is_list(ignore_files) -> + Enum.map(ignore_files, &Path.expand(&1, root)) - {ignored, ignored_files} + ignore_files_str when is_binary(ignore_files_str) -> + for i <- String.split(ignore_files_str, ",", trim: true), do: Path.expand(i, root) end threshold = From 40158aea7fec62b93fa1b9118b3880d03b912721 Mon Sep 17 00:00:00 2001 From: Roeland van Batenburg Date: Tue, 14 Oct 2025 13:37:25 +1300 Subject: [PATCH 15/17] fix warning from zero arg functions from endpoint (#13) --- lib/sobelow/parse.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sobelow/parse.ex b/lib/sobelow/parse.ex index 27d1d265..6ee68e16 100644 --- a/lib/sobelow/parse.ex +++ b/lib/sobelow/parse.ex @@ -461,7 +461,7 @@ defmodule Sobelow.Parse do end end - defp create_fun_cap(fun, meta, idx) when is_number(idx) do + defp create_fun_cap(fun, meta, idx) when is_number(idx) and idx > 0 do opts = Enum.map(1..trunc(idx), fn i -> {:&, [], [i]} end) {fun, meta, opts} end From 93ab93fe10e2d403b017645cc24c6507a9dce3be Mon Sep 17 00:00:00 2001 From: Eksperimental Date: Mon, 13 Oct 2025 19:38:18 -0500 Subject: [PATCH 16/17] Sort elements in .sobelow-conf alphabetically (#14) --- lib/sobelow.ex | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/sobelow.ex b/lib/sobelow.ex index 97096a2c..51c0aa8e 100644 --- a/lib/sobelow.ex +++ b/lib/sobelow.ex @@ -242,16 +242,16 @@ defmodule Sobelow do def save_config(conf_file) do conf = [ - verbose: get_env(:verbose), - private: get_env(:private), - skip: get_env(:skip), - router: get_env(:router), exit: get_env(:exit_on), format: get_env(:format), + ignore_files: get_env(:ignored_files), + ignore: get_env(:ignored), out: get_env(:out), + private: get_env(:private), + router: get_env(:router), + skip: get_env(:skip), threshold: get_env(:threshold), - ignore: get_env(:ignored), - ignore_files: get_env(:ignored_files), + verbose: get_env(:verbose), version: get_env(:version) ] @@ -263,7 +263,7 @@ defmodule Sobelow do end if yes? do - File.write!(conf_file, inspect(conf)) + File.write!(conf_file, inspect(conf, limit: :infinity, printable_limit: :infinity)) MixIO.info("Updated .sobelow-conf") end end From 23f3b22edb88559ae4bf66be43c70d53b9767535 Mon Sep 17 00:00:00 2001 From: Holden Oullette Date: Mon, 13 Oct 2025 18:48:45 -0600 Subject: [PATCH 17/17] version bump - 0.14.1 --- .github/workflows/elixir.yml | 2 ++ CHANGELOG.md | 11 +++++++++-- README.md | 4 ++-- mix.exs | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index bb044143..fa6d59d8 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -31,6 +31,8 @@ jobs: otp: 27 - elixir: "1.18.x" otp: 27 + - elixir: "1.19.x" + otp: 28 # We only care about formatting and warnings for the latest version of Elixir checkFormatAndWarnings: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 90a13d7b..46b4c7e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,23 @@ # Changelog -## v0.14.1 (Unreleased) +## v0.14.1 * Enhancements * Implicitly use `.sobelow-conf` if detected in the root directory rather than require `--config` switch. The `--no-config` switch is still supported to prevent any settings from being read in from the file if needed. - + * Added guidance for `warn_if_outdated` option in mix deps + * Added support for Elixir v1.19.x * Bug fixes * Handled extra config options for app releases in mix.exs * Properly handle the use of CLI switches and config file settings in the same run. These would previously clobber each other in unapparent ways leading to confusing behavior. CLI switch take precedence. + * `.sobelow-conf` now sorted alphabetically + * Fix edwarning from zero argument functions + * Fixed broken skip funcationality + * Fixed broken GitHub Actions CI + * Misc + * Typo fix ## v0.14.0 * Removed diff --git a/README.md b/README.md index eb470901..e8afd44c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/sobelow/) [![Total Download](https://img.shields.io/hexpm/dt/sobelow.svg)](https://hex.pm/packages/sobelow) [![License](https://img.shields.io/hexpm/l/sobelow.svg)](https://hex.pm/packages/sobelow) -[![Last Updated](https://img.shields.io/github/last-commit/nccgroup/sobelow.svg)](https://github.com/nccgroup/sobelow/commits/master) +[![Last Updated](https://img.shields.io/github/last-commit/sobelow/sobelow.svg)](https://github.com/sobelow/sobelow/commits/main) Sobelow is a security-focused static analysis tool for Elixir & the Phoenix framework. For security researchers, it is a useful @@ -212,7 +212,7 @@ This list, and other helpful information, can be found on the command line: $ mix help sobelow - + ## Umbrella Apps In order to run Sobelow against all child apps within an umbrella app with a single command, you can add an alias for sobelow in your root `mix.exs` file: diff --git a/mix.exs b/mix.exs index 9101cc44..21c899a6 100644 --- a/mix.exs +++ b/mix.exs @@ -2,7 +2,7 @@ defmodule Sobelow.Mixfile do use Mix.Project @source_url "https://github.com/sobelow/sobelow" - @version "0.14.0" + @version "0.14.1" def project do [