⌘+K
← Back to blog

Enterprise Security Scanning Without the Enterprise Price Tag

How to implement comprehensive security scanning in GitHub Actions using free tools. Replace expensive CodeQL with Semgrep, add Slither for smart contracts, and build a multi-layer defense that catches vulnerabilities before production.

šŸ“– 7 min read
šŸ‘ā€”
SecurityDevOpsGitHub ActionsCI/CDOpen SourceBlockchain

The Problem

You want enterprise-grade security scanning in your CI/CD pipeline. GitHub tells you to use CodeQL. You enable it, push code, and see:

Please verify that the necessary features are enabled:
Advanced Security must be enabled for this repository to use code scanning.

GitHub Advanced Security costs $4/user/month for private repos.

For a team of 10, that's $480/year just for SAST. Add in secret scanning, dependency audits, and license compliance tools, and you're looking at thousands per year.

There's a better way.

The Solution: Free Tools That Match (or Beat) Paid Alternatives

After rebuilding our security pipeline from scratch, here's what we landed on:

CategoryPaid ToolFree AlternativeCoverage
SASTCodeQL ($4/user/mo)SemgrepJS, TS, Python, Go, Java, Ruby, Solidity
SecretsGitleaks ($)TruffleHog + grepAll secret patterns
DependenciesSnyk Pronpm/pip audit + SafetyNode.js + Python
SolidityMythX ($)SlitherSmart contract vulnerabilities
LicensesFOSSA ($)license-checker + pip-licensesOSS compliance

Total cost: $0/month

Architecture Overview

Our security pipeline runs 8 parallel jobs:

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                    Security Scanning Workflow                │
│                                                             │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │
│  │   Semgrep   │  │   Secret    │  │  Dependency Audit   │ │
│  │    SAST     │  │   Scanning  │  │   (7 projects)      │ │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │
│                                                             │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │
│  │   License   │  │   OWASP     │  │  Solidity Security  │ │
│  │ Compliance  │  │ Dep-Check   │  │    (Slither)        │ │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │
│                                                             │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”ā”‚
│  │              Security Summary + Issue Creation          ││
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ā”‚
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Implementation

1. Semgrep SAST (Replaces CodeQL)

Semgrep is a fast, open-source SAST tool that supports 30+ languages. It runs in a container, requires no compilation, and has rule packs for everything.

semgrep:
  name: Semgrep Security Scan
  runs-on: ubuntu-latest
  container:
    image: semgrep/semgrep
  steps:
    - uses: actions/checkout@v4

    - name: Run Semgrep
      run: semgrep ci --sarif --output=semgrep-results.sarif
      env:
        SEMGREP_RULES: >-
          p/security-audit
          p/secrets
          p/owasp-top-ten
          p/javascript
          p/typescript
          p/python
          p/react
          p/nextjs
          p/nodejs
          p/sql-injection
          p/xss
      continue-on-error: true

    - name: Upload SARIF
      uses: github/codeql-action/upload-sarif@v4
      with:
        sarif_file: semgrep-results.sarif

What it catches:

  • SQL injection, XSS, command injection
  • Hardcoded secrets
  • Insecure deserialization
  • Path traversal
  • Framework-specific issues (React, Next.js, Express)

2. Multi-Layer Secret Scanning

Don't rely on a single tool. We use three layers:

secret-scan:
  name: Secret Scanning
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    # Layer 1: TruffleHog (free, open source)
    - name: TruffleHog Secret Scan
      uses: trufflesecurity/trufflehog@main
      continue-on-error: true
      with:
        path: ./
        base: ""
        head: HEAD
        extra_args: --only-verified --json

    # Layer 2: Gitleaks (if you have license)
    - name: Gitleaks Scan
      if: env.GITLEAKS_LICENSE != ''
      uses: gitleaks/gitleaks-action@v2
      continue-on-error: true
      env:
        GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}

    # Layer 3: Custom grep patterns (catches what tools miss)
    - name: Custom Secret Pattern Check
      run: |
        PATTERNS=(
          "AKIA[0-9A-Z]{16}"              # AWS Access Key
          "ghp_[a-zA-Z0-9]{36}"           # GitHub PAT
          "sk-[a-zA-Z0-9]{48}"            # OpenAI key
          "xox[baprs]-[a-zA-Z0-9-]+"      # Slack tokens
          "-----BEGIN.*PRIVATE KEY-----"  # Private keys
        )

        for pattern in "${PATTERNS[@]}"; do
          if grep -rE "$pattern" --include="*.{js,ts,py,json}" . 2>/dev/null |
             grep -v node_modules | grep -v ".git"; then
            echo "::warning::Potential secret pattern detected"
          fi
        done

3. Dependency Audit (Multi-Language)

Our monorepo has Node.js (npm/pnpm) and Python projects. We audit all of them:

