> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudthinker.io/llms.txt
> Use this file to discover all available pages before exploring further.

# App Pentesting

> Set up an app, attach a login and your source code, then let Oliver test it for security problems and show you the proof.

Oliver hunts for real security problems in your app and shows you the proof for each one. You set the boundaries once — what to test, what's off-limits, and what to sign in as — and Oliver tests as deeply as those allow.

<Note>App Pentesting is in beta. Find it under **App Pentesting** in the navigation menu.</Note>

## Prerequisites

* A domain you own, and the ability to add a DNS record for it.
* Optional: a connected Git provider, if you want Oliver to read your source code.

## Register your app

<Steps>
  <Step title="Open App Pentesting">
    Go to **App Pentesting** from the navigation menu, then click **Register your first app**. If you already have apps, click **New app** instead.

    <Frame>
      <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/01-appsec-empty-landing.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=17b4f9ef33d0f16574ccda81cee3b952" alt="App Pentesting landing page with the Register your first app call to action" width="3016" height="1716" data-path="images/security/pentest/01-appsec-empty-landing.png" />
    </Frame>
  </Step>

  <Step title="Describe the target">
    Enter an **App name** and a **Target** — a domain like `example.com` or an API base URL like `https://api.example.com/v1`. CloudThinker suggests an **OWASP framework** from the target: **OWASP Web** for a site, **OWASP API** for an API URL. Change it if the suggestion is wrong.

    <Frame>
      <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/02-new-app-dialog.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=63060e3d9bd684c4dc898ba09a8483a8" alt="New app dialog with App name, Target, and OWASP framework fields" width="3016" height="1716" data-path="images/security/pentest/02-new-app-dialog.png" />
    </Frame>
  </Step>

  <Step title="Create the app">
    Click **Create app**.

    **Success state:** the app overview opens and shows **No pentests yet**, with a **Verify domain** button. Verify the domain next — you can't run a pentest until you do.

    <Frame>
      <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/03-app-setup-hero.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=65ecc2110d8ff454c97ceb54b86bdf16" alt="App overview showing the No pentests yet setup hero" width="3016" height="1716" data-path="images/security/pentest/03-app-setup-hero.png" />
    </Frame>
  </Step>
</Steps>

## Verify the domain

CloudThinker only tests sites you can prove you own. You do this once per domain, and every app on that domain reuses the proof.

<Steps>
  <Step title="Add the domain">
    Open **App Pentesting → Settings**. Under **Verified domains**, click **Add domain** — or **Manage domains** if you have verified one before — and enter the host in the **Domain** field.

    <Frame>
      <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/04-manage-verified-domains.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=4eedc55312935fc1340d3d59b5264605" alt="Verified domains section with the add domain dialog open" width="3016" height="1716" data-path="images/security/pentest/04-manage-verified-domains.png" />
    </Frame>
  </Step>

  <Step title="Publish the TXT record">
    Copy the **TXT name** and **TXT value**, add them at your DNS provider, then click **Check DNS**. DNS propagation can take a few minutes, so retry if the first check fails.

    **Success state:** the domain badge reads **Verified**.

    <Frame>
      <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/05-verify-domain-txt.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=90c26620075551ae0c14ef5ff0ab00fd" alt="Verify domain dialog showing the TXT name and TXT value to publish" width="3016" height="1716" data-path="images/security/pentest/05-verify-domain-txt.png" />
    </Frame>
  </Step>
</Steps>

## Set the boundaries

Open the app's **Settings** tab. What you set here decides how much Oliver can find. Everything saves as you type — there's no save button.

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/06-app-settings.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=b62befda9dc1e5c9b97ce2d5bfe29669" alt="App Settings tab with domain verification, scope, context files, repositories, test identities, schedule, and default intensity" width="3016" height="1716" data-path="images/security/pentest/06-app-settings.png" />
</Frame>

