bbscanner / .github /workflows /deploy-hf.yml
Wuhp
Verify installed transport guards and expose intentional program-policy stops
13d625f
Raw History Blame Contribute Delete
11 kB
name: Deploy to Hugging Face Space
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: hf-deploy
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install test dependencies
run: python3 -m pip install --user -r requirements.txt
- name: Run offline regression and integration tests
env:
ZAP_API_KEY: test-key
run: python3 -m pytest -q tests/
- name: Validate Python backend syntax
run: python3 -m py_compile app/request_policy.py app/policy_entry.py app/resource_flow.py app/bounty_discovery.py app/arjun_runner.py app/dalfox_runner.py app/replay_inputs.py app/replay_runner.py app/replay_modules.py app/protocol_runner.py app/protocol_modules.py app/analysis_modules.py app/waf_runner.py app/target_import.py app/planning.py app/coverage.py app/sampling.py app/concurrency.py app/idor_module.py app/idor_runner.py app/main.py app/pipeline.py app/web_modules.py app/client_modules.py app/wapiti_guard.py app/wapiti_runner.py app/config.py app/module_inputs.py app/final_modules.py app/final_module_names.py app/nettacker_runner.py app/garak_runner.py app/template_builder.py app/review.py app/zap_control.py app/scope.py app/jwtcheck.py app/storage.py
- name: Validate dashboard JavaScript syntax
run: |
python3 - <<'PY'
from pathlib import Path
page = Path("app/index.html").read_text()
assert "<script>" in page and "</script>" in page
js = page.split("<script>", 1)[1].split("</script>", 1)[0]
Path("/tmp/asfb-inline.js").write_text(js)
PY
node --check /tmp/asfb-inline.js
node --check app/preferences.js
node tests/preferences_store_test.cjs
- name: Verify dashboard in Chromium with mocked APIs
env:
ASFB_PLAYWRIGHT_MODULE: ${{ runner.temp }}/asfb-ui/node_modules/playwright
run: |
npm install --prefix "$RUNNER_TEMP/asfb-ui" --no-save playwright@1.56.1
"$RUNNER_TEMP/asfb-ui/node_modules/.bin/playwright" install --with-deps chromium
node tests/dashboard_browser_smoke.cjs
- name: Save remote UI review screenshots
if: always()
uses: actions/upload-artifact@v4
with:
name: dashboard-ui-review
path: ui-review/
if-no-files-found: ignore
retention-days: 7
- name: Build and verify scanner container
run: |
docker build --progress plain -t asfb-ci .
docker run --rm -v "$PWD/tests:/app/tests:ro" --entrypoint /bin/sh asfb-ci -exc '
/usr/local/bin/trufflehog filesystem --help > /tmp/trufflehog-help
grep -q -- "no-verification" /tmp/trufflehog-help
/opt/asfb-venv/bin/python /app/tests/trufflehog_offline_smoke.py
/usr/local/bin/trivy sbom --help > /tmp/trivy-help
grep -q -- "--skip-db-update" /tmp/trivy-help
/usr/local/bin/osv-scanner scan source --help > /tmp/osv-help
grep -q -- "--sbom" /tmp/osv-help
grep -q -- "--output" /tmp/osv-help
/usr/local/bin/kr brute --help > /tmp/kr-help
grep -q -- "--max-redirects" /tmp/kr-help
grep -q -- "--force-method" /tmp/kr-help
grep -q -- "--header" /tmp/kr-help
grep -q -- "--delay" /tmp/kr-help
/usr/local/bin/amass enum -help > /tmp/amass-help 2>&1 || true
grep -q -- "-passive" /tmp/amass-help
grep -q -- "-timeout" /tmp/amass-help
/opt/depscan/bin/depscan --help > /tmp/depscan-help
grep -q -- "--bom" /tmp/depscan-help
grep -q -- "--reachability-analyzer" /tmp/depscan-help
/opt/depscan/bin/depscan-vdb download --help > /tmp/depscan-vdb-help
grep -q -- "--scope" /tmp/depscan-vdb-help
/opt/idor-forge-venv/bin/python /app/tests/idor_offline_smoke.py
/opt/garak/bin/python /app/tests/final_python_smoke.py garak
/opt/nettacker/bin/python /app/tests/final_python_smoke.py nettacker
/opt/asfb-venv/bin/python -c "from pathlib import Path; from app.template_builder import build_draft; Path(\"/tmp/asfb-draft.yaml\").write_text(build_draft(\"CI observation\", \"/status\", \"healthy\"))"
/usr/local/bin/nuclei -validate -t /tmp/asfb-draft.yaml -duc > /tmp/asfb-draft-check 2>&1
/usr/local/bin/node /opt/retire/lib/cli.js --help > /tmp/retire-help
grep -q -- "--path" /tmp/retire-help
grep -q -- "--jsrepo" /tmp/retire-help
grep -q -- "--exitwith" /tmp/retire-help
/usr/local/bin/node /app/tests/retire_offline_smoke.js
/opt/wapiti/bin/python /app/app/wapiti_runner.py --help > /tmp/wapiti-help
grep -q -- "--max-scan-time" /tmp/wapiti-help
grep -q -- "--no-bugreport" /tmp/wapiti-help
/opt/wapiti/bin/python /app/tests/wapiti_offline_smoke.py
test -f /opt/nikto/program/nikto.pl
test -f /opt/testssl/testssl.sh
ruby -c /app/app/wpscan_runner.rb
ruby -c /app/app/wpscan_scope.rb
ruby /app/tests/test_wpscan_scope.rb
ruby /app/app/wpscan_runner.rb --hh > /tmp/wpscan-help
grep -q -- "--max-scan-duration" /tmp/wpscan-help
grep -q -- "--max-response-size" /tmp/wpscan-help
grep -q -- "--plugins-version-detection" /tmp/wpscan-help
grep -q -- "--themes-version-detection" /tmp/wpscan-help
grep -q -- "--throttle" /tmp/wpscan-help
perl /opt/nikto/program/nikto.pl -Help > /tmp/nikto-help
grep -q -- "-maxtime" /tmp/nikto-help
grep -q -- "-Pause" /tmp/nikto-help
grep -qi -- "Add-header" /tmp/nikto-help
bash /opt/testssl/testssl.sh --help > /tmp/testssl-help
grep -q -- "-S" /tmp/testssl-help
grep -q -- "--jsonfile" /tmp/testssl-help
test -s /home/zap/.cache/wpscan/db/metadata.json
test -x /usr/local/bin/ffuf
test -x /usr/local/bin/dalfox
test -x /usr/local/bin/nuclei
test -x /usr/local/bin/katana
test -x /usr/local/bin/gau
test -x /usr/local/bin/pd-httpx
test -f /opt/sqlmap/sqlmap.py
test -x /opt/asfb-venv/bin/arjun
/opt/asfb-venv/bin/python -c "import fastapi, httpx; import app.main, app.review"
/usr/local/bin/dalfox scan --help > /tmp/dalfox-help 2>&1 || true
grep -q -- "--workers" /tmp/dalfox-help
grep -q -- "--scan-timeout" /tmp/dalfox-help
grep -q -- "--skip-mining" /tmp/dalfox-help
grep -q -- "--max-payloads-per-param" /tmp/dalfox-help
grep -q -- "--rate-limit" /tmp/dalfox-help
grep -q -- "--skip-waf-probe" /tmp/dalfox-help
grep -q -- "--skip-reflection-header" /tmp/dalfox-help
grep -q -- "--skip-reflection-cookie" /tmp/dalfox-help
grep -q -- "--skip-reflection-path" /tmp/dalfox-help
grep -q -- "--skip-discovery" /tmp/dalfox-help
grep -q -- "--skip-xss-scanning" /tmp/dalfox-help
grep -q -- "--user-agent" /tmp/dalfox-help
grep -q -- "--headers" /tmp/dalfox-help
grep -q -- "--delay" /tmp/dalfox-help
/usr/local/bin/gau --help > /tmp/gau-help 2>&1 || true
grep -q -- "--providers" /tmp/gau-help
grep -q -- "--config" /tmp/gau-help
test -s /app/app/gau.toml
/opt/asfb-venv/bin/python /opt/sqlmap/sqlmap.py -hh > /tmp/sqlmap-help
grep -q -- "--ignore-redirects" /tmp/sqlmap-help
grep -q -- "--output-dir" /tmp/sqlmap-help
grep -q -- "--flush-session" /tmp/sqlmap-help
grep -q -- "-A" /tmp/sqlmap-help
grep -q -- "--headers" /tmp/sqlmap-help
/usr/local/bin/katana -h > /tmp/katana-help 2>&1 || true
grep -q -- "-depth" /tmp/katana-help
grep -q -- "-list" /tmp/katana-help
grep -q -- "-crawl-scope" /tmp/katana-help
grep -q -- "-disable-redirects" /tmp/katana-help
grep -q -- "-delay" /tmp/katana-help
/usr/local/bin/pd-httpx -h > /tmp/httpx-help 2>&1 || true
grep -q -- "-list" /tmp/httpx-help
grep -q -- "-content-type" /tmp/httpx-help
grep -q -- "-no-fallback-scheme" /tmp/httpx-help
grep -q -- "-delay" /tmp/httpx-help
/usr/local/bin/ffuf -h > /tmp/ffuf-help 2>&1 || true
grep -q -- "-json" /tmp/ffuf-help
/opt/asfb-venv/bin/arjun -h > /tmp/arjun-help 2>&1 || true
grep -q -- "-oJ" /tmp/arjun-help
/usr/local/bin/nuclei -validate -t /app/app/nuclei-templates -duc > /tmp/nuclei-validate 2>&1
/opt/asfb-venv/bin/python -c "from app import config; import pathlib; assert all(pathlib.Path(p).is_file() for p in config.NUCLEI_TEMPLATE_PATHS)"
/opt/asfb-venv/bin/python -c "from app import config; assert config.ARJUN_WORDLIST in (\"small\", \"medium\", \"large\")"
/opt/asfb-venv/bin/python -c "import pathlib; assert pathlib.Path(\"/opt/sqlmap/sqlmap.py\").is_file()"
'
- name: Verify new analysis engines without network access
run: |
docker run --rm --network none -v "$PWD/tests:/app/tests:ro" --entrypoint /bin/sh asfb-ci -ec '
/opt/wafw00f/bin/python /app/tests/analysis_offline_smoke.py wafw00f
/opt/asfb-venv/bin/python /app/tests/analysis_offline_smoke.py semgrep
/opt/protocol/bin/python /app/tests/protocol_offline_smoke.py
/opt/asfb-venv/bin/python /app/tests/replay_cli_smoke.py
/opt/asfb-venv/bin/python /app/tests/review_native_smoke.py
ruby /app/tests/wpscan_keyless_smoke.rb
/opt/wafw00f/bin/python /app/tests/policy_engine_smoke.py requests
/opt/wapiti/bin/python /app/tests/policy_engine_smoke.py httpx
/opt/nettacker/bin/python /app/tests/policy_engine_smoke.py aiohttp
'
- name: Validate Hugging Face token
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
if [ -z "$HF_TOKEN" ]; then
echo "::error::GitHub Actions secret HF_TOKEN is missing"
exit 1
fi
- name: Push source to wuhp/bbscanner
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
set -eu
# Authentication is supplied through a temporary HTTP header, not embedded in the remote URL.
BASIC_AUTH="$(printf 'oauth2:%s' "$HF_TOKEN" | base64 -w0)"
git -c http.extraheader="AUTHORIZATION: Basic $BASIC_AUTH" push --force https://huggingface.co/spaces/wuhp/bbscanner HEAD:main