# Penetration Test Scope — Corvin EU_PRODUCTION

> **Audience:** External penetration-test firm engaged by the
> operator. This document defines the scope, assumptions, and
> success criteria for an annual pentest of an Corvin deployment
> running the EU_PRODUCTION preset. The operator customises this
> file (target host names, IP ranges, contact details) and hands it
> to the firm before the engagement.

---

## 1. Engagement metadata

- **Target deployment:** _____________________________________
- **Target host(s) / IP range:** _____________________________
- **In-scope time window:** __________________________________
- **Operator contact (technical):** ___________________________
- **Operator contact (legal / DSB):** _________________________
- **Authorisation letter signed:** ☐ yes ☐ no

---

## 2. Scope

### 2.1 In-scope systems

- Corvin bridge daemon(s) (Telegram, Discord, WhatsApp, Signal — whichever the operator runs).
- Corvin forge MCP server (`operator/forge/forge/mcp_server.py`).
- Local Ollama daemon (used by HermesEngine and optionally OpenCode).
- The L16 hash chain (`audit.jsonl`) on the target host.
- The L37 sealed audit segments + retention pipeline.
- The L36 `corvin-erasure` orchestrator.
- Console UI (`core/console/`).
- Compliance reports plugin (`core/compliance/corvin_compliance_reports`).

- Tenant configuration files under `<corvin_home>/tenants/<tid>/global/`.

### 2.2 Out-of-scope

- Any Anthropic / OpenAI / Google API endpoint (these are explicitly
  blocked under EU_PRODUCTION; pentesting them is wasted effort).
- Third-party messaging platforms (Telegram BotAPI, Discord API,
  WhatsApp Cloud API) — out of operator control; we only test our
  use of them.
- Personal devices of end users.
- Physical security of the host.
- Social engineering (separate engagement).

---

## 3. Threat model

### 3.1 Threat actors

- **External attacker** with no Corvin credentials.
- **Authenticated user** (admin / member / observer roles).
- **Compromised bridge daemon** (e.g. via Telegram-token theft).
- **Insider** with shell access to the bridge host.
- **Compromised Ollama worker** (HermesEngine or OpenCode via Ollama — e.g. via malicious model or prompt-injection from Ollama output).

### 3.2 Critical assets

- **Audit chain integrity** — must remain tamper-evident under
  every threat actor.
- **Pseudonym-to-identity mapping** — must not leak to anyone
  outside the operator-controlled identity store.
- **EU egress lockdown** — must not be bypassable from any
  attack path.
- **Forge sandbox** — must not be escapable into the host filesystem.

---

## 4. Test cases (mandatory)

### 4.1 Egress lockdown (L35)

- [ ] Verify `default_action: deny` blocks all unlisted hosts.
- [ ] Attempt to spawn an engine that targets `api.anthropic.com` —
  verify `egress.blocked` (CRITICAL) audit event lands.
- [ ] Attempt DNS resolution of forbidden hosts from inside the
  bridge process — verify perimeter firewall blocks.
- [ ] Attempt to add `api.anthropic.com` to `allowed_hosts` via
  config edit — verify L35 loader raises ValueError.

### 4.2 Data classification (L34)

- [ ] Submit a prompt containing AWS key shape — verify it is
  classified SECRET and refused against non-local engines.
- [ ] Submit a prompt with email PII — verify CONFIDENTIAL
  classification.
- [ ] Verify `data_flow.blocked` (CRITICAL) is emitted on every
  refusal with metadata only (no prompt text in audit details).
- [ ] Attempt to register an engine with `locality=local` for
  `claude_code` (override) — verify config-load fails consistency
  check.

### 4.3 Audit chain integrity (L16 + L37)

- [ ] Attempt to edit a single record in live `audit.jsonl` —
  verify `voice-audit verify` detects + emits CRITICAL.
- [ ] Attempt to chmod a sealed segment to 644 — verify the
  retention sweep doesn't fail on permission changes.
- [ ] Verify chain link across rotation boundary
  (`audit.rotation_link.prev_hash == sealed[i-1].last_hash`).
- [ ] Attempt to decrypt a sealed segment without the recipient
  key — verify failure + `audit.unseal_requested` is NOT emitted
  (only on actual decrypt attempt).
- [ ] Test the `audit.unseal_requested` WARNING event lands BEFORE
  any decryption, as the audit-of-the-audit invariant requires.

