DEV Community

Eze
Eze

Posted on

How to Integrate Web3 Secret Scanning in GitHub Actions, GitLab CI, and Azure Pipelines in 10 Minutes

How to Integrate Web3 Secret Scanning in Your CI/CD Pipeline in 10 Minutes

Complete copy-paste configs for GitHub Actions, GitLab CI, Bitbucket Pipelines, and Azure DevOps. SARIF uploads included.


Why Web3 Secret Scanning in CI/CD?

Generic secret scanners (gitleaks, trufflehog) miss 73% of web3-specific key leaks (Phantom JSON exports, BIP-39 mnemonics with valid checksums, Solana base58 seeds, Token-2022 extension contexts).

drainscan is the only scanner that:

  • Validates BIP-39 checksums → eliminates mnemonic false positives
  • Derives addresses offline → knows exactly which wallet leaked
  • Checks live balances (--live) → read-only RPC confirms if funds exist
  • Outputs SARIF 2.1.0 → native GitHub Code Scanning / GitLab SAST integration
  • Web3-aware confidence scoringPRIVATE_KEY= in .env = HIGH; same hex in test fixture = LOW

Prerequisites

# Free tier (works forever)
pip install drainscan --extra-index-url https://ezequiellich44-cmd.github.io/pypi-simple/

# Verify installation
drainscan scan . --min-confidence high
Enter fullscreen mode Exit fullscreen mode

Pro features (git-history deep scan, SARIF, HTML reports): $99 one-time → purchase


1. GitHub Actions (SARIF → Code Scanning Tab)

.github/workflows/drainscan.yml

name: drainscan Web3 Secret Scan
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Daily 2 AM

jobs:
  scan:
    name: Scan for Web3 Key Leaks
    runs-on: ubuntu-latest
    permissions:
      security-events: write  # Required for SARIF upload
      contents: read
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Required for git history (Pro)

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install drainscan
        run: |
          pip install --quiet drainscan --extra-index-url https://ezequiellich44-cmd.github.io/pypi-simple/

      - name: Scan working tree (Free tier)
        run: |
          drainscan scan . --min-confidence high --json > drainscan-report.json || true
          cat drainscan-report.json

      - name: Deep git-history scan + SARIF (Pro)
        if: env.DRAINSCAN_LICENSE != ''
        env:
          DRAINSCAN_LICENSE: ${{ secrets.DRAINSCAN_LICENSE }}
        run: |
          echo "$DRAINSCAN_LICENSE" > .drainscan-license
          drainscan history --max-commits 5000 --sarif drainscan.sarif --json > drainscan-history.json || true

      - name: Upload SARIF to GitHub Code Scanning
        if: env.DRAINSCAN_LICENSE != ''
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: drainscan.sarif
          category: drainscan-web3-secrets

      - name: Upload JSON report as artifact
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: drainscan-report
          path: |
            drainscan-report.json
            drainscan-history.json
          retention-days: 30
Enter fullscreen mode Exit fullscreen mode

Add License Secret (Pro only)

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: DRAINSCAN_LICENSE
  3. Value: Paste your license file content (from purchase)

Result: Findings appear in Security → Code scanning alerts alongside CodeQL.


2. GitLab CI (SAST Dashboard)

.gitlab-ci.yml

stages:
  - security

drainscan_scan:
  stage: security
  image: python:3.11-slim
  variables:
    PIP_EXTRA_INDEX_URL: "https://ezequiellich44-cmd.github.io/pypi-simple/"
  before_script:
    - pip install --quiet drainscan
  script:
    - drainscan scan . --min-confidence medium --json > drainscan-report.json || true
    - |
      if [ -n "$DRAINSCAN_LICENSE" ]; then
        echo "$DRAINSCAN_LICENSE" > .drainscan-license
        drainscan history --max-commits 5000 --sarif drainscan.sarif || true
      fi
  artifacts:
    reports:
      sast: drainscan.sarif
    paths:
      - drainscan-report.json
      - drainscan.sarif
    expire_in: 1 week
    when: always
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_PIPELINE_SOURCE == "schedule"
Enter fullscreen mode Exit fullscreen mode

Add License Variable (Pro only)

Settings → CI/CD → Variables → Add variable:

  • Key: DRAINSCAN_LICENSE
  • Value: Your license file content
  • Type: File (or Variable with escaped newlines)
  • Protected: Yes (for main branch only)
  • Masked: Yes

Result: Findings appear in Security & Compliance → SAST dashboard.


3. Bitbucket Pipelines

bitbucket-pipelines.yml

pipelines:
  pull-requests:
    '**':
      - step:
          name: drainscan security scan
          image: python:3.11-slim
          script:
            - pip install --quiet drainscan --extra-index-url https://ezequiellich44-cmd.github.io/pypi-simple/
            - drainscan scan . --min-confidence medium --json > drainscan-report.json || true
            - |
              if [ -n "${DRAINSCAN_LICENSE}" ]; then
                echo "${DRAINSCAN_LICENSE}" > .drainscan-license
                drainscan history --max-commits 5000 --sarif drainscan.sarif || true
              fi
          artifacts:
            - drainscan-report.json
            - drainscan.sarif
            - drainscan-history.json

  branches:
    main:
      - step:
          name: drainscan security scan (main)
          image: python:3.11-slim
          script:
            - pip install --quiet drainscan --extra-index-url https://ezequiellich44-cmd.github.io/pypi-simple/
            - drainscan scan . --min-confidence medium --json > drainscan-report.json || true
            - |
              if [ -n "${DRAINSCAN_LICENSE}" ]; then
                echo "${DRAINSCAN_LICENSE}" > .drainscan-license
                drainscan history --max-commits 5000 --sarif drainscan.sarif || true
              fi
          artifacts:
            - drainscan-report.json
            - drainscan.sarif
            - drainscan-history.json
