From 2e3732e38bc86b2b4cfa23e8e0315b263369daff Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Sat, 7 Mar 2026 18:37:24 +0000 Subject: [PATCH] Apply all necessary exclusions to sobelow findings --- .sobelow-conf | 4 +++- lib/music_library/scrobble_rules.ex | 3 +++ lib/music_library_web/components/core_components.ex | 2 ++ lib/music_library_web/components/record_form.ex | 3 +++ lib/music_library_web/controllers/asset_controller.ex | 2 +- lib/music_library_web/live/artist_live/form.ex | 3 +++ 6 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.sobelow-conf b/.sobelow-conf index 2ae4b899..9f4df1ee 100644 --- a/.sobelow-conf +++ b/.sobelow-conf @@ -4,7 +4,9 @@ ignore_files: [], ignore: [ # Enabled via config/runtime.exs - "Config.HTTPS" + "Config.HTTPS", + # Placeholder values overridden in runtime.exs from env vars + "Config.Secrets" ], out: nil, private: false, diff --git a/lib/music_library/scrobble_rules.ex b/lib/music_library/scrobble_rules.ex index fbcb9ea1..4a78c7e8 100644 --- a/lib/music_library/scrobble_rules.ex +++ b/lib/music_library/scrobble_rules.ex @@ -497,6 +497,9 @@ defmodule MusicLibrary.ScrobbleRules do end) end + # column and json_path are hardcoded string literals from internal callers, + # never user input. All user-derived values use parameterized ? placeholders. + # sobelow_skip ["SQL.Query"] defp apply_all_rules_for_column(rules, column, json_path, tracks) do {case_clauses, case_params} = Enum.reduce(rules, {"", []}, fn rule, {sql_acc, params_acc} -> diff --git a/lib/music_library_web/components/core_components.ex b/lib/music_library_web/components/core_components.ex index ea3a3749..08720a26 100644 --- a/lib/music_library_web/components/core_components.ex +++ b/lib/music_library_web/components/core_components.ex @@ -133,6 +133,8 @@ defmodule MusicLibraryWeb.CoreComponents do """ end + # Renders syntax-highlighted JSON from internal debug structs, not user input. + # sobelow_skip ["XSS.Raw"] defp format_debug_data(%{type: :json, data: data}) do data |> Jason.encode!(pretty: true) diff --git a/lib/music_library_web/components/record_form.ex b/lib/music_library_web/components/record_form.ex index 07842625..41dbe751 100644 --- a/lib/music_library_web/components/record_form.ex +++ b/lib/music_library_web/components/record_form.ex @@ -430,6 +430,9 @@ defmodule MusicLibraryWeb.Components.RecordForm do {:noreply, assign(socket, form: to_form(changeset, action: :validate))} end + # path comes from Phoenix's consume_uploaded_entries callback — + # a framework-generated temp file path, not user input. + # sobelow_skip ["Traversal.FileModule"] def handle_event("save", %{"record" => record_params}, socket) do uploaded_covers = consume_uploaded_entries(socket, :cover_data, fn %{path: path}, entry -> diff --git a/lib/music_library_web/controllers/asset_controller.ex b/lib/music_library_web/controllers/asset_controller.ex index 222e14dc..548122be 100644 --- a/lib/music_library_web/controllers/asset_controller.ex +++ b/lib/music_library_web/controllers/asset_controller.ex @@ -75,7 +75,7 @@ defmodule MusicLibraryWeb.AssetController do # Format is always resolved to either "image/webp" or "image/jpeg" in # pick_format/1, so it's safe. - # sobelow_skip ["XSS.ContentType"] + # sobelow_skip ["XSS.ContentType", "XSS.SendResp"] defp respond_with_cache(conn, data, format, etag) do conn |> put_resp_content_type(format, "utf-8") diff --git a/lib/music_library_web/live/artist_live/form.ex b/lib/music_library_web/live/artist_live/form.ex index 774cb7b1..64a3a7a2 100644 --- a/lib/music_library_web/live/artist_live/form.ex +++ b/lib/music_library_web/live/artist_live/form.ex @@ -195,6 +195,9 @@ defmodule MusicLibraryWeb.ArtistLive.Form do {:noreply, assign(socket, form: to_form(changeset, action: :validate))} end + # path comes from Phoenix's consume_uploaded_entries callback — + # a framework-generated temp file path, not user input. + # sobelow_skip ["Traversal.FileModule"] def handle_event("save", params, socket) do artist_info_params = params["artist_info"] || %{}