Continuous pentesting runs a scoped AI pentest on what each release changes: on every merge, after a deploy, or on a schedule. Each run reads the commits since the last run, tests the routes those changes reach, and replays every open issue against your live app. This page shows you how to set it up, what a run does, and what it doesn't cover yet.

*A Delta Assessment: new issues from the change, known issues replayed, and the code analyzed.*

## When to Use It

A full-scope AI pentest describes your app on the day it ran. Continuous pentesting keeps that picture current between full assessments, without rerunning a full pentest for every release.

| You need | Use |
| --- | --- |
| A deep assessment of the whole app, before an audit or a major release | A full-scope [AI pentest](<https://docs.escape.tech/documentation/ai-pentesting/quickstart/index.md>) |
| Pentest depth on each change, between full assessments | Continuous pentesting |
| Fast, known checks on every build, or testing without source code | [DAST](<https://docs.escape.tech/documentation/dast/index.md>) |

Continuous runs are white-box: they read your code from GitHub. If you can't share source code, use DAST.

## Prerequisites

- An **AI Pentesting profile** on a web app, REST API, or GraphQL API. Mobile app profiles don't support continuous pentesting.
- The **Escape GitHub App** installed with access to the repositories behind the app. See the [GitHub integration](<https://docs.escape.tech/documentation/asm/integrations/github/index.md>).
- Permission to edit the AI Pentesting profile.
- The deployed target and its credentials, configured as for your full-scope assessment. See [Authentication](<https://docs.escape.tech/documentation/platform/authentication/index.md>).

> [!TIP]
>
> **Start from a full-scope assessment**
>
> Run a full-scope white-box assessment on the profile first. Continuous runs start from the latest one, so the agents already know your app before they test changes.

## Set Up Continuous Pentesting

1. Open your profile from **AI Pentesting \> [Profiles](<https://app.escape.tech/pentest/profiles/>)**.
2. On the **Continuous pentesting** banner, click **Set up continuous pentesting**.
3. Under **Trigger**, pick when runs start: **On every merge**, **After a deploy**, or **On a schedule**. See [Triggers](<#triggers>).
4. Under **Repositories**, add the GitHub repositories behind the app and pick the branch to watch on each. The form preselects the default branch. We recommend watching 3 repositories at most per profile.
5. Click **Set up continuous pentesting**.

The banner now shows **Live** with the trigger and the next run. To change the trigger or the repositories later, click **Settings** on the banner.

Before saving, Escape checks that it reads every repository on its branch. If one isn't visible to a GitHub App installation, or the branch doesn't exist, nothing is saved and the form tells you which repository failed.

## Triggers

Each profile has one trigger.

### On Every Merge

Escape starts a run when the installed GitHub App sees a push to a watched branch. There's no workflow to add to your repository. Branch deletions and tag pushes don't start a run.

When you watch several repositories, a merge to any of them starts a run, and that run covers the new commits on every watched repository, not only the one that was merged.

### After a Deploy

Your pipeline starts a run once your deploy stage finishes. Place the step **after** the deploy: a run against a build that isn't deployed yet tests the old version of your app.

Store two secrets in your CI: `ESCAPE_API_KEY` (from your [user settings](<https://app.escape.tech/user/profile/>)) and `ESCAPE_PROFILE_ID`. For the CLI and Public API examples, expose both secrets as environment variables to the step. Then call Escape in one of these ways:

```yaml
- name: Escape continuous pentest
  uses: Escape-Technologies/cli@v1.15.0
  with:
    profile_id: ${{ secrets.ESCAPE_PROFILE_ID }}
    api_key: ${{ secrets.ESCAPE_API_KEY }}
    continuous: 'true'
```

With `continuous: 'true'`, the Action runs `continuous-scans start` instead of a full scan and passes `GITHUB_SHA` as the commit tag. `configuration_override` isn't supported for continuous runs.

```bash
escape-cli continuous-scans start "$ESCAPE_PROFILE_ID"
```

Requires `escape-cli` 1.15.0 or later. Add `--watch` to block until the run ends, and `--fail-on-severity` (with `--watch`) to fail the job on new issues at or above a severity. See the [CLI documentation](<https://docs.escape.tech/documentation/automate/cli/index.md>).

```bash
curl -X POST https://public.escape.tech/v3/continuous-scans \
  -H "X-ESCAPE-API-KEY: $ESCAPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"profileId\": \"$ESCAPE_PROFILE_ID\"}"
```

The response is the scan, and its `id` is the scan ID. Use this from GitLab CI, Bitbucket Pipelines, Jenkins, or any CI that sends an HTTP request.

When you watch more than one repository and want to pin the run to the commit you just deployed, pass that commit and its repository: `--continuous-commit-hash` and `--repository-url` on the CLI, or `continuous.commitHash` and `continuous.repositoryUrl` in the API body. Other watched repositories use their branch head.

> [!NOTE]
>
> The `continuous-scans` API route and the CLI commands are tagged Beta. Continuous pentesting itself is generally available.

### On a Schedule

Runs start on a daily, weekly, or monthly schedule. Daily is the most frequent cadence. Click **Run now** on the setup page to start an extra run right away.

## What a Run Does

Each run follows the same steps:

1. **Reads what changed.** It collects the commits on each watched branch since the last run.
2. **Analyzes the changed code.** Static analysis runs on the change and reports only the issues the change introduced.
3. **Maps the change to routes.** A change to shared code, such as a middleware or an auth helper, opens risk on routes whose own code never moved. The run maps the change to every route it reaches, up to 20 routes per run.
4. **Attacks those routes.** [Cascade](<https://docs.escape.tech/documentation/ai-pentesting/multi-agent-pentest/index.md>) agents test the routes against your deployed app. When a route fronts a chatbot, an AI agent, or an MCP server, the run applies AI red teaming techniques.
5. **Replays every open issue.** In parallel, the run replays each open issue on the profile against the deployed app.

A run is capped at 60 minutes, and never runs longer than the profile's maximum duration. See [Guardrails](<https://docs.escape.tech/documentation/ai-pentesting/guardrails/index.md>).

### Where Each Run Starts

Continuous runs start from the latest full-scope assessment on the profile. When you turn continuous pentesting on, or turn it back on after a pause, each repository starts from its current commit.

### One Run at a Time

A merge or a schedule that fires while a run is in progress doesn't start a second run. The next run covers every commit since the last one.

### How Issues Change

- **New issues** from the change are filed like any other AI Pentesting issue, with their [Proof of Exploit](<https://docs.escape.tech/documentation/ai-pentesting/proof-of-exploit/index.md>).
- **Known issues** come back as replays, not as duplicates.
- An open issue moves to **Resolved** only when its replay verifies the fix. No retest request needed.
- A status you set yourself (ignored, false positive, manual review) never changes. A resolved issue isn't reopened by a replay.

Status changes trigger your [workflows](<https://docs.escape.tech/documentation/automate/index.md>) the same way as any other assessment.

## Read the Delta Assessment

Each run produces a **Delta Assessment**, listed in the profile's assessment history. Its summary has three cards:

| Card | What it shows |
| --- | --- |
| **New issues** | Issues the change introduced, by severity. |
| **Code analyzed** | The diff against the previous assessment: lines and files changed, per repository and branch. |
| **Replayed issues** | Known issues re-tested on this run, and the outcome of each replay. |

The **Reasoning** tab shows the agents' reasoning and each replay, so you see what the run tested and why.

## Pause Continuous Pentesting

On the setup page, click **Disable** to pause continuous pentesting. A run in progress finishes. Your repositories and settings are kept.

Click **Enable** to turn it back on. Each repository restarts from its current commit, so **commits made while it was paused aren't tested**. Run a full-scope assessment after a long pause.

To manage the setup from a terminal, use `escape-cli profiles continuous-pentest` with `create`, `update`, `enable`, or `disable`.

## Limits

- **White-box only.** Continuous runs need your source code. Without it, use [DAST](<https://docs.escape.tech/documentation/dast/index.md>).
- **GitHub only.** Runs read code from GitHub repositories. Any CI triggers a run through the API, but the code must be on GitHub.

## FAQ

**Does it replace my full-scope pentest?** No. Start from a full-scope assessment and run one again after big changes or a long pause. Continuous runs keep it current in between.

**Does it replace DAST?** No. DAST runs fast, known checks on every build, without source code. Continuous pentesting goes deeper on the apps where business logic matters, each time their code changes.

**Will it flood my team with findings?** No. Known issues come back as replays, not new findings, and a run reports what the change introduced.

**Does it slow down my pipeline?** No. Runs happen on Escape's side. The merge trigger needs no pipeline step, and the deploy trigger is one API call your build doesn't wait on unless you add `--watch`.

## Related

- [Whitebox Agent](<https://docs.escape.tech/documentation/ai-pentesting/whitebox-agent/index.md>)
- [Issue Retest](<https://docs.escape.tech/documentation/platform/issue-retest/index.md>)
- [GitHub CI/CD](<https://docs.escape.tech/documentation/automate/ci-cd/github/index.md>)
- [Guardrails](<https://docs.escape.tech/documentation/ai-pentesting/guardrails/index.md>)
