# Scans Management

Scans are the core of Escape's security testing capabilities. Each scan executes comprehensive security tests against your applications, identifying vulnerabilities, misconfigurations, and security risks.

## Understanding Scans

A scan represents a single execution of security tests against a configured profile. During a scan, Escape:

- Analyzes your application's API or web interface
- Tests for security vulnerabilities across multiple categories
- Generates detailed findings with reproduction steps
- Provides remediation guidance for identified issues

Scans can be triggered manually, scheduled automatically, or integrated into CI/CD pipelines.

## Listing Scans

List scans with flexible filtering. By default the CLI returns DAST and AI Pentesting kinds (`BLST_REST`, `BLST_GRAPHQL`, `FRONTEND_DAST`, `AUTOMATED_PENTEST`). Use `--all-kinds` to include ASM and every other scan kind.

```bash
escape-cli scans list [flags]
```

**Aliases:** `list`, `ls`

**Filtering Options:**

| Flag | Short | Description | Values |
| --- | --- | --- | --- |
| `--profile-id` | `-p` | Filter by profile ID(s) | Comma-separated UUIDs |
| `--status` | `-s` | Filter by scan status | `STARTING`, `RUNNING`, `FINISHED`, `FAILED`, `CANCELED` |
| `--kind` | `-k` | Filter by scanner type (overrides the default kind set) | `BLST_REST`, `BLST_GRAPHQL`, `FRONTEND_DAST`, `AUTOMATED_PENTEST` |
| `--all-kinds` |  | Include ASM and every scan kind. Default is DAST + AI Pentest. | \- |
| `--limit` |  | Cap how many scans are fetched (`0` = no limit) | Integer |
| `--initiator` | `-i` | Filter by initiator | `MANUAL`, `API`, `SCHEDULED`, `CI` |
| `--after` |  | Show scans after date | RFC3339 format (for example 2025-01-01T00:00:00Z) |
| `--before` |  | Show scans before date | RFC3339 format |
| `--project-id` |  | Filter by project ID(s) | Comma-separated UUIDs |
| `--asset-id` | `-a` | Filter by asset ID(s) | Comma-separated UUIDs |
| `--sort-by` |  | Sort field | `createdAt` |
| `--sort-direction` |  | Sort direction | `asc`, `desc` |
| `--ignored` |  | Filter by ignored status | `true`, `false` |

**Basic Example:**

```bash
# List all scans for a profile
escape-cli scans list -p 11111111-1111-1111-1111-111111111111
```

**Advanced Filtering Examples:**

```bash
# List only running scans
escape-cli scans list --status RUNNING

# List failed scans from last week
escape-cli scans list --status FAILED --after 2025-01-01T00:00:00Z

# List CI-triggered scans for multiple profiles
escape-cli scans list -p profile-1,profile-2 -i CI

# List REST API scans only
escape-cli scans list --kind BLST_REST

# List AI Pentesting scans
escape-cli scans list --kind AUTOMATED_PENTEST

# Include ASM and other scan kinds
escape-cli scans list --all-kinds

# Export to JSON
escape-cli scans list -o json > scans.json
```

**Example Output:**

```text
ID                                      CREATED AT                           KIND           STATUS      PROGRESS    LINK
11111111-1111-1111-1111-111111111111    2025-02-05 08:34:47.541 +0000 UTC    BLST_REST      FINISHED    1.000000    https://...
22222222-2222-2222-2222-222222222222    2025-02-02 08:27:23.919 +0000 UTC    BLST_GRAPHQL   RUNNING     0.453000    https://...
33333333-3333-3333-3333-333333333333    2025-01-31 18:35:48.477 +0000 UTC    FRONTEND_DAST  FINISHED    1.000000    https://...
```

### Scan Statuses

| Status | Description |
| --- | --- |
| `STARTING` | Scan initialization |
| `RUNNING` | Scan actively executing |
| `FINISHED` | Scan completed successfully |
| `FAILED` | Scan encountered an error |
| `CANCELED` | Scan was manually cancelled |

### Scanner Types

| Type | Description |
| --- | --- |
| `BLST_REST` | REST API security testing |
| `BLST_GRAPHQL` | GraphQL API security testing |
| `FRONTEND_DAST` | Web application security testing |
| `AUTOMATED_PENTEST` | AI Pentesting |

### Scan Initiators

