Basics
This check is disabled by default.
Learn how to enable it via .credo.exs.
This check has a base priority of high and works with any version of Elixir.
Explanation
Flags Repo reads in handle_event/3 and handle_params/3 that look
a record up by a client-sent param, in a clause that never consults
the current user or scope. Event and URL params come from the client:
any user can send any id.
Before:
def handle_event("delete", %{"id" => id}, socket) do
post = Repo.get!(Post, id)
{:ok, _} = Repo.delete(post)
{:noreply, socket}
endAfter:
def handle_event("delete", %{"id" => id}, socket) do
post = Blog.get_post!(socket.assigns.current_scope, id)
{:ok, _} = Blog.delete_post(socket.assigns.current_scope, post)
{:noreply, socket}
endA param taints the variables it flows into through =, <-, and
pipes, within the clause; calls into helpers are not followed. A
clause that reads one of scope_assigns (socket.assigns.current_user,
or a %{assigns: %{current_user: user}} pattern) or calls a function
matching authorizers counts as scoped. Modules matching
excluded_modules are skipped. Ash calls are not Repo calls: Ash
policies authorize them.
Context functions count as lookups too: a call into one of the
project's own modules whose Mod.fun name matches lookup_functions
(by default get_* and fetch_*, such as Blog.get_post!(id)).
Calls into dependencies, the standard library, and modules that use
an Ash module (domains and resources) never match.
An app that keeps its scope under another assign, such as :subject
or :current_account, reports every clause until scope_assigns
names it:
{Soundcheck.Check.Warning.UnscopedLookupByClientParam,
[scope_assigns: [:subject]]}Confidence: medium. Tier: syntactic (works without compiling).
Check-Specific Parameters
Use the following parameters to configure this check:
:excluded_paths
Paths to skip (atoms, binaries as path segments, or regexes).
This parameter defaults to [~r/\/test\//, "test"].
:strict
Unused.
This parameter defaults to false.
:repo_modules
Repo modules: atoms or regexes on the alias-expanded name.
This parameter defaults to [~r/\.Repo$/].
:lookup_functions
Context lookups in the project's own modules: Mod.fun names, regexes or exact.
This parameter defaults to [~r/\.get_\w+!?$/, ~r/\.fetch_\w+!?$/].
:scope_assigns
Assign keys whose use counts as scoping the clause.
This parameter defaults to [:current_scope, :current_user].
:authorizers
Function names (fun or Mod.fun, regexes or exact) that authorize.
This parameter defaults to [~r/authoriz/, ~r/permit/, ~r/can\?$/, ~r/allowed\?$/].
:excluded_modules
Modules to skip: atoms or regexes.
This parameter defaults to [~r/Admin/].
General Parameters
Like with all checks, general params can be applied.
Parameters can be configured via the .credo.exs config file.