| Section               | What to do                                                                                                                                                                             | Why it matters                                                                    |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| **Scope**             | Click **Manage scope**. Add the paths Oliver may test under **Include paths** (`/api/**`), and anything off-limits under **Exclude paths** (`/admin/**`). Type a path and press Enter. | Your fence. Oliver never touches anything outside it.                             |
| **Test identities**   | Click **Add authentication** and attach a login.                                                                                                                                       | Lets Oliver test behind the sign-in page instead of only the public pages.        |
| **Repositories**      | Click **Add repository**, pick a provider, then a repo and branch.                                                                                                                     | Lets Oliver read your code, so findings point at the exact line that caused them. |
| **Context files**     | Click **Attach context** to add an API spec, Postman collection, diagram, or docs — up to 10 MB each, or paste text inline.                                                            | Helps Oliver find things faster. Doesn't change how deep it tests.                |
| **Default intensity** | Pick how aggressive new runs start out.                                                                                                                                                | A starting point only — you can change it on any run.                             |

### Attach a login

Attach two logins and Oliver can prove the most valuable thing of all: that one customer cannot read another's data. Name them something like `victim` and `attacker`, and describe what each is allowed to see — their role, their team, the records they own. That description is how Oliver knows which access is a bug.

<Tabs>
  <Tab title="Session token">
    Best for web apps. Sign in, open your browser's developer tools, find any request on the **Network** tab, copy it as cURL, and paste it in. Click **Verify and attach** — CloudThinker replays it to confirm the login works before saving.
  </Tab>

  <Tab title="Long-lived token">
    Best for APIs. Add the header your API expects — usually `Authorization` set to `Bearer ...` — then click **Attach token**. These don't expire, so scheduled runs keep working.
  </Tab>
</Tabs>

**Success state:** the identity shows a **Ready for testing** chip.

## How deep Oliver goes

The more you attach, the more Oliver can reach. You don't choose this — Oliver takes the deepest level available and shows it as an **Access level** badge in the run dialog.

| What you attached | Access level | What Oliver can test                      |
| ----------------- | ------------ | ----------------------------------------- |
| Nothing           | Black-box    | Only what a stranger on the internet sees |
| A login           | Gray-box     | Everything a signed-in user sees          |
| A repository      | White-box    | The running app plus the code behind it   |

One catch: browser sessions expire. An app with only a session tests as gray-box when you click **Run now**, but drops to black-box on a schedule, because the session dies before the scheduled run fires. Attach a long-lived token or a repository to keep the depth.

## Run the pentest

Click **Run pentest**. Everything lives in one dialog. **Setup** at the top repeats your target, framework, and scope so you can catch a mistake before anything is sent — **Edit setup ›** takes you back to fix it. Most runs finish in a few minutes and stop at 30.

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/07-run-pentest-modal.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=75bca7cfeefa47bc6747d24eb1738e4d" alt="Run pentest dialog with setup facts, intensity picker, access level badge, context, and schedule" width="3016" height="1716" data-path="images/security/pentest/07-run-pentest-modal.png" />
</Frame>

**Intensity** decides how far Oliver goes — and how much it can change:

| Intensity      | What Oliver does                                                            | Your data                                 |
| -------------- | --------------------------------------------------------------------------- | ----------------------------------------- |
| **Safe**       | Only reads pages and data                                                   | Never changed. Safe to run on production. |
| **Aggressive** | Submits forms and creates test data, to reach bugs reading alone can't find | Added and edited, never deleted           |
| **Full**       | Everything above, plus deletion attempts                                    | Can be permanently removed                |

<Warning>
  Narrow **Scope** before running Full against anything you care about.
</Warning>

**Access level** shows how deep this run goes; **Go deeper** tells you what to add to unlock more. If you attached a repository, you also pick a **Scan scope**: **Incremental** checks only what changed since your last run, **Full** checks everything. Your first run is always Full.

Then finish one of two ways:

* **Run now** starts immediately and opens the workbench.
* **Schedule** repeats it — **Daily**, **Weekly**, **Monthly**, **No Repeat**, or **Custom** — at a time you set, with an optional end date. Times use your local time and keep the same clock time year-round, so a run can land an hour off across a daylight saving change.

