← Back to Blog

Automating Smart Contract Security Scans in CI/CD (GitHub Actions)

2026-03-25 GitHub Actions CI/CD automation DevSecOps smart-contract security

"I'll Just Scan Before Deployment" — That Mindset Is the Problem

Running security checks only right before deployment leads to:

Integrating security scans into CI/CD automatically detects vulnerabilities on every PR and blocks merges when critical issues are found.


Basic Setup: Slither on Every PR

Assumed Folder Structure

my-defi-project/
├── contracts/
│   ├── Token.sol
│   └── Vault.sol
├── hardhat.config.js
└── .github/
    └── workflows/
        └── security.yml

Basic Workflow

# .github/workflows/security.yml
name: Smart Contract Security Scan

on:
  pull_request:
    paths:
      - 'contracts/**/*.sol'  # Only run when Solidity files change

jobs:
  slither:
    name: Slither Analysis
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Run Slither
        uses: crytic/slither-action@v0.4.0
        id: slither
        with:
          target: contracts/
          slither-args: '--filter-paths node_modules'
          fail-on: high  # Fail CI on high severity or above

      - name: Upload SARIF
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.slither.outputs.sarif }}

This configuration:
- Runs automatically on every PR that changes files in contracts/
- Fails the check when HIGH severity or above vulnerabilities are found (can block merge)
- Automatically uploads results to the GitHub Security tab


Advanced Setup: Multi-Engine + PR Comments

ContractScan GitHub Action Integration

# .github/workflows/security-full.yml
name: Full Security Scan

on:
  pull_request:
    paths:
      - 'contracts/**'

jobs:
  security-scan:
    name: ContractScan Analysis
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write  # Permission to post PR comments

    steps:
      - uses: actions/checkout@v4

      - name: Run ContractScan
        id: scan
        run: |
          RESULT=$(curl -s -X POST https://contract-scanner.raccoonworld.xyz/ci/scan \
            -F "file=@contracts/MyContract.sol" \
            -H "X-Api-Key: ${{ secrets.CONTRACTSCAN_API_KEY }}")
          echo "$RESULT" > scan-result.json
          CRITICAL=$(echo "$RESULT" | jq '.severity_summary.Critical // 0')
          echo "critical-count=$CRITICAL" >> $GITHUB_OUTPUT

      - name: Security Gate
        if: steps.scan.outputs.critical-count > 0
        run: |
          echo "❌ Critical vulnerabilities found. Blocking merge."
          exit 1

Example automated PR comment:

## ContractScan Security Report

🔴 **1 Critical** | 🟠 **2 High** | 🟡 **3 Medium**

### Critical Issues

**[SWC-107] Reentrancy in Vault.withdraw()**
- File: `contracts/Vault.sol:45`
- The contract state is changed after an external call.
- Fix: Apply Checks-Effects-Interactions pattern

---
Full report: [View on ContractScan](https://contract-scanner.raccoonworld.xyz/report/...)

Branch Protection Rules

In GitHub Settings → Branches → Branch protection rules:

  1. Select main / master branch
  2. Enable Require status checks to pass before merging
  3. Add Slither Analysis or ContractScan Analysis check
  4. Enable Require branches to be up to date

Now PRs cannot be merged unless the security scan passes.


Practical Severity Policies

Failing CI on every finding creates too many false positives and blocks development. Recommended policy:

# Apply different thresholds per environment
jobs:
  security-scan:
    strategy:
      matrix:
        include:
          - branch: main
            fail-on: high      # main branch: block on high and above
          - branch: develop
            fail-on: critical  # develop: block on critical only

Or allowlist specific issues:

- name: Run Slither
  uses: crytic/slither-action@v0.4.0
  with:
    slither-args: >
      --exclude-informational
      --exclude-low
      --filter-paths "node_modules,test"

Hardhat / Foundry Project Integration

Hardhat Projects

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-node@v4
    with:
      node-version: '20'

  - run: npm ci

  - name: Compile contracts
    run: npx hardhat compile

  - name: Run Slither
    uses: crytic/slither-action@v0.4.0
    with:
      node-version: '20'
      hardhat: true

Foundry Projects

steps:
  - uses: actions/checkout@v4
    with:
      submodules: recursive

  - name: Install Foundry
    uses: foundry-rs/foundry-toolchain@v1

  - name: Build
    run: forge build

  - name: Run Slither
    uses: crytic/slither-action@v0.4.0
    with:
      foundry: true

Complete DevSecOps Pipeline

Developer commit
     ↓
[PR opened]
     ↓
GitHub Actions triggered
     ├── Slither static analysis (30s)
     ├── Semgrep pattern check (20s)
     └── AI vulnerability analysis (60s)
     ↓
Results auto-posted as PR comment
     ↓
Severity gate evaluation
  CRITICAL/HIGH → ❌ Merge blocked
  MEDIUM/LOW   → ⚠️ Warning only
     ↓
[Code review + fixes]
     ↓
Security scan passes
     ↓
[Final pre-deployment review]
     ↓
Mainnet deployment

Cost: Start Completely Free

Consider paid plans as your team grows or scan volume increases. For now, you can build the entire pipeline at zero cost.


Conclusion: Automation Is the Answer to Security

Summary of what this series has covered:

  1. Introduction: Why smart contract security matters — immutability, direct asset control
  2. Reentrancy: From The DAO to Euler Finance, the CEI pattern and ReentrancyGuard
  3. Top 5 Vulnerabilities: Access control, overflow, oracle manipulation, flash loans, front-running
  4. Tool Comparison: Slither vs Mythril vs Semgrep — when to use what
  5. CI/CD Automation: This post — integrating security into your pipeline with GitHub Actions

Run a free scan at contract-scanner.raccoonworld.xyz before deploying a single line of code. Five minutes can save millions.

Scan your contract now
Slither + AI analysis — 3 free scans, no install required
Try Free Scan →