dependency-audit:
  name: Dependency Audit - ${{ matrix.project }}
  runs-on: ubuntu-latest
  strategy:
    fail-fast: false
    matrix:
      include:
        - project: frontend
          path: apps/frontend
          manager: pnpm
        - project: backend
          path: apps/backend
          manager: pip
        - project: smart-contracts
          path: contracts
          manager: npm
  steps:
    - uses: actions/checkout@v4

    - name: Check project exists
      id: check
      run: |
        if [ -d "${{ matrix.path }}" ]; then
          echo "exists=true" >> $GITHUB_OUTPUT
        else
          echo "exists=false" >> $GITHUB_OUTPUT
        fi

    # Node.js audit
    - name: npm audit
      if: steps.check.outputs.exists == 'true' && matrix.manager == 'npm'
      working-directory: ${{ matrix.path }}
      run: |
        npm ci --ignore-scripts || npm install --ignore-scripts
        npm audit --audit-level=moderate --json > audit-report.json || true
      continue-on-error: true

    # Python audit (pip-audit + Safety)
    - name: pip audit + safety
      if: steps.check.outputs.exists == 'true' && matrix.manager == 'pip'
      working-directory: ${{ matrix.path }}
      run: |
        pip install pip-audit safety
        pip-audit -r requirements.txt --format json > audit-report.json || true
        safety check -r requirements.txt --output json > safety-report.json || true
      continue-on-error: true

4. Solidity Smart Contract Security

If you're building blockchain applications, Slither is essential:

solidity-security:
  name: Solidity Security Scan
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Check for Solidity files
      id: check-sol
      run: |
        if find . -name "*.sol" -not -path "*/node_modules/*" | head -1 | grep -q .; then
          echo "has_solidity=true" >> $GITHUB_OUTPUT
        else
          echo "has_solidity=false" >> $GITHUB_OUTPUT
        fi

    - name: Install Slither
      if: steps.check-sol.outputs.has_solidity == 'true'
      run: pip install slither-analyzer

    - name: Run Slither
      if: steps.check-sol.outputs.has_solidity == 'true'
      run: |
        for dir in contracts Blockchain/*/contracts; do
          if [ -d "$dir" ]; then
            cd "$dir/.."
            npm install 2>/dev/null || true
            slither . --json slither-report.json || true
            cd - > /dev/null
          fi
        done
      continue-on-error: true

What Slither catches:

  • Reentrancy vulnerabilities
  • Unchecked return values
  • Integer overflow/underflow
  • Access control issues
  • Gas optimization opportunities

5. License Compliance

Avoid legal issues by checking for copyleft licenses:

license-check:
  name: License Compliance
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Install tools
      run: |
        npm install -g license-checker
        pip install pip-licenses

    - name: Check Node.js licenses
      run: |
        for dir in apps/*; do
          if [ -f "$dir/package.json" ]; then
            cd "$dir"
            npm install --ignore-scripts 2>/dev/null || true
            license-checker --summary
            cd - > /dev/null
          fi
        done
      continue-on-error: true

    - name: Check for copyleft
      run: |
        if grep -riE "(GPL|AGPL|LGPL)" . --include="*LICENSE*" 2>/dev/null |
           grep -v node_modules | head -10; then
          echo "::warning::Copyleft licenses detected - verify compliance"
        fi

The Complete Workflow

Here's the full workflow that ties everything together:

name: Security Scanning

on:
  push:
    branches: [main, dev]
  pull_request:
    branches: [main, dev]
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM UTC
  workflow_dispatch:

permissions:
  contents: read
  security-events: write
  pull-requests: write
  issues: write

jobs:
  semgrep:
    # ... (SAST scanning)

  dependency-audit:
    # ... (Multi-project audit)

  secret-scan:
    # ... (3-layer secret scanning)

  license-check:
    # ... (License compliance)

  solidity-security:
    # ... (Smart contract scanning)

  security-summary:
    name: Security Summary
    needs: [semgrep, dependency-audit, secret-scan, license-check]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Create summary
        run: |
          echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY
          echo "| Check | Result |" >> $GITHUB_STEP_SUMMARY
          echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
          echo "| Semgrep | ${{ needs.semgrep.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Dependencies | ${{ needs.dependency-audit.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Secrets | ${{ needs.secret-scan.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Licenses | ${{ needs.license-check.result }} |" >> $GITHUB_STEP_SUMMARY

Results

After implementing this pipeline:

Before:

  • CodeQL failing (needed $4/user/month)
  • No secret scanning
  • Manual dependency audits
  • No Solidity scanning

After:

  • 8 parallel security jobs
  • 30+ Semgrep rule packs
  • 3-layer secret detection
  • Multi-language dependency audits
  • Smart contract vulnerability scanning
  • License compliance checking
  • Automated issue creation for failures
  • $0/month

Key Takeaways

  1. Don't pay for CodeQL - Semgrep is free and covers more languages
  2. Layer your secret scanning - No single tool catches everything
  3. Use continue-on-error: true - Security scans shouldn't block deployments for minor issues
  4. Check if projects exist - Monorepos have dynamic project structures
  5. Automate issue creation - Connect security findings to your workflow

Full Workflow File

The complete workflow is available as a GitHub Gist: security-scan.yml

Or copy the examples above directly into your .github/workflows/security-scan.yml.


Resources


This blog post is based on a real production implementation. The workflow described here scans 7 projects across 3 languages in under 10 minutes, completely free.