diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..5c8751f --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,88 @@ +--- +name: audit + +# Fails when a locked dependency has a published security advisory. Lock files +# can become vulnerable without any change here, so this also runs daily on +# main instead of only when a pull request touches them. +# +# To acknowledge an advisory that does not affect Textbin, list it under +# `hex: [ignore_advisories: [...]]` in mix.exs, or under +# `[advisories] ignore = [...]` in .cargo/audit.toml, with a comment saying why. + +"on": + pull_request: + push: + branches: [main] + schedule: + - cron: "17 6 * * *" + workflow_dispatch: + +permissions: + contents: read + +env: + OTP_VERSION: "28.5" + ELIXIR_VERSION: "1.20" + CARGO_AUDIT_VERSION: "0.22.2" + +jobs: + hex: + name: Hex advisories + runs-on: blacksmith-2vcpu-ubuntu-2404 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + + - name: Cache Mix dependencies + uses: actions/cache@v4 + with: + path: deps + key: mix-audit-${{ runner.os }}-${{ hashFiles('mix.lock') }} + restore-keys: | + mix-audit-${{ runner.os }}- + + # Hex 2.5 is the first release whose audit checks security advisories + # as well as retirements; installing the latest keeps that true. + - name: Install Hex + run: mix local.hex --force + + # hex.audit loads the project, which needs the locked deps present. + - name: Install dependencies + run: mix deps.get + + - name: Audit + run: mix hex.audit + + cargo: + name: RustSec advisories + runs-on: blacksmith-2vcpu-ubuntu-2404 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + # Building cargo-audit takes about three minutes; the binary only + # changes with its version. + - name: Cache cargo-audit + id: cargo-audit-cache + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/cargo-audit + key: cargo-audit-${{ runner.os }}-${{ env.CARGO_AUDIT_VERSION }} + + - name: Install cargo-audit + if: steps.cargo-audit-cache.outputs.cache-hit != 'true' + run: cargo install cargo-audit --locked --version "$CARGO_AUDIT_VERSION" + + - name: Audit + run: cargo audit diff --git a/AGENTS.md b/AGENTS.md index 595db0b..7f354d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,7 @@ This is a web application written using the Phoenix web framework. - When Jujutsu is available for the workspace, use `jj` to record changes with detailed explanations; use Git commits only when `jj` is unavailable - Add concise comments or module/function docs that explain intent, domain boundaries, security decisions, or non-obvious tradeoffs. Avoid comments that merely restate what the code does - The API contract lives next to the code: each API controller action declares its OpenAPI operation with `operation` (helpers in `TextbinWeb.ApiDocs`, schemas in `TextbinWeb.ApiSpec.Schemas`). Requests that do not match it are rejected, every API response in the test suite is checked against it, and a full `mix test` fails if a documented response is never produced. After changing an operation, run `mix openapi.export` and commit `priv/openapi.json` +- CI fails when a locked dependency has a published security advisory (`mix hex.audit` and `cargo audit`, on every pull request and daily). Fix it by upgrading; acknowledge an advisory that does not affect Textbin only in `hex: [ignore_advisories: ...]` in `mix.exs` or `.cargo/audit.toml`, with a comment explaining why - Use the already included and available `:req` (`Req`) library for HTTP requests, **avoid** `:httpoison`, `:tesla`, and `:httpc`. Req is included by default and is the preferred HTTP client for Phoenix apps ### Phoenix v1.8 guidelines