Skip to main content

Scan from the CLI

Run your first scan from your terminal with Docker. This takes about 5 minutes.

Prerequisites

  • Docker (or Podman) installed and running
  • At least 2 GB of free RAM
  • A Levo account (sign up) — needed for dashboard reporting; optional for local-only scans
Using Podman?

Substitute podman for docker in every command below. On rootless or SELinux-enforcing hosts, append :U (and :Z if SELinux is enforcing) to the volume mounts — see Docker & Podman reference → Podman.

1. Pull the image

docker pull levoai/levoai-shadownet:stable

2. Run a scan

The simplest possible scan — a public URL, no authentication, results printed to your terminal:

docker run --rm -it --shm-size=1g \
levoai/levoai-shadownet:stable \
scan https://example.com
--shm-size=1g is required

The headless Chromium browser inside the container needs at least 1 GB of shared memory. Without this flag, scans crash mid-crawl with opaque errors.

3. Send findings to the Levo dashboard

Get your credentials. Log in and grab your Auth Key (Settings → API Keys), Organization ID, and Environment ID (Environments → copy ID).

Export them in your shell. Keeping credentials in env vars (instead of inline) keeps them out of shell history and lets you reuse them across runs:

export LEVOAI_AUTH_KEY=<your-auth-key>
export LEVOAI_ORG_ID=<your-org-id>
export LEVOAI_ENV_ID=<your-env-id>
export LEVOAI_BASE_URL=https://api.levo.ai

Scan and report findings:

docker run --rm -it --shm-size=1g \
-e LEVOAI_AUTH_KEY \
-e LEVOAI_ORG_ID \
-e LEVOAI_ENV_ID \
-e LEVOAI_BASE_URL \
-v $(pwd)/reports:/app/reports \
levoai/levoai-shadownet:stable \
scan https://example.com \
--send-issues \
--name "My First CLI Scan"

The bare -e VAR form forwards the variable's value from your shell — no need to repeat the secret on the command line.

Open Scans → DAST Scans in the Levo dashboard to see the run.

Persistent login (optional)

For repeated scans you can login once and skip the auth env vars on each run. The session is saved in /home/levo/.config/configstore inside the container — mount a host directory there to persist it:

docker run --rm -it \
-v $HOME/.config/configstore:/home/levo/.config/configstore:rw \
levoai/levoai-shadownet:stable \
login -k $LEVOAI_AUTH_KEY -o $LEVOAI_ORG_ID

On rootless Podman, change the trailing :rw to :U (or :U,Z on SELinux hosts).

4. Authenticated scan

For an app that requires login, keep credentials in env vars (same pattern as the Levo creds in Section 3) so secrets don't land in shell history:

export SCAN_USERNAME=you@example.com
export SCAN_PASSWORD=...

docker run --rm -it --shm-size=1g \
-e LEVOAI_AUTH_KEY -e LEVOAI_ORG_ID -e LEVOAI_ENV_ID -e LEVOAI_BASE_URL \
-e SCAN_USERNAME -e SCAN_PASSWORD \
levoai/levoai-shadownet:stable \
scan https://app.example.com \
--auth form \
--username "$SCAN_USERNAME" --password "$SCAN_PASSWORD" \
--login-url https://app.example.com/login

Prefer token auth for APIs:

export SCAN_TOKEN="Bearer <your-token>"

docker run --rm -it --shm-size=1g \
-e LEVOAI_AUTH_KEY -e LEVOAI_ORG_ID -e LEVOAI_ENV_ID -e LEVOAI_BASE_URL \
-e SCAN_TOKEN \
levoai/levoai-shadownet:stable \
scan https://api.example.com \
--auth token \
--token "$SCAN_TOKEN"

More options in the Authentication overview.

5. Swap flags for a config file

Once your flag list gets long, move the scan config into levo-dast.yml and commit it to git:

# levo-dast.yml
version: "1"
name: acme-webapp
target:
url: https://app.example.com
auth:
strategy: form
login_url: https://app.example.com/login
username: ${SCAN_USERNAME}
scan:
depth: smart
reporting:
output: sarif
fail_on: high
# Secrets stay in env vars, never in YAML.
SCAN_USERNAME=you@example.com SCAN_PASSWORD='secret' \
docker run --rm -it --shm-size=1g \
-v $(pwd)/levo-dast.yml:/app/levo-dast.yml \
-e SCAN_USERNAME -e SCAN_PASSWORD \
-e LEVOAI_AUTH_KEY -e LEVOAI_ORG_ID -e LEVOAI_ENV_ID \
levoai/levoai-shadownet:stable \
scan

Next steps

Was this page helpful?