---
description: Real-browser Playwright DAST for local web targets, with route, session, authorization, client, and evidence coverage
agents: [pentester]
task_types: [security, dast]
triggers: [browser dast, dynamic scan, playwright security]
---

# Pentester — Browser DAST Playbook

Load this only when the app is browser-accessible on `localhost` or `127.0.0.1`. This is a real Chromium execution path through Playwright, not an HTML-only approximation. Browser automation complements source review and API/manual probes; it cannot prove server-side authorization or business invariants by itself.

## Prerequisite gate

1. Confirm the authorized origin and reject public, production, shared, or third-party targets.
2. Require a valid project-local `aios-qa.config.json` and a reachable local URL.
3. Run `aioson qa:doctor .` and inspect every failed check.
4. Reuse project-local `playwright` and its Chromium binary. Never install Playwright, browsers, proxies, certificates, or extensions without explicit user approval.
5. If any prerequisite is missing, record affected WSTG/browser/endpoint rows as `not_tested` with the exact reason; continue with safe static coverage when possible.

## Phase 0 — AIOSON baseline

Run the existing baseline before targeted probes:

```bash
aioson qa:run . --persona=hacker --url=http://127.0.0.1:3000
aioson qa:scan . --url=http://127.0.0.1:3000 --depth=3 --max-pages=50
```

Use only the authorized local origin and conservative crawl limits. Import automated results as `status: needs_validation` candidates. Pentester validates the real execution path and adds safe evidence; Pentester does not make QA's final severity or acceptance decision.

Preserve:

- tool/CLI version, command, configuration, start/end time and exit state;
- discovered sanitized routes and methods;
- report/screenshot paths without embedding secrets or sensitive response bodies;
- console, network and browser errors relevant to a candidate.

A clean baseline is not a clean security review. Continue through every phase triggered by the target profile.

## Browser context model

Create independent contexts rather than reusing cookies or storage:

- anonymous;
- identity A / owner;
- identity B / other user or tenant;
- privileged identity, only when an authorized fixture exists.

Record roles, never credentials. For each context, capture the start URL, authenticated landing state, cookies/storage inventory, discovered routes and API calls. Close contexts and revoke/clean fixture state after the run.

## Operator-interactive authentication

When a protected local route has no prepared authorized fixture session:

1. Launch the project-local Chromium with `headless: false` at the authorized login URL.
2. Tell the operator to enter login, password, MFA, SSO, CAPTCHA, or recovery input directly in the real page. Never ask for a credential in chat, a shell argument, configuration, source, an AIOSON artifact, or a report.
3. Before input begins, disable screenshots, video, tracing, form-value inspection, and request/response-body capture for the authentication ceremony. Do not read DOM input values or export Playwright `storageState`.
4. Keep the authenticated browser context live only in memory. Resume after the operator confirms completion or the declared non-secret landing state is reached.
5. Repeat the ceremony in a fresh context for each authorized role needed by the matrix. Never copy cookies or tokens between roles.
6. On cancellation, timeout, unavailable headed Chromium, or absent roles, close the context and mark only the affected routes/controls `not_tested` with the prerequisite reason.

Do not claim complete authorization coverage from an administrator alone. Prefer anonymous, owner A, other user or tenant B, and a privileged test identity. The operator's real production account is outside scope; use disposable local/test identities. After probing, log out or revoke the fixture sessions and close every context. Persist only `authentication_mode: operator_interactive`, role labels, sanitized routes, results, and safe evidence paths.

## Route and state inventory

Crawl navigation, forms, links, client router states, redirects, service-worker routes, XHR/fetch, GraphQL, WebSocket/SSE and downloads. Correlate browser-observed endpoints with source handlers and API documentation.

For each dynamic coverage entry store only:

```json
{
  "method": "PATCH",
  "url": "http://127.0.0.1:3000/api/orders/:id",
  "roles": ["owner", "other-user"],
  "status": "passed",
  "evidence": ["evidence/browser/owner-vs-other-order.json"]
}
```

Strip userinfo, query strings, fragments, tokens, personal data and secret values before persistence. A crawler that cannot reach an authenticated or client-only route must record that limitation.

## Response and transport controls

For main documents, redirects, API responses and sensitive downloads inspect:

- CSP, `frame-ancestors`, HSTS outside localhost expectations, `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy` and cache controls;
- CORS origin/credential behavior on actual APIs, including preflight, null/untrusted origins and response variance;
- content type and disposition for user-controlled or downloaded content;
- framework/version disclosure, debug headers, source maps, directory listings, backup/config assets and verbose errors;
- redirect destinations and Host/forwarded-host-derived absolute URLs;
- authenticated/private responses in browser, service-worker and intermediary caches.

Severity is contextual. A source map is not automatically high: validate whether it discloses non-public source, secrets, sensitive routes or exploitable logic. Missing headers are findings only when the relevant browser threat exists and the effective policy is weak.

## Cookies, sessions, JWT, and CSRF

After every identity transition inspect cookie attributes, domains, paths, expiry and rotation. Exercise login, privilege change, logout, refresh, password/reset flows and session revocation. Verify browser back/forward/cache does not reveal protected content after logout.

