188 lines
7.9 KiB
Markdown
188 lines
7.9 KiB
Markdown
|
|
# Pentest send package — v2026 engagement
|
||
|
|
|
||
|
|
> Operational checklist for handing off the v1.0.9 pre-launch pentest
|
||
|
|
> brief to the external team. Companion to `docs/PENTEST_SCOPE_2026.md`
|
||
|
|
> (the technical scope) — this doc is purely "what you send, in what
|
||
|
|
> order, via which channel."
|
||
|
|
|
||
|
|
The scope doc is technical and reusable across engagements. This file
|
||
|
|
is the per-engagement "send package" that wraps it: the email template,
|
||
|
|
the credentials-delivery plan, the IP allow-list step, and the kick-off
|
||
|
|
checklist.
|
||
|
|
|
||
|
|
## The 5-step send sequence
|
||
|
|
|
||
|
|
Run these in order. Each step has a check (✓) the operator ticks before
|
||
|
|
moving to the next — out-of-order steps cause the engagement to stall.
|
||
|
|
|
||
|
|
### Step 1 — counter-sign the NDA + authorisation letter
|
||
|
|
|
||
|
|
- [ ] NDA template signed by the pentester firm and counter-signed by us.
|
||
|
|
- [ ] Authorisation-to-test letter signed by Veza tech lead (limits the
|
||
|
|
scope to what's in `PENTEST_SCOPE_2026.md` §"In-scope assets" — the
|
||
|
|
letter MUST list the staging URL explicitly so a reviewer can map
|
||
|
|
pentester traffic to authorised activity).
|
||
|
|
- [ ] Both PDFs uploaded to the shared 1Password vault (entry name :
|
||
|
|
`pentest-2026-legal`). Do **not** email PDFs.
|
||
|
|
|
||
|
|
### Step 2 — provision pentester credentials
|
||
|
|
|
||
|
|
- [ ] Run `bash scripts/pentest/seed-test-accounts.sh staging` (creates
|
||
|
|
the 3 accounts from `PENTEST_SCOPE_2026.md` §"Authentication
|
||
|
|
context", outputs random passwords).
|
||
|
|
- [ ] Output passwords land in three 1Password entries :
|
||
|
|
`pentest-2026-listener`, `pentest-2026-creator`, `pentest-2026-admin`.
|
||
|
|
Each entry's "Notes" field includes the role and the MFA bypass
|
||
|
|
token if applicable.
|
||
|
|
- [ ] Share each entry **read-only** with the pentester's 1Password
|
||
|
|
account using the firm's billing email. Do **not** put passwords
|
||
|
|
in chat, email, or shell history.
|
||
|
|
- [ ] Set entry expiration to engagement-end + 7 days (so cleanup is
|
||
|
|
automatic if the team forgets to revoke).
|
||
|
|
|
||
|
|
### Step 3 — allow-list the pentester's IP
|
||
|
|
|
||
|
|
The Forgejo source-code mirror at `https://10.0.20.105:3000/senke/veza`
|
||
|
|
is grey-box read-only access. The pentester needs their static
|
||
|
|
egress IP allow-listed before they can `git clone`.
|
||
|
|
|
||
|
|
- [ ] Pentester sends their static egress IP (PGP-signed mail, or
|
||
|
|
1Password Notes field).
|
||
|
|
- [ ] SSH to `srv-102v` (Forgejo container) and add the IP to
|
||
|
|
`/etc/forgejo/allowlist.conf`.
|
||
|
|
- [ ] `systemctl reload forgejo`.
|
||
|
|
- [ ] Verify : `curl -I https://10.0.20.105:3000/senke/veza` from the
|
||
|
|
pentester IP returns 200 ; from any other IP, 403.
|
||
|
|
|
||
|
|
(A future iteration could turn this into an Ansible playbook
|
||
|
|
`infra/ansible/playbooks/pentest_allowlist_ip.yml`. For now the manual
|
||
|
|
SSH path is fine — this happens once per engagement.)
|
||
|
|
|
||
|
|
### Step 4 — send the kick-off email
|
||
|
|
|
||
|
|
Use the template below. Replace the placeholders inside `<…>`. Send
|
||
|
|
PGP-encrypted (the pentester's key is in their security.txt) to
|
||
|
|
**both** their lead pentester and their project manager so the chain
|
||
|
|
of responsibility is recorded.
|
||
|
|
|
||
|
|
```text
|
||
|
|
Subject : [PENTEST] Veza v1.0.9 pre-launch engagement — kick-off
|
||
|
|
|
||
|
|
Hi <lead pentester first name>,
|
||
|
|
|
||
|
|
Per the signed scope letter dated <YYYY-MM-DD>, the Veza v1.0.9
|
||
|
|
pre-launch pentest engagement starts on <YYYY-MM-DD>. The brief is
|
||
|
|
attached as PENTEST_SCOPE_2026.md (see also the rendered HTML at
|
||
|
|
https://staging.veza.fr/legal/pentest-scope-2026.html).
|
||
|
|
|
||
|
|
Quick links :
|
||
|
|
|
||
|
|
• Staging URL : https://staging.veza.fr
|
||
|
|
• Source code : https://10.0.20.105:3000/senke/veza
|
||
|
|
(grey-box, read-only ; your egress IP <PENTESTER_IP>
|
||
|
|
has been allow-listed as of <YYYY-MM-DD HH:MM UTC>.)
|
||
|
|
• Status page : https://status.veza.fr (we'll lower the alert
|
||
|
|
threshold during your engagement so the SOC isn't
|
||
|
|
paged on every benign 401).
|
||
|
|
• Test accounts: shared with your firm's 1Password — entries
|
||
|
|
pentest-2026-{listener,creator,admin}. Passwords
|
||
|
|
expire <engagement_end + 7d>.
|
||
|
|
|
||
|
|
Engagement window :
|
||
|
|
|
||
|
|
• Start : <YYYY-MM-DD>
|
||
|
|
• End : <YYYY-MM-DD> (~10 business days)
|
||
|
|
• Re-test: 1 round, after our team's fix pass (typically 2 weeks
|
||
|
|
after the initial report)
|
||
|
|
|
||
|
|
Communications :
|
||
|
|
|
||
|
|
• Async : security@veza.fr (PGP fingerprint at
|
||
|
|
https://veza.fr/.well-known/security.txt)
|
||
|
|
• Weekly sync : <weekday HH:MM TZ>, video link in the calendar invite
|
||
|
|
• Critical findings : phone the on-call number in the contract
|
||
|
|
(HIGH severity = phone, not email)
|
||
|
|
|
||
|
|
Expected deliverables :
|
||
|
|
|
||
|
|
• Initial findings report (markdown or PDF) at engagement end
|
||
|
|
• Re-test report after our fix pass
|
||
|
|
• Optional : exec-level summary slide deck
|
||
|
|
|
||
|
|
Reach out if anything in PENTEST_SCOPE_2026.md is unclear before
|
||
|
|
day 1. Otherwise — good hunting.
|
||
|
|
|
||
|
|
Best,
|
||
|
|
<Tech lead name>
|
||
|
|
Veza
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] Email PGP-signed and sent.
|
||
|
|
- [ ] Calendar invite sent for the weekly sync.
|
||
|
|
- [ ] Slack/Signal channel created for HIGH-severity escalation
|
||
|
|
(channel naming : `#pentest-2026-veza`).
|
||
|
|
|
||
|
|
### Step 5 — lower the SOC alerting threshold
|
||
|
|
|
||
|
|
During the engagement, automated scanners and authentication
|
||
|
|
brute-force attempts WILL fire alerts. Tune them down so the on-call
|
||
|
|
isn't paged on every legitimate pentester action.
|
||
|
|
|
||
|
|
- [ ] In `config/prometheus/alert_rules.yml` → `HighErrorRate`,
|
||
|
|
`HighLatencyP99` : add a `for: 30m` override OR mute via
|
||
|
|
Alertmanager silence (recommended: silence rather than edit
|
||
|
|
rules so the change auto-expires at engagement end).
|
||
|
|
- [ ] Silence URL : `https://prometheus.veza.fr/alertmanager/#/silences/new`
|
||
|
|
→ matchers: `severity=warning`, comment: `pentest-2026 active`,
|
||
|
|
duration: `engagement_end + 24h`.
|
||
|
|
- [ ] Subscribe the engagement Slack channel to the silence's
|
||
|
|
auto-removal so the SOC knows when the heightened alerting
|
||
|
|
resumes.
|
||
|
|
|
||
|
|
## Reception checklist (after pentester confirms receipt)
|
||
|
|
|
||
|
|
- [ ] Pentester replied to the kick-off email within 1 business day.
|
||
|
|
- [ ] Pentester confirmed they can `git clone` the source repo.
|
||
|
|
- [ ] Pentester confirmed they can log in as each of the 3 test
|
||
|
|
accounts.
|
||
|
|
- [ ] Pentester confirmed the staging URL responds (`/api/v1/health`
|
||
|
|
returns 200).
|
||
|
|
- [ ] First findings — even informational — start landing in the
|
||
|
|
shared report by end of engagement day 3 (a complete silence
|
||
|
|
until the final report is a process smell).
|
||
|
|
|
||
|
|
If any reception checklist item fails after 24h, the engagement
|
||
|
|
hasn't really started. Phone the firm's PM, don't email.
|
||
|
|
|
||
|
|
## Post-engagement housekeeping
|
||
|
|
|
||
|
|
- [ ] Findings report received → import into the issue tracker as
|
||
|
|
separate tickets, severity preserved, attribution
|
||
|
|
`external-pentest-2026`.
|
||
|
|
- [ ] Fix pass scheduled and timeboxed (HIGH within 1 week, MEDIUM
|
||
|
|
within 4 weeks, LOW best-effort).
|
||
|
|
- [ ] Re-test scheduled 2 weeks after fix-pass start.
|
||
|
|
- [ ] Re-test report received → update the ticket statuses ; any
|
||
|
|
remaining unresolved finding above LOW blocks v2.0.0-public.
|
||
|
|
- [ ] Test accounts' passwords manually rotated **the day the
|
||
|
|
engagement ends** (don't wait for 1Password's auto-expiry).
|
||
|
|
- [ ] Pentester IP removed from Forgejo allow-list.
|
||
|
|
- [ ] Alertmanager silence removed (should auto-remove, but verify).
|
||
|
|
- [ ] Engagement folder zipped and stored at
|
||
|
|
`docs/archive/pentest-2026/` (kept 5 years for audit trail).
|
||
|
|
- [ ] Public summary blog post drafted (no findings details, just the
|
||
|
|
"we did this, here's what we learned" framing). Reviewed by
|
||
|
|
legal before publish.
|
||
|
|
|
||
|
|
## Linked artefacts
|
||
|
|
|
||
|
|
- `docs/PENTEST_SCOPE_2026.md` — the technical scope (what's testable)
|
||
|
|
- `docs/SECURITY_PRELAUNCH_AUDIT.md` — internal Day 21 audit (what we
|
||
|
|
already cleared)
|
||
|
|
- `docs/archive/PENTEST_REPORT_VEZA_v0.12.6.md` — last engagement's
|
||
|
|
report, format reference for what to expect back
|
||
|
|
- `scripts/pentest/seed-test-accounts.sh` — credential provisioning
|
||
|
|
helper (creates the 3 staging accounts referenced in the scope)
|
||
|
|
- `docs/GO_NO_GO_CHECKLIST_v2.0.0_PUBLIC.md` — the row this engagement
|
||
|
|
unblocks
|