# `ExQuality.Stages.Sobelow`
[🔗](https://github.com/riddler/ex_quality/blob/v0.16.0/lib/ex_quality/stages/sobelow.ex#L1)

Runs Sobelow security static analysis on Phoenix applications.

Sobelow reports findings at three confidence levels, but only the ones at or
above the project's `exit:` threshold actually block a build. Printing all
three levels on every run trains a reader to ignore the output, so this stage
separates the two: findings at or above the threshold are reported as
`severity: :error` and rendered, and the rest are reported as a count only.

    ✗ Sobelow: 2 blocking findings (1 high, 1 medium), 3 informational not shown

Set `sobelow: [show_informational: true]` in `.quality.exs`, or pass
`--verbose`, to render the informational ones too.

## Threshold

The `exit:` setting in `.sobelow-conf` decides what blocks. It is the
project's security decision, so it wins over anything in `.quality.exs`;
`sobelow: [exit: "high"]` there only supplies a default for a project with no
`.sobelow-conf`, and the default when neither says is `"medium"`.

ExQuality never proposes editing `.sobelow-conf` as a remedy. A tool that
silences its own findings to go green is a regression dressed as a pass.

## How the tool is invoked

`mix sobelow --config` replaces every other command line option with the
contents of `.sobelow-conf`, including the output format, so this stage reads
that file itself and passes the parts it understands (`ignore`,
`ignore_files`, `router`, `skip`, `threshold`) as switches alongside
`--format json`. The report is written with `--out` rather than read from
stdout, so tool chatter on either stream cannot corrupt it.

`--exit` is never passed. The stage decides pass or fail from the findings it
parsed, which is the same decision made against the same threshold, and it
keeps a scan that found nothing blocking from being indistinguishable from a
scan that did not run.

## Umbrellas

`mix sobelow` at an umbrella root finds no application to scan and exits 0,
so the stage fans out over the child apps itself, one `--root` per app, in
parallel. Each app reads its own `.sobelow-conf` and each finding is tagged
with its app.

Only apps that declare `:phoenix` or `:sobelow` are scanned. Sobelow has
nothing to say about the others, and a run that named every one of them as
unscanned would spend most of its output on apps a reader has no action to
take on.

# `run`

```elixir
@spec run(keyword()) :: ExQuality.Stage.result()
```

Runs the sobelow stage.

## Config options

- `exit` - default threshold when `.sobelow-conf` sets none (default: `"medium"`)
- `show_informational` - render findings below the threshold (default: false)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
