Skip to content

ZAP Nightly Security Scan #47

ZAP Nightly Security Scan

ZAP Nightly Security Scan #47

---
name: "ZAP Nightly Security Scan"
on:
schedule:
# Run at 1:00 AM CET (00:00 UTC in winter, 23:00 UTC in summer)
# Using 00:00 UTC as approximation for 1am CET
- cron: '0 0 * * *'
workflow_dispatch: # Allow manual trigger
permissions:
contents: write
jobs:
zap-scan:
name: "OWASP ZAP DAST Scan"
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: POSTGRES_LOCAL_PWD
POSTGRES_DB: copi_dev
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Elixir and Erlang
uses: erlef/setup-beam@e6d7c94229049569db56a7ad5a540c051a010af9 # v1.20.4
with:
elixir-version: 1.18.2
otp-version: 27.3.3
env:
ImageOS: ubuntu24
- name: Cache deps
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: copi.owasp.org/deps
key: ${{ runner.os }}-mix-cache-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-cache-
- name: Install dependencies
working-directory: copi.owasp.org
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get
- name: Setup database
working-directory: copi.owasp.org
env:
MIX_ENV: dev
run: |
mix ecto.create
mix ecto.migrate
- name: Install Node.js dependencies
working-directory: copi.owasp.org/assets
run: npm install
- name: Build assets
working-directory: copi.owasp.org
env:
MIX_ENV: dev
run: mix assets.build
- name: Start Phoenix server in background
working-directory: copi.owasp.org
env:
MIX_ENV: dev
SECRET_KEY_BASE: ${{ secrets.SECRET_KEY_BASE || 'test_secret_key_base_for_ci_only_min_64_chars_long_required_here' }}
run: |
mix phx.server &
echo $! > phoenix.pid
- name: Wait for application to be ready
run: |
echo "Waiting for Phoenix server to start..."
timeout 60 bash -c 'until curl -f http://localhost:4000 > /dev/null 2>&1; do sleep 2; done'
echo "Phoenix server is ready!"
- name: Run ZAP Full Scan with AJAX Spider
run: |
mkdir -p zap-reports
sudo chown 1000:1000 zap-reports
docker run --network="host" \
--user 1000:1000 \
-v $(pwd)/zap-reports:/zap/wrk/:rw \
-t ghcr.io/zaproxy/zaproxy:stable \
zap-full-scan.py \
-t http://localhost:4000/games/new \
-j \
-r copi_dast_report.html \
-w copi_dast_report.md \
-J copi_dast_report.json \
-x copi_dast_report.xml \
-a \
-d \
-z "-config ajaxSpider.maxDuration=10 -config scanner.maxScanDurationInMins=180" \
|| true
- name: Stop Phoenix server
if: always()
working-directory: copi.owasp.org
run: |
if [ -f phoenix.pid ]; then
kill $(cat phoenix.pid) || true
rm phoenix.pid
fi
- name: Upload ZAP reports as artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: zap-dast-reports
path: zap-reports/
retention-days: 30
- name: Check for high-risk vulnerabilities
if: always()
run: |
if [ -f zap-reports/copi_dast_report.json ]; then
echo "Checking for high-risk vulnerabilities..."
HIGH_RISK=$(jq '[.site[].alerts[] | select(.riskcode == "3")] | length' zap-reports/copi_dast_report.json || echo "0")
MEDIUM_RISK=$(jq '[.site[].alerts[] | select(.riskcode == "2")] | length' zap-reports/copi_dast_report.json || echo "0")
echo "High Risk Vulnerabilities: $HIGH_RISK"
echo "Medium Risk Vulnerabilities: $MEDIUM_RISK"
if [ "$HIGH_RISK" -gt "0" ]; then
echo "⚠️ WARNING: $HIGH_RISK high-risk vulnerabilities detected!"
echo "Please review the ZAP report for details."
fi
else
echo "ZAP report not found, skipping vulnerability check"
fi
- name: Upload reports to pre-release
if: always()
run: |
for f in \
zap-reports/copi_dast_report.html \
zap-reports/copi_dast_report.json \
zap-reports/copi_dast_report.xml \
zap-reports/copi_dast_report.md; do
if [ -f "$f" ]; then
gh release upload "pre-release" "$f" --clobber
fi
done
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}