How to Automate Firebase Security Testing in CI/CD
Stop deploying Firebase security vulnerabilities to production. This guide shows you how to add automated security testing to your CI/CD pipeline so every deployment is security-verified.
Why Automate Security Testing?
Manual testing is:
- Inconsistent - Developers forget to test
- Slow - Takes time away from development
- Error-prone - Easy to miss edge cases
- Not scalable - Can't test on every commit
Automated testing catches issues before they reach production.
Quick Setup (5 Minutes)
Step 1: Install FireScan in CI
GitHub Actions:
yaml
- name: Install FireScan
run: go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latestGitLab CI:
yaml
install_firescan:
script:
- go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latestCircleCI:
yaml
- run:
name: Install FireScan
command: go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latestStep 2: Create Config File
Create .firescan.yaml in your repo:
yaml
projectID: your-project-id
apiKey: $FIREBASE_API_KEY # From environment variable
auth:
email: [email protected]
password: $TEST_USER_PASSWORD
scans:
- type: all
options:
concurrency: 50
wordlist: allStep 3: Add to Pipeline
GitHub Actions:
yaml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Install FireScan
run: go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latest
- name: Run Security Scan
env:
FIREBASE_API_KEY: ${{ secrets.FIREBASE_API_KEY }}
TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
run: |
firescan --config .firescan.yaml --json > scan-results.json
- name: Check for Critical Issues
run: |
if grep -q '"severity":"Critical"' scan-results.json; then
echo "Critical security vulnerabilities found!"
cat scan-results.json
exit 1
fi
- name: Upload Results
if: always()
uses: actions/upload-artifact@v3
with:
name: security-scan-results
path: scan-results.jsonGitLab CI:
yaml
security_scan:
stage: test
image: golang:1.21
script:
- go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latest
- firescan --config .firescan.yaml --json > scan-results.json
- |
if grep -q '"severity":"Critical"' scan-results.json; then
echo "Critical vulnerabilities found!"
exit 1
fi
artifacts:
paths:
- scan-results.json
when: alwaysAdvanced Configurations
Fail on Specific Severities
bash
#!/bin/bash
# check-security.sh
RESULTS_FILE="scan-results.json"
# Count issues by severity
CRITICAL=$(grep -c '"severity":"Critical"' $RESULTS_FILE || true)
HIGH=$(grep -c '"severity":"High"' $RESULTS_FILE || true)
MEDIUM=$(grep -c '"severity":"Medium"' $RESULTS_FILE || true)
echo "Security Scan Results:"
echo "Critical: $CRITICAL"
echo "High: $HIGH"
echo "Medium: $MEDIUM"
# Fail if critical or high issues found
if [ $CRITICAL -gt 0 ]; then
echo "❌ Critical vulnerabilities found!"
exit 1
fi
if [ $HIGH -gt 0 ]; then
echo "⚠️ High severity issues found!"
exit 1
fi
echo "✅ Security scan passed"
exit 0Scan Multiple Environments
yaml
# .firescan.prod.yaml
projectID: myapp-prod
apiKey: $FIREBASE_API_KEY_PROD
scans:
- type: all
options:
wordlist: all
# .firescan.staging.yaml
projectID: myapp-staging
apiKey: $FIREBASE_API_KEY_STAGING
scans:
- type: all
options:
wordlist: allIn pipeline:
yaml
- name: Scan Production
run: firescan --config .firescan.prod.yaml --json > prod-results.json
- name: Scan Staging
run: firescan --config .firescan.staging.yaml --json > staging-results.jsonParallel Scanning
yaml
jobs:
scan-rtdb:
runs-on: ubuntu-latest
steps:
- name: Scan Realtime Database
run: firescan --config .firescan.yaml --json --rtdb-only > rtdb-results.json
scan-firestore:
runs-on: ubuntu-latest
steps:
- name: Scan Firestore
run: firescan --config .firescan.yaml --json --firestore-only > firestore-results.jsonIntegration Examples
Slack Notifications
yaml
- name: Notify Slack on Failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Security scan failed! Critical vulnerabilities found in ${{ github.repository }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}Create GitHub Issues
yaml
- name: Create Issue on Critical Findings
if: failure()
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('scan-results.json'));
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '🚨 Critical Security Vulnerabilities Found',
body: `Security scan found critical issues:\n\`\`\`json\n${JSON.stringify(results, null, 2)}\n\`\`\``,
labels: ['security', 'critical']
});Pull Request Comments
yaml
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('scan-results.json'));
const criticalCount = results.filter(r => r.severity === 'Critical').length;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Security Scan Results\n\n` +
`- Critical: ${criticalCount}\n` +
`- High: ${results.filter(r => r.severity === 'High').length}\n\n` +
(criticalCount > 0 ? '❌ **Cannot merge - critical issues found**' : '✅ No critical issues')
});Best Practices
1. Store Secrets Securely
Never commit:
- API keys
- Test user passwords
- Project IDs (if sensitive)
Use environment variables or secret management.
2. Test Multiple Scenarios
yaml
- name: Test Unauthenticated Access
run: firescan --config .firescan.yaml --unauth --json > unauth-results.json
- name: Test Authenticated Access
run: firescan --config .firescan.yaml --json > auth-results.json
- name: Test Write Permissions
run: firescan --config .firescan.yaml --write --test --json > write-results.json3. Cache Dependencies
yaml
- name: Cache Go modules
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}4. Run on Schedule
yaml
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
push:
branches: [main]
pull_request:5. Set Timeouts
yaml
- name: Security Scan
timeout-minutes: 10
run: firescan --config .firescan.yaml --timeout 8mHandling False Positives
Create .firescan-ignore.yaml:
yaml
ignore:
- path: /public/*
reason: Intentionally public content
- path: /metadata
reason: Non-sensitive metadataThen:
bash
firescan --config .firescan.yaml --ignore-file .firescan-ignore.yamlMonitoring and Reporting
Save Historical Results
yaml
- name: Store Results with Timestamp
run: |
DATE=$(date +%Y-%m-%d-%H-%M-%S)
cp scan-results.json "security-scans/scan-$DATE.json"
- name: Commit Results
run: |
git config user.name "Security Bot"
git config user.email "[email protected]"
git add security-scans/
git commit -m "Security scan results $DATE"
git pushGenerate Reports
bash
# Compare with previous scan
jq -s '.[0] as $new | .[1] as $old |
{
"new_issues": ($new | map(select(.severity == "Critical")) | length),
"resolved": ($old | map(select(.severity == "Critical")) | length) - ($new | map(select(.severity == "Critical")) | length)
}' scan-results.json previous-scan.jsonTroubleshooting CI/CD Integration
Issue: Scans Timeout
Reduce concurrency:
yaml
options:
concurrency: 10 # Lower number
timeout: 5mIssue: Too Many Findings
Start with critical only:
bash
if grep -q '"severity":"Critical"' scan-results.json; then
exit 1
fi
# Ignore High/Medium initiallyIssue: API Rate Limiting
Add rate limiting:
yaml
options:
rate-limit: 10 # Requests per secondNext Steps
Automate your Firebase security testing today and never deploy vulnerable code again.
Need help setting up CI/CD security? Get professional help or support this project.