| Initiator | Description |
| --- | --- |
| `MANUAL` | Manually started via UI or CLI |
| `API` | Started via API call |
| `SCHEDULED` | Scheduled/cron triggered |
| `CI` | CI/CD pipeline triggered |

## Getting Scan Details

Retrieve detailed information about a specific scan.

```bash
escape-cli scans get <scan-id>
```

**Aliases:** `describe`, `show`, `status`

**Example:**

```bash
escape-cli scans get 11111111-1111-1111-1111-111111111111
```

**Table Columns:** `ID`, `CREATED AT`, `FINISHED AT`, `KIND`, `STATUS`, `PROGRESS`, `SCORE`, `COVERAGE`, `DURATION`, `PROFILE ID`, `ORG ID`, `COMMIT BRANCH`, `COMMIT HASH`, `COMMIT AUTHOR`, `LINK`.

## Starting a Scan

Initiate a new security scan against a profile.

### Basic Usage

```bash
escape-cli scans start <profile-id>
```

**Example:**

```bash
escape-cli scans start 11111111-1111-1111-1111-111111111111
```

The command returns the scan ID. Save it to monitor progress:

```bash
SCAN_ID=$(escape-cli scans start <profile-id> -o json | jq -r '.id')
echo "Started scan: $SCAN_ID"
```

### Start and Watch

Monitor the scan in real-time by adding the `--watch` flag:

```bash
escape-cli scans start <profile-id> --watch
```

**Short form:**

```bash
escape-cli scans start <profile-id> -w
```

### Failing the Pipeline on Severity

With `--watch`, `--fail-on-severity LEVEL` makes the command exit non-zero when the finished scan has an open issue at or above `LEVEL`:

```bash
escape-cli scans start <profile-id> --watch --fail-on-severity HIGH
```

**Rules:**

- `LEVEL` is an issue severity: `INFO`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` (matched without case).
- On `scans start`, the flag requires `--watch`.
- `OPEN` and `MANUAL_REVIEW` issues count. Resolved, ignored, and false-positive issues do not.
- The error is `N issue(s) at or above LEVEL`, written to stderr; the process exits 1. In `-o json` mode stdout still holds the single scan document.

A failed, canceled, or unfinished scan also exits non-zero, so a pipeline stops on scan failures as well as on findings.

### Including Commit Metadata

When running scans from CI/CD pipelines, include commit information for better traceability:

```bash
escape-cli scans start <profile-id> \
  --commit-hash "a1b2c3d4" \
  --commit-branch "feature/security-improvements" \
  --commit-author "john.doe@example.com" \
  --commit-link "https://github.com/org/repo/commit/a1b2c3d4" \
  --profile-picture "https://github.com/johndoe.png"
```

**Available commit metadata flags:**

| Flag | Description | Example |
| --- | --- | --- |
| `--commit-hash` | Git commit SHA | `a1b2c3d4` |
| `--commit-branch` | Branch name | `main`, `feature/auth` |
| `--commit-author` | Author email | `dev@example.com` |
| `--commit-link` | Commit URL | Full GitHub/GitLab URL |
| `--profile-picture` | Author avatar URL | Avatar image URL |

### CI/CD Auto-Detection

Run the CLI binary directly in your CI job to include commit information automatically from its environment. The GitHub Action runs in Docker; automatic detection requires environment variables that the Action doesn't forward:

**GitHub Actions:**

- Auto-detects: `GITHUB_SHA`, `GITHUB_REF_NAME`, `GITHUB_ACTOR`, `GITHUB_ACTOR_ID`
- Automatically builds commit link from repository info

**GitLab CI:**

- Auto-detects: `CI_COMMIT_SHA`, `CI_COMMIT_REF_NAME`, `GITLAB_USER_EMAIL`
- Automatically builds commit link from `CI_PROJECT_URL`

**CircleCI:**

- Auto-detects: `CIRCLE_SHA1`, `CIRCLE_BRANCH`, `CIRCLE_USERNAME`

**Generic/Local:**

- Uses: `COMMIT_HASH`, `COMMIT_LINK`, `COMMIT_BRANCH`, `COMMIT_AUTHOR`

When these variables are available to the binary, it populates commit metadata automatically.

### Configuration Overrides

Override scan configuration for a single run using JSON that matches the [scanner configuration schema](<https://docs.escape.tech/documentation/reference/configuration-schemas/index.md>). Use top-level fields (there is no `scan` wrapper).

Max scan duration is configured on the profile (**Max scan duration**). Use `--override` only to change it for a single run.

```bash
escape-cli scans start <profile-id> \
  --override '{"mode": "read_only"}'
