# Penetration-Test Scope and Engagement Guidelines This document is the canonical scope and ground-rules contract for any third-party penetration testing of the platform. It is referenced from [`SECURITY.md`](../../SECURITY.md), from [`vulnerability-disclosure.md`](./vulnerability-disclosure.md) and from the public `.well-known/security.txt`. Engagement-specific addenda (test credentials, NDA, statement-of-work) are provided privately by the operator. > **Status:** template — pre-defined scope. The operator selects a test window per engagement and signs the addendum separately. ## 1. Engagement contact and escalation | Role | Contact | Channel | | --- | --- | --- | | Primary security contact | `security@` | Email + PGP (see `.well-known/pgp-key.txt`) | | Data-protection officer (DPO) | `dpo@` | Email | | Out-of-hours escalation | `oncall@` | Operator-side paging | | Coordinated-disclosure liaison | `security@` | Email | All initial engagement traffic must go through `security@`; secondary channels are only used after the operator confirms. ## 2. In-scope assets The following systems are in scope for authorised testing. Replace `` with the agreed environment (`staging` or `pentest`). ### Web and API surface - `https://app..` — primary tenant web SSR - `https://admin..` — admin UI (host-aware variant) - `https://api..` — versioned `/v1/*` HTTP surface - `https://realtime..` — Hocuspocus collaboration WebSocket - `https://app../.well-known/security.txt` - `https://app../embed/forms/*` — form-widget embed surface - `https://app../api/leads/capture` — marketing lead-capture endpoint - `https://cdn../widget.js` and `marketing.js` — public widget bootstraps ### Tenant data plane Test tenants are provisioned per engagement (see [§4](#4-test-tenants-and-credentials)). Cross-tenant assertions must be exercised against operator-provided tenant pairs only. ### Background processing surface Worker-internal HTTP probes (`/healthz`, `/readyz` on per-group ports `9101–9105`) are **out of public scope** but may be exercised through documented admin endpoints exposed by the API. ### Documentation surface The repository's documentation set (`docs/security/*`, `docs/operations/*`) is in scope for review only — modifications must come via the responsible-disclosure channel. ## 3. Out-of-scope assets and activities The following are explicitly **out of scope** and any testing against them voids the safe-harbor commitment in [`vulnerability-disclosure.md`](./vulnerability-disclosure.md): ### Out-of-scope assets - Production tenants (`app.` without `` prefix) - Third-party provider consoles or APIs: - Stripe (live + test), Mailjet, OpenAI / Anthropic / Scaleway / Aleph-Alpha, Bunny CDN, Cloudflare, GitHub, Sentry SaaS (if used), MeiliSearch Cloud, Qdrant Cloud - Marketing site (`` and `www.` static pages) — separate engagement - Operator infrastructure outside the documented endpoints (DNS registrar, Coolify console, Postgres direct port, Redis direct port) - Customer-configured outbound webhook destinations - Customer-configured SSO IdPs ### Out-of-scope activities - **Destructive testing** — no actions that permanently delete data, corrupt backups, or DOS production / staging - **Real-user data exfiltration** — no harvest of production-grade PII. If a test inadvertently surfaces production data, stop, do not store, do not share, and notify `security@` immediately - **Stripe live-mode replay** — webhook replay must use Stripe CLI in test-mode against the dedicated `pentest` tenant; live-mode payloads are out of scope - **Mail-bomb / SMS-bomb** — no testing that triggers more than 10 outbound notifications per minute to non-operator-provided addresses - **Social engineering** of operator staff, customers, or third-party support — out of scope - **Physical access** — out of scope - **Denial-of-service / load testing** — disallowed without operator-signed addendum and a maintenance window - **Modification of test artifacts on a shared environment** — each engagement gets its own tenant - **Brute-force at scale** — limited bursts to demonstrate rate-limit behavior are allowed; sustained credential-stuffing campaigns are not - **Testing of public CDN edge caches** — must not include cache-poisoning against shared edges ## 4. Test tenants and credentials For each engagement the operator provisions: - One dedicated `pentest-` tenant on `` - Two non-admin users (Owner + Member) with synthetic email addresses (`pentest+owner-@`, `pentest+member-@`) - One service API key with `pentest-readonly` scope - One service API key with `pentest-readwrite` scope (scoped to the `pentest-` tenant only) Credentials are delivered via PGP-encrypted email or 1Password share, single-use, with a 30-day TTL aligned to the engagement window. For cross-tenant isolation tests, the operator additionally provisions a **paired** `pentest-isolation-` tenant. Both tenants share a synthetic data shape but must remain logically isolated; demonstrating a cross-tenant read or write between this pair is an in-scope finding. ## 5. Test windows - Default window: **two consecutive weeks** within an operator-confirmed slot - Allowed hours: Monday–Friday 09:00–18:00 CET (Europe/Berlin). Off-hours testing only with written operator confirmation - Maintenance freeze: no testing during operator-announced freezes (e.g. release nights, regulatory audit windows) - Live-update channel: `security@` with a daily status email; an emergency stop is honoured within one business hour ## 6. Expected test classes The engagement is expected to exercise (non-exhaustive): - **OWASP Top 10** (web) - **OWASP API Security Top 10** - **OWASP ASVS Level 2** — control coverage check - **Tenant isolation** — cross-tenant reads / writes across all data planes (DB, cache, search, vector store, storage, mail, realtime) - **AuthN / AuthZ** — session, JWT, API-key, magic-link, TOTP, recovery codes, magic-link invitation, SSO (when enabled) - **IDOR / BOLA** across every `/v1/*` resource - **Privilege escalation** — role, permission, plugin capability (where shipped) - **CSRF / clickjacking / CORS** - **CSP regressions** once enforcement lands - **Webhook surface** — inbound signature forgery, replay, SSRF on outbound delivery - **AI surface** — prompt injection (covered for tool-call surfaces), cost exhaustion, prompt-data leakage in logs - **Form-widget + lead-capture** — origin spoof, embed tamper, honeypot bypass, Turnstile bypass - **Realtime (Hocuspocus)** — anonymous connect, cross-document read, malformed Yjs payload - **Storage** — presigned-URL forgery, key-prefix bypass, malicious upload (AV layers 1 + 2) - **Backup / snapshot CLI** — restore-in-production guardrail, PII-profile leakage Items explicitly out of scope from the test classes: - LLM jailbreaks against generic chat surfaces — not in scope (we accept that prompt-injection mitigation is best-effort for free-form chat). Tool-call surfaces remain in scope. - Dependency-vulnerability scanning against shipped SBOM — covered separately via SBOM workflow (see [`sbom.md`](./sbom.md)) ## 7. Reporting format Findings are reported in Markdown, one file per finding, named `YYYY-MM-DD-.md`. Each file contains: 1. **Title** — concise (≤ 80 chars) 2. **Severity** — CVSS 3.1 vector + score, plus the operator severity bucket (P0–P3, see [`incident-response.md`](./incident-response.md)) 3. **Affected surface** — generic route class, endpoint shape, worker job, or documentation page. **Never** a customer-specific URL 4. **Reproduction** — minimal steps using fixtures / synthetic values only. PoC must be deterministic against the pentest tenants 5. **Observed impact** — what happened 6. **Expected behavior** — what should have happened 7. **Remediation suggestion** — optional; the operator's engineers own remediation design 8. **Evidence** — request IDs, job IDs, screenshots redacted of customer / tenant / credential material 9. **References** — CWE, OWASP, related findings All findings are delivered via PGP-encrypted email to `security@` or via the operator's coordinated-disclosure portal once enabled. ## 8. Disclosure timeline - **Acknowledgement**: ≤ 48 hours from receipt - **Triage** (severity assigned, owning team identified): ≤ 5 business days - **Fix window**: - **P0 / Critical**: emergency patch ≤ 7 calendar days - **P1 / High**: ≤ 30 calendar days - **P2 / Medium**: ≤ 60 calendar days - **P3 / Low**: ≤ 90 calendar days - **Public disclosure**: 90 days after report, or earlier on mutual agreement, or later if the operator and reporter agree that a longer fix window is justified by complexity. The operator commits to publishing a security advisory at disclosure time. - **Bug-bounty** (when active): see [`bug-bounty.md`](./bug-bounty.md). Until the program is active, findings remain eligible for the coordinated-disclosure hall of fame. ## 9. Safe harbor Researchers who: - limit their activity to the in-scope assets, - avoid the out-of-scope activities, - respect the operator's stop request, - report findings exclusively through `security@` until disclosure is mutually agreed, - do not modify, destroy, or exfiltrate data beyond the minimum required to demonstrate impact are granted safe harbor: the operator will not pursue legal action, will request that other parties also stand down, and will publicly credit the researcher on request. ## 10. Pre-engagement checklist (operator) - [ ] Engagement addendum signed (scope, dates, contact, billing) - [ ] Pentest tenants provisioned (primary + isolation-pair) - [ ] Synthetic test data seeded - [ ] Test credentials delivered via PGP / 1Password share with TTL - [ ] Sentry sampling raised to 100 % for `pentest:*` tags - [ ] Operator on-call paged into the engagement Slack channel - [ ] Maintenance freeze calendar confirmed clear - [ ] PGP public key on `.well-known/pgp-key.txt` not within 30 days of expiry - [ ] Internal IR-team briefed (severity classification, escalation path) ## 11. Pre-engagement checklist (researcher) - [ ] PGP key shared and verified - [ ] Engagement addendum signed - [ ] Test credentials received and rotated into researcher's password manager (single-use, no sharing) - [ ] In-scope / out-of-scope confirmed against §2 / §3 - [ ] Reporting format confirmed against §7 - [ ] Operator stop-channel acknowledged (`security@`)