Github Actions
Integrate BlockSecOps into your GitHub workflow. - GitHub repository - BlockSecOps account with API access - API key created --- 1. Go to Settings → API Keys...
Last updated: January 14, 2026
GitHub Actions
Integrate BlockSecOps into your GitHub workflow.
Prerequisites
- GitHub repository
- BlockSecOps account with API access
- API key created
Setup
1. Create API Key
- Go to Settings → API Keys
- Click Create Key
- Name: "GitHub Actions"
- Permissions: Scans, Contracts
- Copy the key
2. Add Secret
- Go to GitHub repo → Settings → Secrets
- Click New repository secret
- Name:
BLOCKSECOPS_API_KEY - Value: Your API key
- Save
Basic Workflow
Create .github/workflows/security-scan.yml:
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
npm install -g @blocksecops/cli
- name: Run security scan
env:
BLOCKSECOPS_API_KEY: ${{ secrets.BLOCKSECOPS_API_KEY }}
run: |
blocksecops scan ./contracts --preset standard
- name: Check results
env:
BLOCKSECOPS_API_KEY: ${{ secrets.BLOCKSECOPS_API_KEY }}
run: |
blocksecops check --fail-on critical
Using the API Directly
If not using the CLI:
name: Security Scan (API)
on:
push:
paths:
- 'contracts/**'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create archive
run: |
cd contracts
zip -r ../contracts.zip .
- name: Upload and scan
env:
API_KEY: ${{ secrets.BLOCKSECOPS_API_KEY }}
API_URL: https://api.blocksecops.com/api/v1
run: |
# Upload
UPLOAD_RESPONSE=$(curl -s -X POST "$API_URL/contracts/upload" \
-H "Authorization: Bearer $API_KEY" \
-F "[email protected]")
CONTRACT_ID=$(echo $UPLOAD_RESPONSE | jq -r '.id')
# Start scan
SCAN_RESPONSE=$(curl -s -X POST "$API_URL/scans" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"contract_id\": \"$CONTRACT_ID\", \"preset\": \"standard\"}")
SCAN_ID=$(echo $SCAN_RESPONSE | jq -r '.id')
# Wait for completion
while true; do
STATUS=$(curl -s "$API_URL/scans/$SCAN_ID" \
-H "Authorization: Bearer $API_KEY" | jq -r '.status')
if [[ "$STATUS" == "completed" ]]; then
break
elif [[ "$STATUS" == "failed" ]]; then
echo "Scan failed"
exit 1
fi
echo "Waiting... ($STATUS)"
sleep 15
done
# Get results
RESULTS=$(curl -s "$API_URL/scans/$SCAN_ID/results" \
-H "Authorization: Bearer $API_KEY")
# Check for critical
CRITICAL=$(echo $RESULTS | jq '.summary.critical')
if [[ "$CRITICAL" -gt 0 ]]; then
echo "::error::Found $CRITICAL critical vulnerabilities!"
exit 1
fi
echo "Scan passed!"
PR Comment Integration
Post results as PR comment:
- name: Post PR comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const results = JSON.parse(process.env.RESULTS);
const body = `## Security Scan Results
| Severity | Count |
|----------|-------|
| Critical | ${results.summary.critical} |
| High | ${results.summary.high} |
| Medium | ${results.summary.medium} |
| Low | ${results.summary.low} |
[View full results](https://app.blocksecops.com/scans/${results.scan_id})
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
Conditional Scanning
Only on Contract Changes
on:
push:
paths:
- 'contracts/**'
- 'src/**/*.sol'
Skip for Documentation
jobs:
scan:
if: |
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[docs]')
Matrix Scanning
Scan multiple projects:
jobs:
scan:
strategy:
matrix:
project: [token, vault, governance]
steps:
- name: Scan ${{ matrix.project }}
run: |
blocksecops scan ./contracts/${{ matrix.project }}
Caching
Speed up builds with caching:
- name: Cache scan results
uses: actions/cache@v4
with:
path: .blocksecops-cache
key: scan-${{ hashFiles('contracts/**') }}
restore-keys: |
scan-
Status Checks
Required Status Check
- Go to repo Settings → Branches
- Add branch protection rule
- Require status checks
- Select "Security Scan"
Status Badge
Add to README:

Scheduled Scans
Run nightly deep scans:
on:
schedule:
- cron: '0 2 * * *' # 2 AM daily
jobs:
nightly-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deep scan
run: blocksecops scan --preset deep
Troubleshooting
Action Fails with Auth Error
- Verify secret name matches
- Check API key is valid
- Ensure key has required permissions
Scan Takes Too Long
- Use
quickpreset for PRs - Cache results for unchanged files
- Consider async scanning with webhooks
Rate Limit Exceeded
- Add delays between API calls
- Check your plan's limits
- Use webhooks instead of polling
Next Steps
- GitLab CI - GitLab setup
- Webhooks - Async notifications
- API Reference - Full API docs