```

**Short form:**

```bash
escape-cli scans start <profile-id> -c '{"mode": "read_only"}'
```

**Common override examples:**

```bash
# Run scan in read-only mode (no mutations)
--override '{"mode": "read_only"}'

# Override max scan duration for this run only (minutes)
--override '{"max_duration": 240}'
```

`scans start --additional-properties '{"key":"value"}'` adds JSON properties to the scan request.

## Watching Scan Progress

Monitor a running scan until it reaches a terminal state.

```bash
escape-cli scans watch <scan-id>
```

This command:

- Polls scan status every few seconds (progress updates when the progress ratio changes)
- Prints a progress table while the scan is `STARTING`, `RUNNING`, or `PENDING`
- Fetches and lists issues **once** when the scan finishes (not as they are discovered)
- Blocks until the scan reaches a terminal status (`FINISHED`, `FAILED`, or `CANCELED`) or the API stops answering
- Returns exit code 0 only when the scan finishes and no severity gate fails. A failed scan (`scan <id> failed`), a canceled scan (`scan <id> was canceled`), or a watch that ends before a terminal status (`scan <id> did not finish (last status X)`) exits non-zero, so CI/CD pipelines fail on incomplete scans too
- Writes the error to stderr: in `-o json` mode stdout keeps the scan document (plus the issue list when the scan finishes) and no error document is added

With `--fail-on-severity LEVEL`, a finished scan with an open issue at or above `LEVEL` also exits non-zero. See [Failing the Pipeline on Severity](<#failing-the-pipeline-on-severity>).

Use `scans watch` for progress and the final issue list. For live scan event timelines, use the web UI or API.

**Example:**

```bash
# Start a scan and save the ID
SCAN_ID=$(escape-cli scans start <profile-id> -o json | jq -r '.id')

# Watch the scan progress
escape-cli scans watch $SCAN_ID
```

**Typical output:**

```text
STATUS    PROGRESS
RUNNING   25%
RUNNING   50%
FINISHED  100%

ID          SEVERITY  CATEGORY  NAME  LINK
...
```

## Retrieving Scan Issues

Fetch one page of security findings from a scan. This command includes resolved and ignored issues. For complete results and CI gates, use the paginated `escape-cli issues list --scan-id <scan-id>` command, with `--status OPEN` for open findings.

```bash
escape-cli scans issues <scan-id>
```

**Aliases:** `issues`, `results`, `res`, `result`, `iss`

**Example:**

```bash
escape-cli scans issues 11111111-1111-1111-1111-111111111111
```

**Table Columns:** `ID`, `SEVERITY`, `CATEGORY`, `NAME`, `LINK`.

### Filtering Issues

Get specific issue details:

```bash
# Get issues in JSON format for parsing
escape-cli scans issues <scan-id> -o json

# Filter high severity issues
escape-cli scans issues <scan-id> -o json | jq '.[] | select(.severity=="HIGH")'

