Skip to content

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@latest

GitLab CI:

yaml
install_firescan:
  script:
    - go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latest

CircleCI:

yaml
- run:
    name: Install FireScan
    command: go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latest

Step 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: all

Step 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.json

GitLab 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: always

Advanced 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 0

Scan 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: all

In 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.json

Parallel 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.json

Integration 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.json

3. 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 8m

Handling False Positives

Create .firescan-ignore.yaml:

yaml
ignore:
  - path: /public/*
    reason: Intentionally public content
  - path: /metadata
    reason: Non-sensitive metadata

Then:

bash
firescan --config .firescan.yaml --ignore-file .firescan-ignore.yaml

Monitoring 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 push

Generate 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.json

Troubleshooting CI/CD Integration

Issue: Scans Timeout

Reduce concurrency:

yaml
options:
  concurrency: 10  # Lower number
  timeout: 5m

Issue: Too Many Findings

Start with critical only:

bash
if grep -q '"severity":"Critical"' scan-results.json; then
  exit 1
fi
# Ignore High/Medium initially

Issue: API Rate Limiting

Add rate limiting:

yaml
options:
  rate-limit: 10  # Requests per second

Next 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.