Skip to content
Visibility internal Owner _ Approver _ Created _ Updated _

scan-live.sh



FieldValue
TypeShell
SourceForge/Skills/Security_Scan/scripts/scan-live.sh
ParentForge
GitHubForge/Skills/Security_Scan/scripts/scan-live.sh

This page is auto-generated. Edit the source to change the content.



#!/usr/bin/env bash
# Runs DAST against a LIVE target. Refuses to run unless the host is listed
# in the scope file -- this is what stops a typo from scanning production or
# somebody else's server.
#
# Scope file: .security-scan/scope.txt  (one hostname per line, # for comments)
#
# Usage: scan-live.sh --target https://staging.example.com [--out DIR] [--active]
#
# Default is a PASSIVE baseline: it crawls and inspects responses but does not
# send attack payloads. --active sends real payloads and can mutate data --
# only use it against a disposable environment with seeded data.
set -uo pipefail

TARGET=""
OUT=".security-scan/results"
SCOPE=".security-scan/scope.txt"
ACTIVE=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --target) TARGET="$2"; shift 2 ;;
    --out) OUT="$2"; shift 2 ;;
    --scope) SCOPE="$2"; shift 2 ;;
    --active) ACTIVE=1; shift ;;
    *) echo "unknown argument: $1" >&2; exit 2 ;;
  esac
done

if [[ -z "$TARGET" ]]; then
  echo "error: --target is required. This script will not guess a target." >&2
  exit 2
fi

HOST="$(printf '%s' "$TARGET" | sed -E 's#^[a-zA-Z]+://##; s#[:/].*$##')"

if [[ ! -f "$SCOPE" ]]; then
  cat >&2 <<EOF
error: no scope file at $SCOPE

Create it and list the hosts you are authorised to scan, one per line:

  mkdir -p "$(dirname "$SCOPE")"
  echo "staging.example.com" >> "$SCOPE"

Scanning a host you do not control is unlawful in most jurisdictions. The
scope file exists so that is a deliberate act rather than a typo.
EOF
  exit 2
fi

if ! grep -qxF "$HOST" <(grep -vE '^\s*(#|$)' "$SCOPE"); then
  echo "error: '$HOST' is not listed in $SCOPE -- refusing to scan." >&2
  echo "In scope: $(grep -vE '^\s*(#|$)' "$SCOPE" | tr '\n' ' ')" >&2
  exit 2
fi

mkdir -p "$OUT"
# Absolute path for report output (native ZAP cwd, or Docker volume mount).
OUT_ABS="$(cd "$OUT" && pwd)"
echo "target:   $TARGET"
echo "host:     $HOST (in scope)"
echo "mode:     $([[ $ACTIVE == 1 ]] && echo 'ACTIVE -- sends payloads, may mutate data' || echo 'passive baseline')"
echo

if [[ $ACTIVE == 1 ]]; then
  echo "!!! Active mode. Confirm this is a disposable environment with seeded"
  echo "!!! data, not production. Ctrl-C within 10s to abort."
  sleep 10
fi

ZAP_SCRIPT=$([[ $ACTIVE == 1 ]] && echo "zap-full-scan.py" || echo "zap-baseline.py")
if command -v "$ZAP_SCRIPT" >/dev/null 2>&1 && command -v zap.sh >/dev/null 2>&1; then
  # Prefer native ZAP (Forgentic / Railway image — no Docker-in-Docker).
  echo ">>> ZAP (native $ZAP_SCRIPT)"
  (
    cd "$OUT_ABS"
    python3 "$(command -v "$ZAP_SCRIPT")" -t "$TARGET" -J zap.json -r zap.html
  ) || echo "    ZAP exited nonzero (alerts found or error) -- see $OUT/zap.html"
elif command -v docker >/dev/null 2>&1; then
  # Local fallback when ZAP is not installed natively.
  echo ">>> ZAP (Docker $ZAP_SCRIPT)"
  docker run --rm -v "$OUT_ABS:/zap/wrk/:rw" \
    ghcr.io/zaproxy/zaproxy:stable \
    "$ZAP_SCRIPT" -t "$TARGET" -J zap.json -r zap.html \
    || echo "    ZAP exited nonzero (alerts found or error) -- see $OUT/zap.html"
else
  echo "(ZAP not available -- need native zap.sh + $ZAP_SCRIPT, or Docker; skipping)"
fi

if command -v nuclei >/dev/null 2>&1; then
  echo ">>> Nuclei"
  NUCLEI_ARGS=(-u "$TARGET" -jsonl -o "$OUT/nuclei.jsonl" -severity low,medium,high,critical)
  [[ $ACTIVE == 0 ]] && NUCLEI_ARGS+=(-exclude-tags dos,fuzz,intrusive)
  nuclei "${NUCLEI_ARGS[@]}" || echo "    nuclei exited nonzero"
else
  echo "(nuclei not installed -- skipping)"
fi

echo
echo "=== results in $OUT ==="
ls -1 "$OUT" 2>/dev/null
exit 0