# Count issues by severity
escape-cli scans issues <scan-id> -o json | jq 'group_by(.severity) | map({severity: .[0].severity, count: length})'
```

## Targets, Coverage, and Agent Logs

| Command | Purpose | Options |
| --- | --- | --- |
| `scans targets <scan-id>` | List scan targets; alias `target`. | `--type` (`API_ROUTE` or `GRAPHQL_RESOLVER`), `--size` (total cap; `0` fetches all pages) |
| `scans coverage <scan-id>` | Summarize coverage; alias `cov`. | `--type`, `--coverage`, `--user`, `--size` filter the target sample; overall and per-user summaries remain exhaustive. |
| `scans reasoning <scan-id>` | Read agent reasoning logs; aliases `reasoning-logs`, `agent-reasoning`. | `--agent-id`, `--search`, `--list-limit`, `--hydrate-limit` |
| `scans agents <scan-id>` | List pentesting agents; alias `agent-list`. | `--search`, `--event-search`, `--roots-only` |

## Cancelling a Scan

Stop a running scan before it completes.

```bash
escape-cli scans cancel <scan-id>
```

**Example:**

```bash
escape-cli scans cancel 11111111-1111-1111-1111-111111111111
```

For **AI Pentesting** scans, cancellation immediately stops the currently running pentesting agent. Use it to interrupt an active agent run.

If you need to stop **all current and future AI Pentesting scans** for an organization, enable the AI Pentesting scan kill switch from **Organization Settings**. That setting cancels running AI Pentesting scans and blocks new AI Pentesting scans from starting until it's disabled again.

> [!NOTE]
>
> **When to Cancel Scans**
>
> - The scan is taking longer than expected
> - You need to update the profile configuration
> - Resources are needed for higher priority scans
> - The wrong profile or configuration was used

## Ignoring a Scan

Mark a scan as ignored, excluding it from reports and metrics.

```bash
escape-cli scans ignore <scan-id>
```

**Example:**

```bash
escape-cli scans ignore 11111111-1111-1111-1111-111111111111
```

**Use cases for ignoring scans:**

- Test runs during configuration
- Failed scans due to temporary issues
- Scans with incorrect settings
- Historical scans that should be excluded from metrics

## Listing Scans with Problems

List scans together with validation problems surfaced during execution (broken authentication, unreachable target, invalid schema). This is the scan-indexed counterpart of [`escape-cli problems`](<https://docs.escape.tech/documentation/automate/cli/problems/index.md>), which groups problems by profile.

```bash
escape-cli scans problems [flags]
```

**Aliases:** `problems`, `pb`

**Filtering Options:**

| Flag | Short | Description | Values |
| --- | --- | --- | --- |
| `--profile-id` | `-p` | Filter by profile ID(s) | Comma-separated UUIDs |
| `--project-id` |  | Filter by project ID(s) | Comma-separated UUIDs |
| `--asset-id` | `-a` | Filter by asset ID(s) | Comma-separated UUIDs |
| `--status` | `-s` | Filter by scan status | `STARTING`, `RUNNING`, `FINISHED`, `FAILED`, `CANCELED` |
| `--kind` | `-k` | Filter by scanner type | `BLST_REST`, `BLST_GRAPHQL`, `FRONTEND_DAST`, `AUTOMATED_PENTEST` |
| `--initiator` | `-i` | Filter by initiator | `MANUAL`, `API`, `SCHEDULED`, `CI` |
| `--after` |  | Show scans after date | RFC3339 format (for example 2025-01-01T00:00:00Z) |
| `--before` |  | Show scans before date | RFC3339 format |
| `--ignored` |  | Filter by ignored status | `true`, `false` |
| `--sort-by` |  | Sort field | for example `createdAt` |
| `--sort-direction` |  | Sort direction | `asc`, `desc` |

**Examples:**

```bash
# List all scans with problems
escape-cli scans problems

# Filter by profile
escape-cli scans problems --profile-id <profile-id>

# Filter by status
escape-cli scans problems --status FAILED

# Export to JSON
escape-cli scans problems -o json
```

**Example Output:**

```text
SCAN ID                                 STATUS    KIND          INITIATOR   PROBLEMS   CREATED AT                           LINK
11111111-1111-1111-1111-111111111111    FAILED    BLST_REST     SCHEDULED   2          2025-02-05 08:34:47.541 +0000 UTC    https://...
22222222-2222-2222-2222-222222222222    FAILED    FRONTEND_DAST MANUAL      1          2025-02-02 08:27:23.919 +0000 UTC    https://...
```

## Complete Scan Workflow

Here's a typical end-to-end scan workflow:

```bash
#!/bin/bash
set -euo pipefail

# Configuration
PROFILE_ID="11111111-1111-1111-1111-111111111111"

# Start the scan and capture ID
echo "Starting security scan..."
SCAN_ID=$(escape-cli scans start "${PROFILE_ID}" -o json | jq -r '.id')
echo "Scan ID: ${SCAN_ID}"

# Watch the scan progress
echo "Monitoring scan progress..."
escape-cli scans watch "${SCAN_ID}"

# Require a successful scan before evaluating findings.
[ "$(escape-cli scans get "$SCAN_ID" -o json | jq -r '.status')" = "FINISHED" ] || {
    echo "ERROR: Scan didn't finish successfully"
    exit 1
}

# Retrieve results
echo "Fetching scan results..."
escape-cli issues list --scan-id "${SCAN_ID}" --status OPEN -o json > scan-results.json

