Short answer: Smart contract CI security means running automated analysis on every pull request so known vulnerability patterns are caught before merge. A solid baseline is three jobs: Slither static analysis on every PR with results uploaded to GitHub code scanning, your Foundry tests including invariant tests on every PR, and longer Echidna fuzzing campaigns on a schedule. The workflows below use the official, maintained actions for each tool.
Manual review happens a few times in a protocol's life; code changes every day. CI closes that gap for the class of bugs automated tools are good at — known patterns and broken invariants — and leaves reviewers free to spend their time on design and economics. It also gives you a history: when a finding first appeared, which PR introduced it, and when it was fixed.
What CI will not do is tell you your protocol is safe. Treat it as a regression net, not an audit. For the trade-offs between tools, see our smart contract security tools comparison and the hands-on Slither, Mythril, and Echidna workflow.
The crytic/slither-action compiles your project (Foundry, Hardhat, and other frameworks are detected automatically) and runs Slither. Writing SARIF and uploading it to GitHub code scanning puts findings inline on the PR diff and in the repository's Security tab.
# .github/workflows/slither.yml
name: Slither
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
security-events: write
jobs:
slither:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Run Slither
uses: crytic/slither-action@v0.4.2
id: slither
with:
sarif: results.sarif
fail-on: none
- name: Upload SARIF to code scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.slither.outputs.sarif }}
fail-on: none lets the upload step run even when Slither reports findings. Once you have triaged the existing backlog, switch to fail-on: high (or medium) so new findings at that severity block the merge. If your config file sets fail thresholds, use fail-on: config.
Triage before you enforce. Turning on a hard failure against an untriaged codebase guarantees people learn to ignore the check. Review the first run, fix real issues, and suppress accepted ones with // slither-disable-next-line <detector> and a comment explaining why.
If you use Foundry, your invariant tests are often the most valuable security check you own, because they encode rules specific to your protocol.
# .github/workflows/test.yml
name: Tests
on:
pull_request:
push:
branches: [main]
jobs:
forge-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Build
run: forge build --sizes
- name: Test (unit, fuzz, invariant)
run: forge test -vvv
env:
FOUNDRY_PROFILE: ci
Define a ci profile in foundry.toml with modest fuzz.runs and invariant.runs so PR checks finish in minutes, and a heavier profile for scheduled runs.
Fuzzing finds more the longer it runs, which makes it a poor fit for every PR and a good fit for a nightly schedule. The crytic/echidna-action wraps the Echidna Docker image.
# .github/workflows/echidna.yml
name: Echidna
on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
jobs:
echidna:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Build
run: forge build --build-info
- name: Run Echidna
uses: crytic/echidna-action@v2
with:
files: .
contract: VaultEchidnaTest
config: echidna.yaml
crytic-args: --ignore-compile
The --ignore-compile argument reuses the Foundry build from the previous step, because the action's container does not include your toolchain. Echidna exits non-zero when a property is falsified, so a failing nightly run shows up in the Actions tab with a minimized reproduction in the log.
Mythril is slow enough that running it across a whole repository on every PR is rarely worth it. If you want it, run it on a short list of high-value contracts, with explicit bounds, on a schedule or a release branch:
- name: Mythril (bounded)
run: |
docker run --rm -v "$PWD":/src mythril/myth \
analyze /src/src/Vault.sol --solv 0.8.24 -t 2 --execution-timeout 300
Firepan connects to repositories through the Firepan GitHub App. Once installed, the repository events and branches your installation is configured to send can trigger repeatable Firepan analysis, so findings can be compared as the code changes — see repository-connected analysis. Results include evidence tied to files and code paths, and the analysis includes best-effort Slither corroboration alongside HOUND AI review. It complements the open-source jobs above rather than replacing them; keep Foundry, Echidna, and any Mythril runs in your own workflows.
To try it without installing anything, request a free public-repository scan.
Q: Will security checks slow down my pull requests?
A: Slither typically adds a minute or two including compilation. Keep fuzz and invariant run counts modest on PRs and move long fuzzing campaigns to a scheduled workflow so PR feedback stays fast.
Q: Should Slither fail the build?
A: Eventually, yes — but only after you have triaged the existing findings. Start with fail-on none and SARIF upload, fix or suppress the backlog, then enforce fail-on high for new findings.
Q: How do I see Slither findings on the pull request itself?
A: Write SARIF output from the Slither action and upload it with github/codeql-action/upload-sarif. GitHub code scanning then annotates the diff and lists alerts in the Security tab. The workflow needs the security-events: write permission.
Q: Should I run Echidna on every pull request?
A: Usually not. Fuzzing improves with run time, so short PR runs find little. Run Foundry invariant tests with modest settings on PRs and full Echidna campaigns nightly or before releases.
Q: Does this work for Vyper?
A: Slither supports Vyper projects. Foundry and Echidna are primarily used with Solidity, so check each tool's documentation for your Vyper setup.
Firepan
Run a free scan — results in minutes, no credit card required.
Run Free Scan →A hands-on workflow for Slither, Mythril, and Echidna: commands, a property example, what each run actually tells you, and where Foundry invariants, Medusa, and formal tools fit.
Firepan Sentinel, GoPlus, Token Sniffer, Honeypot.is, RugCheck, De.Fi, and Bubblemaps compared: what each rug pull checker looks at, which chains it covers, and how to combine them.
A 15-step security checklist for launching a DeFi protocol: testing and invariants, external review, oracle and access-control configuration, deployment runbooks, key management, and incident response.
The free smart contract audit tools worth using in 2026: no-account AI scans, open-source analyzers like Slither and Aderyn, and fuzzers. What each finds, what it needs, and where free tools stop.
A 10-step checklist to prepare for a smart contract audit: freeze the code, define scope, document the design and invariants, raise test coverage, run automated tools, and plan the fix review. Prepared code costs less to audit.