For every browser-reachable state-changing operation:

1. Identify whether authorization relies on cookies, bearer tokens, browser storage, or another credential.
2. Replay from a cross-site fixture origin with the anti-CSRF value absent, stale or mismatched.
3. Check Origin/Referer and content-type handling where part of the defense.
4. Verify login CSRF, token fixation, multi-tab/concurrent sessions and refresh replay where applicable.

SameSite or JSON alone is not proof. Store only the control result, sanitized request metadata and evidence path, never cookie/token values.

## Authorization in a real browser

With identity A, create or select a fixture resource. Replay the same navigation or captured API operation in identity B and a lower role. Test direct navigation, UI-hidden actions, downloads, client route guards, object identifiers, property edits and function access.

Expected behavior is server-side denial without sensitive rendering or side effects. A disabled button or redirect is not proof if the underlying request succeeds. Link the browser route to the server handler and `app_target_ownership_idor` coverage.

## Client injection and DOM boundaries

Use harmless unique markers in every reachable input that flows into HTML, attributes, URLs, script/config objects, CSS, SVG, markdown/rich text, DOM APIs, templates, `postMessage`, storage or a service worker. Verify the marker is rejected or encoded for its final context and cannot create script-capable markup or navigation.

Inspect:

- inline handlers, unsafe DOM sinks, framework raw-HTML APIs and hydration/state blobs;
- URL schemes, open redirects, DOM clobbering, prototype pollution and third-party widget inputs;
- message origin/source validation, iframe sandboxing and opener relationships;
- CSP violations and whether nonce/hash policies remain effective during navigation.

Do not persist executable payloads in HTML reports. Evidence should describe the safe sentinel and observed DOM/sink state.

## Browser storage, secrets, and privacy

Inspect local/session storage, IndexedDB, Cache Storage, service workers, cookies, DOM, page source and network metadata for session material, API keys, passwords, sensitive personal data and excessive cached responses.

Redact values immediately. Record storage key/type, sensitivity class, length or digest if needed, and evidence path. Browser-accessible tokens receive severity based on the actual XSS/threat model, lifetime, scope and revocability—not name matching alone.

Verify sensitive values do not appear in URLs, history, referrers, analytics calls, console messages, error pages, screenshots or HTML comments.

## Framing, navigation, and third-party resources

Verify effective `frame-ancestors`/frame policy on sensitive pages and attempt controlled framing from a local fixture origin. Inspect form/action targets, downloads, popups, `window.opener`, tabnabbing, external links and redirect chains.

Inventory third-party scripts, styles, frames and workers. Check trust justification, CSP allowance, integrity protection where technically supported, pinned/versioned loading, credential/referrer exposure and failure behavior. SRI absence alone is not necessarily a vulnerability for dynamically versioned resources; report the concrete supply-chain exposure.

## Realtime and client APIs

For WebSockets, SSE, GraphQL subscriptions and browser messaging verify:

- handshake authentication and Origin policy;
- per-message/per-subscription authorization and tenant isolation;
- behavior after token expiry, logout and revocation;
- message size/rate limits, malformed message handling and reconnection storms;
- no sensitive channel names, payloads or errors leak to another context.

Use local fixture messages and bounded counts. Connect results to API Top 10:2023 and WSTG client/API rows.

## Error and exceptional-state browser probes

Trigger safe 404s, invalid input, aborted navigation, offline/downstream failure, duplicate submission, expired session, timeout and refresh/retry transitions. Inspect response/body/DOM/console/network and authoritative state.

Check for stack traces, source paths, SQL/framework errors, stale privileged UI, duplicate side effects, inconsistent optimistic state, endless retries, leaked partial data and failure to clear secrets. A generic error page passes only when the underlying state is consistent and protected logs retain useful diagnostics.

## Evidence and report integration

Every validated browser finding includes:

- `surface: app_target_browser_exposure` plus the deeper owning surface;
- local prerequisite and identity/role context;
- sanitized route/method, source handler when known, safe steps and observed result;
- screenshot/trace/log path only when it contains no secret or personal data;
- OWASP/WSTG/ASVS/API mappings resolved from current official sources;
- correction and re-probe evidence when changed.

Update both report axes:

- folder/module coverage from correlated handlers, components, configuration and tests;
- URL/route/method coverage from browser/network inventory, including role context and state.

## Completion gate

Browser coverage is complete in the declared scope only when:

1. prerequisite checks passed and versions are recorded;
2. anonymous and every available authorized role/context were isolated;
3. discovered routes and network operations are reconciled with source/API inventory;
4. applicable response, session/CSRF, authorization, client injection, storage, framing, realtime and exceptional-state probes have evidence;
5. inaccessible flows are `not_tested`, not omitted;
6. candidates are validated or explicitly pending validation;
7. corrected findings were re-probed in a fresh context.

## Official references

- https://owasp.org/www-project-web-security-testing-guide/
- https://owasp.org/www-project-application-security-verification-standard/
- https://playwright.dev/docs/api/class-browsercontext