# Check for high severity issues
HIGH_ISSUES=$(jq '[.[] | select(.severity=="HIGH" or .severity=="CRITICAL")] | length' scan-results.json)

if [ "$HIGH_ISSUES" -gt 0 ]; then
    echo "ERROR: Found $HIGH_ISSUES high/critical severity issues"
    jq '.[] | select(.severity=="HIGH" or .severity=="CRITICAL") | {severity, name, category}' scan-results.json
    exit 1
else
    echo "SUCCESS: No high/critical severity issues found"
    exit 0
fi
```

## CI/CD Integration

### GitHub Actions Example

```yaml
name: Security Scan

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Install Escape CLI
        run: |
          curl -sf https://raw.githubusercontent.com/Escape-Technologies/cli/refs/heads/main/scripts/install.sh | sudo bash

      - name: Run Security Scan
        env:
          ESCAPE_API_KEY: ${{ secrets.ESCAPE_API_KEY }}
        run: |
          SCAN_ID=$(escape-cli scans start ${{ vars.PROFILE_ID }} \
            --commit-hash ${{ github.sha }} \
            --commit-branch ${{ github.ref_name }} \
            --commit-author ${{ github.actor }} \
            --commit-link ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} \
            -o json | jq -r '.id')

          escape-cli scans watch $SCAN_ID
          [ "$(escape-cli scans get "$SCAN_ID" -o json | jq -r '.status')" = "FINISHED" ]
          escape-cli issues list --scan-id "$SCAN_ID" -o json > results.json

      - name: Upload Results
        uses: actions/upload-artifact@v4
        with:
          name: security-scan-results
          path: results.json
```

See [CI/CD Integration](<https://docs.escape.tech/documentation/automate/ci-cd/index.md>) for more examples.

## Scan Scheduling

While the CLI allows on-demand scan execution, you can configure recurring scans through the Escape web interface:

1. Navigate to your profile settings
2. Configure the scan schedule (cron expression)
3. Set scan parameters and notification preferences

Scheduled scans run automatically without CLI intervention.

## Best Practices

### Scan Frequency

- **Production**: Weekly or bi-weekly scheduled scans
- **Staging**: After each deployment
- **Development**: On-demand or per pull request
- **Critical APIs**: Daily scans for high-value targets

### Resource Management

- Cancel stale or stuck scans to free resources
- Monitor scan duration and optimize configurations
- Stagger scheduled scans to avoid resource contention

### Result Management

- Archive scan results for compliance and auditing
- Track security trends over time
- Automate issue creation in bug tracking systems

### Error Handling

Always check scan status and handle failures:

```bash
if escape-cli scans start <profile-id>; then
    echo "Scan started successfully"
else
    echo "Failed to start scan"
    exit 1
fi
```

## Troubleshooting

### Scan Stuck in STARTING

If a scan remains in `STARTING`:

- Check location health: `escape-cli locations list`
- Verify the location is enabled and running
- Cancel and restart the scan if necessary

### Scan Fails Immediately

Common causes:

- Target application is unreachable
- Authentication credentials are invalid
- Network connectivity issues
- Configuration errors in the profile

Check scan details for error messages:

```bash
escape-cli events list --scan-id <scan-id> --levels ERROR
```

### No Issues Returned

If a scan completes but shows no issues:

- Verify the scan completed successfully
- Check the scan didn't run in read-only mode accidentally
- Review scan configuration for scope limitations

### Performance Issues

If scans take too long:

- Review scan configuration for unnecessary depth
- Enable read-only mode for faster passive scanning
- Consider splitting into multiple focused profiles

## Next Steps

- **[Issues Management](<https://docs.escape.tech/documentation/automate/cli/issues/index.md>)** - Learn to manage and triage security findings
- **[Locations Management](<https://docs.escape.tech/documentation/automate/cli/locations/index.md>)** - Configure scan execution locations
- **[Scan Problems](<https://docs.escape.tech/documentation/automate/cli/problems/index.md>)** - Troubleshoot scan failures
- **[Practical Recipes](<https://docs.escape.tech/documentation/automate/cli/recipes/index.md>)** - Complete scan automation examples
- **[CI/CD Integration](<https://docs.escape.tech/documentation/automate/ci-cd/index.md>)** - Integrate scans into your pipeline