## Read the results

Watch the run happen. The **Timeline** in the middle narrates each step as Oliver works, findings appear on the right the moment they're confirmed, and past runs sit in **Run history** on the left. The full **Report** arrives when the run finishes.

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/08-run-workbench.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=54c4d45fb50743c87bef4b42ddff2dcc" alt="Run workbench with run history, live timeline, and the findings rail" width="3016" height="1716" data-path="images/security/pentest/08-run-workbench.png" />
</Frame>

Four tabs hold the results:

| Tab          | What it shows                                                                                                   |
| ------------ | --------------------------------------------------------------------------------------------------------------- |
| **Overview** | Your OWASP Top 10 coverage and how many findings sit at each severity                                           |
| **Surface**  | Everything Oliver found reachable — badged **Documented** if your specs mentioned it, **Shadow** if they didn't |
| **Runs**     | Every past run and what it added, fixed, or left open                                                           |
| **Findings** | The full list, filterable by severity and status                                                                |

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/09-overview-owasp-coverage.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=2d60d3c56695bf17c840651c9b681490" alt="Overview tab with OWASP Web Top 10 coverage, findings by severity, and the CWE mapping list" width="3016" height="1716" data-path="images/security/pentest/09-overview-owasp-coverage.png" />
</Frame>

Open any finding to see the proof. **Summary** says what's wrong, **Attack path** shows exactly how Oliver got in, **Safe PoC** is the request you can replay yourself, and **Remediation** says how to fix it — **Create PR with agent** turns that fix into a pull request.

A progress bar tracks the finding from **Needs triage** to **Verified fixed**. That last step isn't yours to click: the next scan re-tests it and confirms the fix for you.

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/10-findings-workspace.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=1329ca30ff63d36fa23f4b48b3c02a32" alt="Findings table with search, severity and status filters, and columns for affected surface, OWASP category, severity, and status" width="3016" height="1716" data-path="images/security/pentest/10-findings-workspace.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/cloudthinker/r10lJzyUXeH0AKVA/images/security/pentest/11-finding-detail-evidence.png?fit=max&auto=format&n=r10lJzyUXeH0AKVA&q=85&s=57c0c191e88da2917807a1112464b938" alt="Finding detail with the triage rail, summary, attack path, safe PoC, and remediation" width="3016" height="1716" data-path="images/security/pentest/11-finding-detail-evidence.png" />
</Frame>

## Troubleshooting

<AccordionGroup>
  <Accordion title="A saved login no longer works">
    Your session expired. Rather than quietly testing as a logged-out visitor and reporting less than it should, Oliver stops. Click **Update login**, remove the one marked **Needs refresh**, and add a fresh one. If this keeps happening, attach a long-lived token instead — those don't expire.
  </Accordion>

  <Accordion title="Domain verification required">
    Your TXT record is missing, or DNS hasn't caught up yet. Compare the record at your DNS provider against the **TXT name** and **TXT value** in the verify dialog, wait a few minutes, then click **Check DNS** again.
  </Accordion>

  <Accordion title="The repository dialog shows Connect provider">
    No Git provider is connected to your workspace yet. Click **Connect provider**, finish connecting, then reopen the dialog.
  </Accordion>

  <Accordion title="Incremental scan scope is greyed out">
    Incremental compares against your last successful run, so you need one first. Run a Full scan, and Incremental becomes available after it.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Oliver" icon="user-shield" href="/guide/agents/oliver">
    Meet the Security Engineer agent that runs your pentests and triages the findings
  </Card>

  <Card title="Code Review" icon="code-pull-request" href="/guide/code-review/overview">
    Catch the same classes of vulnerability on every pull request, before they ship
  </Card>

  <Card title="Security" icon="lock" href="/guide/security/overview">
    Harden workspace access itself with MFA, SSO, and single-purpose API keys
  </Card>

  <Card title="Connections" icon="plug" href="/guide/connections/overview">
    Connect the Git provider that unlocks white-box testing against your source
  </Card>
</CardGroup>