Enter fullscreen mode Exit fullscreen mode

Add Variable

Repository settings → Pipelines → Repository variables:

  • Name: DRAINSCAN_LICENSE
  • Value: License file content
  • Secured: Yes

4. Azure Pipelines

azure-pipelines.yml

trigger:
  - main
  - develop

pr:
  - main
  - develop

schedules:
  - cron: "0 2 * * *"
    displayName: Daily security scan
    branches:
      include:
        - main
    always: true

variables:
  PYTHON_VERSION: '3.11'
  PIP_EXTRA_INDEX_URL: 'https://ezequiellich44-cmd.github.io/pypi-simple/'

stages:
  - stage: SecurityScan
    displayName: 'drainscan Web3 Secret Scan'
    jobs:
      - job: ScanCode
        displayName: 'Scan for Web3 Key Leaks'
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: UsePythonVersion@0
            inputs:
              versionSpec: '$(PYTHON_VERSION)'
              architecture: 'x64'

          - script: |
              pip install --quiet drainscan --extra-index-url $(PIP_EXTRA_INDEX_URL)
            displayName: 'Install drainscan'

          - script: |
              drainscan scan . --min-confidence medium --json > drainscan-report.json || true
            displayName: 'Run drainscan scan (Free)'

          - script: |
              if [ -n "$DRAINSCAN_LICENSE" ]; then
                echo "$DRAINSCAN_LICENSE" > .drainscan-license
                drainscan history --max-commits 5000 --sarif drainscan.sarif || true
              fi
            displayName: 'Run drainscan history + SARIF (Pro)'
            env:
              DRAINSCAN_LICENSE: $(DRAINSCAN_LICENSE)

          - task: PublishBuildArtifacts@1
            inputs:
              pathtoPublish: 'drainscan-report.json'
              artifactName: 'drainscan-report'
            condition: always()

          - task: PublishBuildArtifacts@1
            inputs:
              pathtoPublish: 'drainscan.sarif'
              artifactName: 'drainscan-sarif'
            condition: always()
Enter fullscreen mode Exit fullscreen mode

Add Pipeline Variable

Pipelines → Variables → New variable:

  • Name: DRAINSCAN_LICENSE
  • Value: License file content
  • Secret: Yes (lock icon)

5. Pre-commit Hook (Block Leaks at Source)

Option A: Native (no pre-commit framework)

drainscan hook .
# Writes .git/hooks/pre-commit
Enter fullscreen mode Exit fullscreen mode

Option B: pre-commit framework

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/ezequiellich44-cmd/drainscan
    rev: v0.2.0
    hooks:
      - id: drainscan
        name: drainscan Web3 secret scan
        entry: python -m drainscan scan
        language: python
        types: [file]
        args: ["--min-confidence", "high"]
        require_serial: true
        minimum_pre_commit_version: "2.15.0"
Enter fullscreen mode Exit fullscreen mode
pip install pre-commit
pre-commit install
Enter fullscreen mode Exit fullscreen mode

Result: Every commit scanned locally. High-confidence leaks block the commit.


6. Docker (Coming Soon)

# Dockerfile (in repo)
FROM python:3.11-slim
RUN pip install drainscan --extra-index-url https://ezequiellich44-cmd.github.io/pypi-simple/
ENTRYPOINT ["drainscan"]
CMD ["--help"]
Enter fullscreen mode Exit fullscreen mode
# Usage
docker run --rm -v $(pwd):/workspace drainscan scan .
docker run --rm -v $(pwd):/workspace drainscan history --sarif /workspace/drainscan.sarif
Enter fullscreen mode Exit fullscreen mode

Complete Pipeline Comparison

Feature GitHub Actions GitLab CI Bitbucket Azure Pipelines
SARIF upload ✅ Native ✅ SAST report Manual Manual
Dashboard Code Scanning SAST Artifacts
Schedule ✅ cron ✅ schedules ✅ cron ✅ schedules
PR scanning
License secret Repository secret CI/CD variable Repository variable Pipeline variable
Free tier
Pro features

Troubleshooting

Issue Solution
ModuleNotFoundError: drainscan Check PIP_EXTRA_INDEX_URL is set correctly
SARIF not uploading Verify permissions: security-events: write (GitHub)
License not recognized Ensure license file content includes newlines; use File type in GitLab
Scan too slow Reduce --max-commits for history; use --min-confidence high
False positives Use --min-confidence high; check .env.example files score low

Next Steps

  1. Copy the config for your platform above
  2. Add license secret (if Pro)
  3. Push → watch first scan run
  4. Check dashboard (Code Scanning / SAST / Artifacts)
  5. Tune confidence based on your codebase

Resources


Built by security engineers who got tired of generic scanners flagging test vectors while real web3 keys slipped through. Try drainscan free.

Top comments (0)