### 4.4 Forge sandbox (L6 + L10)

- [ ] Attempt path traversal via forge tool argument.
- [ ] Attempt to read `<corvin_home>/secrets.json` from inside
  a forged tool — verify path-gate denies + emits
  `path_gate.denied`.
- [ ] Attempt to disable the path-gate hook — verify it cannot be
  removed from `hooks/hooks.json` without leaving an audit trail.
- [ ] Attempt to spawn a forge tool with `network: allow` from a
  persona that should be restricted — verify denial.

### 4.5 Consent gate (L16 Phase 4)

- [ ] Verify deny-by-default — sending a message without prior
  consent fails closed.
- [ ] Verify consent TTL is enforced.
- [ ] Attempt owner-grants-consent-for-another-user — verify
  refusal (identity binding is load-bearing).
- [ ] Re-validation at consume — modify consent state between
  grant and consume, verify second check fires.

### 4.6 Erasure orchestrator (L36)

- [ ] Run `corvin-erasure user_42` — verify all five layer events
  fire (`requested` → 4× per-layer → `completed`).
- [ ] Submit a raw email as subject_id — verify shape regex
  rejects with `ValueError`.
- [ ] Submit a path-traversal subject_id (`../etc/passwd`) — verify
  rejection.
- [ ] Trigger a deliberate handler failure (e.g. DB-locked) —
  verify `erasure.failed` (CRITICAL) and `overall_status=PARTIAL`.
- [ ] Verify trail file at `<tenant>/global/erasure/<id>.json`
  has mode 0600.
- [ ] Attempt cross-tenant erasure — verify refusal.

### 4.7 Engine identity (compliance-zone)

- [ ] Verify `allowed_engines` is enforced — attempt to set engine
  preference to `claude_code` under EU_PRODUCTION → refused.
- [ ] Engine-canary catches drift from allow-list.
- [ ] Force-set `CORVIN_DEFAULT_ENGINE=claude_code` in env —
  verify L34 + L35 still refuse at spawn-site.

### 4.8 Identity mapping (M4 follow-up)

- [ ] Read `<operator-chosen-identity-store>` — verify operator
  has documented + secured this store.
- [ ] After `corvin-erasure`, verify the identity-mapping handler
  actually deleted the mapping (not just audited).

### 4.9 Voice transcripts (L23)

- [ ] Send a voice note — verify `voice.transcribed` audit event
  contains METADATA ONLY (no transcript text).
- [ ] Verify regression test `test_audit_event_only_carries_metadata`
  passes on the deployment build.

### 4.10 Disclosure (L19, EU AI Act Art. 50)

- [ ] First message from a new uid triggers disclosure card.
- [ ] Second message from same uid does not repeat the card.
- [ ] `/leave` cleanly removes the uid from the chat.

---

## 5. Reporting

### 5.1 Severity grading (CVSS 3.1 base score)

- **Critical:** ≥ 9.0
- **High:** 7.0 – 8.9
- **Medium:** 4.0 – 6.9
- **Low:** 0.1 – 3.9

### 5.2 Findings format

Each finding includes:

1. CVSS 3.1 vector + base score.
2. Affected component (layer + file).
3. Reproduction steps.
4. Proof-of-concept (sanitised; no real PII).
5. Recommended remediation.
6. Reference to the relevant ADR / ref doc.

### 5.3 Go-live criteria

- **Zero Critical** findings outstanding.
- **Zero High** findings outstanding (or each must have an
  operator-signed risk-acceptance with a documented mitigation
  schedule).
- Medium / Low findings logged for the next release cycle.

---

## 6. Rules of engagement

- Tester uses dedicated test accounts (operator-provided).
- No data exfiltration outside the test harness.
- No DDoS or volumetric attacks on the production bridge.
- All test prompts that exercise PII detection use synthetic data
  (no real customer information).
- Test traffic identifiable via dedicated `subject_id` prefix
  (e.g. `pentest_*`).
- Operator receives daily check-ins during the engagement.
- Final report delivered within 14 days of engagement end.

---

## 7. References

- Overall EU compliance design — see Corvin-ADR repo.
- L34 — data classification.
- L35 — egress lockdown.
- L37 — audit-at-rest.
- L36 — erasure orchestrator.
- `docs/compliance/DSB-CHECKLIST.md` — DPO-side checklist.
- `docs/compliance/DPIA-TEMPLATE.md` — DPIA template.
