diff --git a/.gitignore b/.gitignore deleted file mode 100644 index bf80165..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.repo-manager/ diff --git a/.repo-classification.yaml b/.repo-classification.yaml deleted file mode 100644 index 75c9590..0000000 --- a/.repo-classification.yaml +++ /dev/null @@ -1,29 +0,0 @@ -repo_classification: - standard: Repo Classification Standard - version: "1.0" - classified_at: "2026-08-21" - classified_by: codex - category: tooling - domain: infotech - secondary_domains: [] - capability_tags: - - access-control - - evidence - - traceability - - compliance - - risk - - audit - - observability - - operations - business_stake: - - technology - - operations - - legal - - automation - business_mechanics: - - control - - operation - - adaptation - notes: >- - NetKingdom offensive-security tooling that produces independently operated, - authorization-bound adversarial evidence and routes findings to risk-nexus. diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index b7f2a4a..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,123 +0,0 @@ -# whitehat-security — Agent instructions - -## Repository identity - -**Purpose:** Authorization-bound offensive-security tooling that produces -adversarial evidence about security claims and routes findings to the -responsible party. - -**Owner:** NetKingdom -**Domain:** infotech -**Repo slug:** `whitehat-security` -**Topic ID:** `cee7bedf-2b48-46ef-8601-006474f2ad7a` -**Workplan prefix:** `WHITEHAT-WP-` - -## Orient before working - -1. Read `INTENT.md` and `SCOPE.md`. -2. Read `docs/rules-of-engagement.md` before designing or executing probes. -3. Read `.custodian-brief.md` when present and scan `workplans/`. -4. Check the repository inbox: - - `curl -s "http://127.0.0.1:8000/messages/?to_agent=whitehat-security&unread_only=true"` - -5. Check the worktree before editing; preserve unrelated user changes. - -## Non-negotiable safety boundary - -- The rules of engagement are pending personal operator approval. Until they - are approved, perform only documentation work and non-networked fixture - design. Send no packets to a target. -- Even after approval, no live run starts without a dated engagement record - naming authorization, target owner, exact scope, window, technique, - credentials, rate/concurrency ceiling, abort contact and finding destination. -- Never broaden scope after discovery. Record an adjacent system and stop. -- Never collect real tenant row values or credentials as evidence. -- Never use superuser, owner or `BYPASSRLS` privilege for convenience. -- Never perform destructive, persistence, lateral-movement or denial-of-service - activity outside an explicitly authorized technique and window. -- A pass means only that the attempted attacks did not work. Every probe must - first fail against a known-bad fixture. -- This repository finds and reports; it does not fix targets or assign severity. - -## State Hub integration - -State Hub is the coordination index; repository files remain authoritative. - -| Context | URL | -| --- | --- | -| Local workstation | `http://127.0.0.1:8000` | -| Remote tunnel | `http://127.0.0.1:18000` | -| Optional edge relay | `http://127.0.0.1:18080` | - -Use `/state/health` for health checks. After changing workplan files, run: - -`statehub fix-consistency` - -If the command reports C-06/C-11 because this host is not the identifier -registrar, do not set `STATEHUB_REGISTRAR` manually. Commit and push the -file-backed work, then use the scoped fallback once: - -`uv run --project ~/repo-manager rmgr registrar-reconcile --path . --confirm-primary --push` - -At session close, ensure file task statuses reflect reality and record -significant progress in State Hub. Actionable residuals from a finished -workplan must become live work records rather than remaining only in prose. - -## Credential routing - -Before requesting credentials, API keys, SSH access or database passwords: - -`warden route find "" --json` - -`ops-warden` issues SSH certificates only. Other secret material belongs to the -custody route returned by `warden`. Never put credentials in Git, State Hub, -workplans, logs, evidence or chat. - -## Workplan convention - -Workplans live at `workplans/WHITEHAT-WP-NNNN-.md`. Finished plans may -move to -`workplans/archived/YYMMDD-WHITEHAT-WP-NNNN-.md` without changing their -frontmatter ID. - -Required frontmatter: - -```yaml ---- -id: WHITEHAT-WP-NNNN -type: workplan -title: "..." -domain: infotech -repo: whitehat-security -status: proposed | ready | active | blocked | backlog | finished | archived -owner: ... -topic_slug: ... -created: "YYYY-MM-DD" -updated: "YYYY-MM-DD" -state_hub_workstream_id: "" # written by reconciliation; do not edit ---- -``` - -Each task uses one machine-readable block: - -````markdown -```task -id: WHITEHAT-WP-NNNN-T01 -status: wait | todo | progress | done | cancel -priority: high | medium | low -state_hub_task_id: "" # written by reconciliation; do not edit -``` -```` - -Use `proposed` for drafts, `ready` after review, `active` once work has begun, -and `finished` only when all required work is complete or residuals have live -owners. Task progression is `todo` → `progress` → `done`; `wait` is for work -that cannot currently proceed and `cancel` is terminal. - -Small, low-risk work completed directly may use -`workplans/ADHOC-YYYY-MM-DD.md`. Anything requiring analysis, approval, -dependencies or multiple phases needs a normal workplan. - - - diff --git a/INTENT.md b/INTENT.md deleted file mode 100644 index b6b281a..0000000 --- a/INTENT.md +++ /dev/null @@ -1,193 +0,0 @@ -# INTENT — whitehat-security - -## Why this repo exists - -`whitehat-security` is **NetKingdom's offensive security facility**. It attacks -IT infrastructure and surfaces we choose to point it at — our own estate among -them — and reports what it finds to whoever is responsible for fixing it. - -The discipline is offensive because offence is how you find out. A control is -believed until someone tries it. Everything else in the estate's security work -describes what should be true; this repo establishes what is. - -It was seeded to close a specific gap, which remains its first job. NetKingdom's *Tenancy Posture* standard -splits evidence into two kinds: **mechanical** — a structural assertion a -machine can make, which belongs in each repo's own CI — and **adversarial** — -a semantic claim that requires setting up hostile conditions and observing what -happens. Every repo can produce the first. **No repo can honestly produce the -second about itself**, and the framework's most severe open question has been -sitting unowned for exactly that reason: who verifies that a consumer's tenant -boundary actually holds. - -Two repos were asked and both correctly declined, on the grounds that a service -which grows fleet responsibilities because it happened to be nearby is how -boundaries erode. They were right. The work needed a home of its own. - -## Owner: NetKingdom - -`whitehat-security` is a NetKingdom capability, alongside the IAM Profile, -SSO/MFA and the canonical security architecture. Offensive security is security -work, and it belongs with the repo that owns security. - -**Separation of concerns still applies, one level down.** A repo testing its own -boundary grades its own homework. `rapp-postgres` wrote fifteen adversarial -probes against its own isolation model and found four real defects in its own -provisioning SQL — good work, and still the author checking their own work. The -probes most worth having are the ones an author would not think to write, -because the assumption that produced the defect produces the blind spot. So: - -- This facility does not take a repo's declared posture as true. It tests it. -- It does not decide how bad its own findings are. Severity and disclosure are - `risk-nexus`'s, which is `the-custodian`'s, not NetKingdom's. - -**One residual tension, recorded rather than argued away.** NetKingdom owns the -Tenancy Posture framework *and* this facility. When whitehat tests conformance -to that framework, NetKingdom is assessing NetKingdom. The mitigation is the -routing above: findings leave for `risk-nexus` under separate ownership rather -than being resolved inside NetKingdom. That is proportionate, not perfect, and -worth revisiting if conformance findings ever start getting quietly closed. - -## What it owns - -- **Adversarial evidence artifacts.** The tests that produce the evidence the - Tenancy Posture ladders require but no repo can self-certify: - cross-tenant read and write attempts (E2), row-level-security conformance - under attack (E3), per-tenant credential confinement (E4), - noisy-neighbour characterisation (P1/P2), erasure verification (R4). -- **The attacker model.** What an adversary is assumed to hold at each level — - a leaked runtime credential, SQL execution, a compromised process — written - down, so a probe can be judged against a threat rather than against taste. -- **Cadence.** How often each probe runs. This is not a scheduling detail: for - any control whose guarantee is *detection rather than prevention*, the - interval between runs **is** the exposure window. `rapp-postgres` ADR-0003 - says so explicitly and leaves the number to be set here. -- **Differential testing between tenant contexts.** Running the same request as - two tenants and comparing responses is the mechanically reproducible core of - cross-tenant testing, and it is this repo's principal technique. -- **Target selection and authorization.** Which infrastructure or surface the - facility is pointed at, and the authorization that permits it. See the - targeting rule below — this is the repo's most important control. -- **Rules of engagement.** What may be probed, where, with what credentials, - and what must never be done. An automated facility without this is - indistinguishable from the threat it models. -- **Findings delivery to the responsible party.** For our own estate that is - `risk-nexus`, which routes to the owning repo. For any other target it is - whoever is responsible for that infrastructure, on the terms agreed in the - engagement. - -## What it does not own - -- **Fixing anything.** A finding routes through `risk-nexus` to the repo that - owns the defect. A security facility that fixes things becomes a second - engineering team with no boundary and no reviewer. -- **Severity, disclosure and timing.** `risk-nexus`. This repo says what is - true; that repo says how much it matters and who hears about it. -- **Mechanical CI evidence.** Schema assertions, unit tests and provisioning - checks stay with the repo that owns the code. This repo does not take over - anyone's test suite. -- **Deciding what the security model should be.** NetKingdom's canon says what - good looks like. This repo says whether we have it. -- **Blocking delivery.** In build mode a finding is information. If that - changes it will be a recorded decision, not a habit that accretes. - -## The targeting rule - -The facility can be pointed at infrastructure we do not own. That is the point -of it, and it is also the single thing that could turn this repo from an asset -into a liability, so the rule is structural rather than cultural. - -**No target is probed without recorded authorization from whoever is -responsible for it. No exceptions.** - -- **Our own estate, build mode** — standing estate authorization is necessary - but not sufficient. Every live run still needs the dated engagement record, - target-owner acknowledgement and technique-specific scope required by the - rules of engagement. No live target is pre-authorized by this intent. -- **Our own estate, production** — a separate recorded authorization. Build-mode - standing consent does not carry across; the blast radius is different and so - is the decision. -- **Anything we do not own** — written authorization from the responsible party, - per engagement, recorded in this repo *before a packet is sent*. Scope, - window, permitted techniques, and named contacts on both sides. - -Three things that do **not** constitute authorization, written down because -each is a way teams talk themselves into it: a commercial relationship with the -target; the target being publicly reachable; and a belief that the owner "would -obviously be fine with it". Unauthorized probing may be unlawful regardless of -intent, and a white-hat facility that gets this wrong is simply an attacker -with better paperwork. - -**The authorization record is part of the finding.** A report that cannot name -the authorization it ran under is not a finding — it is an incident, and it -gets treated as one. - -**Scope creep during an engagement is prohibited.** A probe that discovers an -adjacent system stops at the boundary and reports what it saw. Following the -interesting thing is exactly how an authorized test becomes an unauthorized -one. - -## Honest limits on "automated" - -The word in the repo's description is *automated*, and it must not be oversold -— overclaiming is the failure this estate keeps catching in itself. - -External testing practice is consistent that the highest-impact cross-tenant -findings concentrate in access control, business logic and tenant isolation: -precisely the categories that need someone who understands what the data -*means* to recognise that a response is wrong. A response can be well-formed, -200, fast, and contain another tenant's rows. - -So: - -- **Automate the reproducible.** Structural conformance, differential responses - between tenant contexts, credential confinement, resource saturation. This is - most of the surface and it should run without anyone remembering to run it. -- **Flag the irreducible.** Where a finding requires semantic judgement, the - facility's job is to set up the conditions, capture the evidence, and mark it - for review with a date — not to return green. -- **A passing suite is not proof of isolation.** It is proof that the attacks - we thought of did not work. State it that way in every report, because the - gap between those two sentences is where breaches live. - -## The failure this repo must avoid - -**A probe that has only ever passed is not evidence.** `rapp-postgres` verified -its own drift check by deliberately breaking the thing it watched and -confirming the check failed. Every probe here inherits that obligation: it must -be shown to fail against a known-bad fixture before it is trusted against a -real system. - -The second failure is subtler. A probe that starts passing because it was -weakened is worse than a deleted probe, because it reports safety. Probe -changes are therefore reviewed as security changes, and a probe that begins -passing after a change to *itself* rather than to the system is treated as a -finding. - -## Relationship to the rest of the estate - -``` -whitehat-security → risk-nexus → policy-nexus - finds triages publishes - (severity, (permanent, - disclosure) addressable) -``` - -For our own estate it reads posture claims and canon from the repos that own -them, attacks the running systems those claims describe, and hands findings to -`risk-nexus`. For any other target, findings go to that infrastructure's -responsible party on the engagement's agreed terms; `risk-nexus` still records -that the engagement happened and what it means for us. - -It publishes nothing directly and fixes nothing, in either case. - -The first work is already specified and waiting: the E2 cross-tenant evidence -artifact, which is Tenancy Posture's highest-severity unowned gap, and the -noisy-neighbour characterisation, which the framework had to reword once -already because its first draft asserted something shared infrastructure cannot -provide. - -## What good looks like - -The estate knows which of its security claims have been tested, when, and by -what attacker model — and can tell the difference between a property that has -been verified and one that has merely never failed. diff --git a/README.md b/README.md index b863063..ac4e67a 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,3 @@ # whitehat-security -NetKingdom's offensive security facility. Automated white hat IT-security, -pen-testing and isolation-probing — pointed at infrastructure we choose, -including our own. - -The estate's **adversarial evidence facility**: it attacks our own systems, on -a schedule, to find out whether the security properties they claim are actually -true. - -It exists because a repo testing its own boundary grades its own homework. The -probes most worth having are the ones an author would not think to write. - -- **Independent in operation.** It does not take a declared posture as true. - NetKingdom owns both the security canon and this facility, so findings leave - through `risk-nexus` under separate ownership rather than being resolved here. -- **It finds; it does not fix.** Findings route to `risk-nexus`, which owns - severity and disclosure. The repo that owns the defect owns the repair. -- **A pass means the attacks we tried did not work** — not that the boundary - holds. Reports say so. - -- Intent: [`INTENT.md`](INTENT.md) -- Scope: [`SCOPE.md`](SCOPE.md) -- Workplans: [`workplans/`](workplans/) -- Rules of engagement (pending operator approval): - [`docs/rules-of-engagement.md`](docs/rules-of-engagement.md) +Automated white hat it-security, pen-testing and isolation-probing. \ No newline at end of file diff --git a/SCOPE.md b/SCOPE.md deleted file mode 100644 index bc27a5a..0000000 --- a/SCOPE.md +++ /dev/null @@ -1,87 +0,0 @@ -# Scope - -## One-liner - -`whitehat-security` is NetKingdom's authorization-bound offensive-security -tooling for producing adversarial evidence about security claims. - -## Core idea - -The repository turns stated security properties into dated, reproducible attack -attempts. It remains separate from the systems it tests, reports findings -without grading their severity, and never treats a passing probe as proof that a -boundary always holds. - -## In scope - -- Attacker models for tenant isolation, credential confinement, noisy-neighbour - behavior and erasure verification. -- Differential probes that compare behavior across controlled tenant contexts. -- Known-bad and known-good fixtures that demonstrate every probe can fail. -- Rules of engagement, target authorization, engagement records, abort - controls and evidence minimization. -- Probe cadence and the resulting assurance/exposure window. -- Delivery of findings and passing-run evidence to `risk-nexus`. - -## Out of scope - -- Fixing defects in target repositories. -- Assigning severity, disclosure policy or remediation deadlines. -- Replacing mechanical checks owned by a target repository's CI. -- Defining the estate's security model or publishing permanent policy. -- Probing any target without the authorization and engagement records required - by [the rules of engagement](docs/rules-of-engagement.md). -- Blocking build-mode delivery without a separately recorded decision. - -## Safety invariants - -- Until the rules of engagement receive personal operator approval, only - documentation and non-networked fixture design may proceed. -- No live target is authorized by this scope document. -- Every live run names its authorization, target, owner, window, technique, - credential lane, rate ceiling, abort contact and finding destination. -- A probe stops at the recorded boundary and never follows an adjacent system. -- Evidence records response shape and counts, never real tenant row values or - credentials. -- Findings leave this repository; repairs do not enter it. - -## Relevant when - -- A service claims a Tenancy Posture evidence level that requires adversarial - rather than mechanical evidence. -- A boundary must be tested using a leaked runtime credential or hostile tenant - context. -- The estate needs to know when a probe last ran, what attacker it modeled, and - whether it was proven against a known-bad fixture. - -## Not relevant when - -- A repository needs unit, schema or provisioning tests for its own code. -- A finding needs triage, severity or disclosure handling; use `risk-nexus`. -- Permanent policy needs publication; use `policy-nexus`. -- The desired activity falls outside an approved engagement boundary. - -## Current state - -- Repository status: active. -- Active plan: `WHITEHAT-WP-0001`. -- `T01` is in progress: the rules of engagement are drafted and awaiting - personal operator approval. -- No live probe traffic is authorized yet. -- `T02` through `T07` remain gated by `T01`. - -## Relationships - -- Owner and security canon: `net-kingdom`. -- Finding intake, severity and disclosure: `risk-nexus`. -- Permanent publication: `policy-nexus`. -- Initial proposed target owners: `tenant-engine`, `audit-core` and - `flex-auth`. - -## Getting oriented - -1. Read [`INTENT.md`](INTENT.md) for the durable purpose and ownership model. -2. Read [the rules of engagement](docs/rules-of-engagement.md) before any probe - design or execution. -3. Read [`WHITEHAT-WP-0001`](workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md) - for active tasks and sequencing. diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md deleted file mode 100644 index 9efa35b..0000000 --- a/WORK-RECORDS.md +++ /dev/null @@ -1,18 +0,0 @@ -# Work Records — whitehat-security - -> Generated by `statehub fix-consistency` (CUST-WP-0061-T04, work-record -> stage 3). Do not edit by hand — edit the source file/block listed for -> each record and re-run fix-consistency to refresh this index. Archived -> workplans are omitted; closed decisions/intakes/engagements stay listed -> so recently-resolved work is still visible. [auto] - -| Kind | ID | Status | Lane | Source | -| --- | --- | --- | --- | --- | -| workplan | WHITEHAT-WP-0001 | active | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T01 | progress | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T02 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T03 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T04 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T05 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T06 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | -| task | WHITEHAT-WP-0001-T07 | wait | — | workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md | diff --git a/docs/rules-of-engagement.md b/docs/rules-of-engagement.md deleted file mode 100644 index 3747aca..0000000 --- a/docs/rules-of-engagement.md +++ /dev/null @@ -1,145 +0,0 @@ -# Rules of engagement for tenancy evidence - -Status: **pending personal operator approval** - -Version: 0.1 - -Date: 2026-08-18 - -Owner: NetKingdom / whitehat-security - -These rules authorize nothing outside their recorded scope. A probe without a -matching authorization record is prohibited, even if technically possible. - -## 1. Authorization classes - -| Target class | Required authorization | -| --- | --- | -| Offline known-good/known-bad fixtures created by this repo | This reviewed document | -| Estate build environment, non-destructive API differential probe | Standing estate authorization plus a dated engagement record naming the target owner | -| Any live Kubernetes workload, database credential, recovery or saturation probe | Separate operator approval for the named target, namespace, window and technique | -| Production | Production-specific written authorization; build-mode consent never carries over | -| Infrastructure not owned by the estate | Written authorization from its responsible party, per engagement, before any packet | - -Public reachability, a commercial relationship, and an assumption that an -owner would agree are never authorization. - -## 2. Engagement record - -Every run begins with a committed or operator-approved record containing: - -- engagement id, authorizer, approval timestamp and expiry -- target service, responsible repo/party, environment and namespace -- source location and network position of the probe -- exact API routes or database names in scope -- tenant fixtures and object identifiers created for the run -- credential lane, audience, role and maximum TTL (never the value) -- permitted techniques, prohibited techniques and concurrency/rate ceilings -- start/end window, operator contact and abort contact -- posture axis/claim and attacker model being tested -- finding destination in `risk-nexus` - -An expired, incomplete or mismatched record fails closed. Discovery of an -adjacent target is recorded and not followed. - -## 3. Initial authorized target envelope - -After personal approval of this document, offline fixtures may be built. No -live target is pre-authorized by this section. The first proposed live -engagements are: - -- `tenant-engine`: HTTP read/write differential using two disposable tenants -- `audit-core`: HTTP append/read differential using two disposable tenants -- `flex-auth`: decision differential for relationship inheritance across two - disposable tenants - -Each still needs its own dated engagement record and target-owner -acknowledgement. `databases/platform-pg` and `databases/apps-pg` are not in the -initial API-probe envelope; RLS, recovery and saturation work require separate -operator windows. - -## 4. Hard prohibitions - -- no destructive operation against data not created for the engagement -- no collection or exfiltration of real tenant row values; record only count, - schema shape, stable test-fixture ids and salted/one-run digests -- no denial-of-service, saturation, lock exhaustion, connection exhaustion or - large payload against shared substrate outside an explicitly approved window -- no superuser, `BYPASSRLS`, owner credential or standing privilege unless the - specific attacker model is testing detection of that misgrant -- no credential reuse outside its named audience/target and no credential - value in Git, evidence, State Hub, logs or chat -- no persistence, implant, account creation, lateral movement, vulnerability - chaining or follow-on discovery beyond the recorded technique -- no weakening alerting, backup, audit or retention controls to make a test pass - -## 5. Credentials and attribution - -Credentials are short-lived and obtained through the sanctioned custody lane. -The engagement records only the catalog/role reference, TTL and lease id if it -is safe metadata. The facility holds the same privilege as the modelled -workload—never broader privilege for convenience. - -HTTP probes send `User-Agent: whitehat-security/` and a stable -correlation id. Database probes set `application_name` to the engagement id. -The operator must be able to identify and terminate a probe from access logs or -`pg_stat_activity` without asking whether it is hostile traffic. - -## 6. Rate, concurrency and data controls - -API differential runs default to one in-flight request and at most 60 requests -per minute. A target owner may set a lower number. Test data uses two newly -created disposable tenants and deterministic synthetic values. Responses are -evaluated in memory; evidence stores status, count, content type, schema keys -and a salted run-local digest—not bodies. - -Database conformance defaults to one connection. Noisy-neighbour work has no -default: its connection/query/CPU ceiling must be written in the individual -operator-approved window. - -## 7. Abort and cleanup - -Any of these immediately aborts a run: - -- target latency/error rate crosses the engagement threshold -- a response appears to contain non-fixture tenant data -- scope, authorization, credential audience or target identity is uncertain -- operator/target owner requests stop -- audit attribution is absent -- an unexpected adjacent system responds - -The runner stops issuing work, closes HTTP/database sessions, revokes or lets -the bounded lease expire, and records the abort without attempting further -diagnosis. Cleanup deletes only fixtures whose ids are in the engagement -record. If cleanup cannot be proven, it becomes a finding; the runner does not -broaden privilege to force it. - -## 8. Evidence and reporting - -Every attempted run—pass, fail or abort—records: - -- authorization and engagement ids -- target revision/digest where observable without privilege escalation -- start/end timestamps and attacker model -- attempted operation count and response-shape comparison -- outcome: `pass`, `finding`, `inconclusive`, or `aborted` -- cleanup and credential-revocation outcome -- the statement: “Pass means only that the attacks attempted in this run did - not work; it is not proof that the tenant boundary always holds.” - -Findings route unchanged to `risk-nexus`; this repo assigns no severity and -does not fix the target. - -## 9. Change control - -Probe logic is security-sensitive. A change that makes a previously failing -known-bad fixture pass is a finding until independently explained. Every live -probe must first fail against its known-bad fixture and pass against the -known-good fixture in the same revision. - -## 10. Approval - -Personal operator approval is still required. Record approver, date and scope -in this section or an immutable linked decision before changing the status to -accepted. Until then, only documentation and non-networked test-fixture design -may proceed; no target packets are authorized by this draft. diff --git a/workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md b/workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md deleted file mode 100644 index 377ab7b..0000000 --- a/workplans/WHITEHAT-WP-0001-cross-tenant-evidence.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -id: WHITEHAT-WP-0001 -type: workplan -title: "Produce the adversarial evidence the Tenancy Posture ladders require" -domain: infotech -repo: whitehat-security -status: active -owner: net-kingdom -topic_slug: whitehat-security -created: "2026-08-17" -updated: "2026-08-21" ---- - -# WHITEHAT-WP-0001 — cross-tenant evidence - -## Goal - -Produce, on a schedule, the adversarial evidence artifacts that NetKingdom's -*Tenancy Posture* standard requires and no repo can honestly produce about -itself — starting with the one the framework calls its highest-severity gap. - -Done means: a service claiming `E2` has been attacked as an adversary holding -its runtime credential, the attempt is recorded with a date and an attacker -model, and a failure routes to `risk-nexus` rather than to a log nobody reads. - -## The forcing case - -*Tenancy Posture* open question 3 has been unowned since the framework was -drafted. What it calls a tenant-boundary failure the security industry calls -**Broken Object Level Authorization** — OWASP API1, top of the API Security Top -10 since that list launched, and the most commonly exploited API vulnerability -in published assessments. - -The estate has no coverage for it. `rapp-postgres` runs fifteen adversarial -probes and every one targets the *consumer* boundary — service versus service. -None targets the tenant boundary *inside* a consumer, which is where the -framework says the residual risk actually lives. - -## Rules of engagement — T01, and nothing else starts first - -An automated facility that probes systems without written scope is -indistinguishable from the threat it models. This is the gating task and it is -not paperwork. - -- **Target authorization**, the control that matters most now the facility is - scoped to any surface we choose rather than only our own. No target without a - recorded authorization from its responsible party. Our estate in build mode - has standing authorization only as a prerequisite: every live run still - needs the dated engagement record and target-owner acknowledgement defined in - the rules of engagement. Production needs its own authorization; anything we - do not own needs written per-engagement authorization recorded here before a - packet is sent. A commercial relationship, public reachability, and "they - would obviously be fine with it" are each explicitly not authorization. -- **Scope.** Which systems, which namespaces, which credentials — and a hard - stop at the engagement boundary. A probe that discovers an adjacent system - reports what it saw and does not follow it. -- **Prohibited actions**, stated as hard rules rather than intentions: - no destructive operations against data the estate did not create for the - test; no exfiltration of real tenant data even as proof of a finding — - a count and a schema shape are proof enough; no denial-of-service against a - shared substrate outside a declared window, because the connection ceiling - means a saturation probe is an outage for every co-resident. -- **Credentials.** The facility holds leased credentials like any workload, - through the sanctioned OpenBao lane. It gets no standing privilege, and - notably **no `BYPASSRLS` and no superuser** — an attacker would not have them - and a probe holding them proves nothing. -- **Attribution.** Every probe connection is identifiable as a probe in - `pg_stat_activity` and in logs, so an operator investigating an anomaly can - tell us from a real adversary in seconds. -- **Abort.** How a run is stopped, by whom, and what state it leaves behind. - -**Output:** `docs/rules-of-engagement.md`, reviewed by the operator personally. -This is exactly the class of thing `risk-nexus`'s escalation duty exists for. - -## Tasks - -### T01 — Rules of engagement -As above. Gates everything. - -```task -id: WHITEHAT-WP-0001-T01 -status: progress -priority: high -``` - -Drafted in `docs/rules-of-engagement.md` on 2026-08-18 with authorization -classes, per-run records, initial target envelope, hard prohibitions, -credential/attribution rules, rate defaults, abort/cleanup and evidence -schema. It authorizes no live traffic until the operator personally approves -§10. T01 remains progress and continues to gate every later task. - -### T02 — The attacker model per axis - -```task -id: WHITEHAT-WP-0001-T02 -status: wait -priority: high -``` - -What the adversary is assumed to hold, so a probe is judged against a threat -rather than against taste. Drawn from *Tenancy Posture* §4.3, which already -distinguishes them: - -| Axis | Adversary holds | Probe answers | -|---|---|---| -| E1/E2 | A legitimate runtime credential and the ability to make ordinary requests as tenant A | Can it reach tenant B's rows? | -| E3 | The above, plus SQL execution on the connection | Can it re-`SET` the tenant GUC and read across? | -| E4 | A leaked per-tenant credential | Can it address another tenant's substrate at all? | -| P1/P2 | A co-resident consumer behaving badly within its own allowance | What degradation do neighbours experience? | -| R | A copy of a backup taken before an erasure | Is the erased data still readable? | - -**Output:** `docs/attacker-model.md`. Note that the E3 row exists because the -framework corrected itself: E3 stops accident, not compromise, and a probe that -only tested accident would report a strength E3 does not have. - -### T03 — Differential cross-tenant harness (the E2 artifact) - -```task -id: WHITEHAT-WP-0001-T03 -status: wait -priority: high -``` - -The core technique: run the same request as two tenants and compare. - -- Provision two disposable tenants against a target service. -- Exercise its surface as tenant A; attempt every object identifier observed - from tenant B's context. -- Assert: B receives a denial or an empty result. **A well-formed 200 - containing A's data is the finding**, and the harness must be built to notice - that rather than to notice errors — both of this estate's real regressions - produced ordinary-looking responses, a 403 and a 404, and nothing alerted. -- Capture evidence as a count and a schema shape, never as tenant data (T01). - -**Acceptance:** run against `tenant-engine` and `audit-core`, both of which -currently claim `E2`. The artifact is the run record, not a green tick. - -### T04 — Prove the probes fail - -```task -id: WHITEHAT-WP-0001-T04 -status: wait -priority: high -``` - -A probe that has only ever passed is not evidence. - -Build known-bad fixtures — a service with a deliberately missing tenant -predicate — and confirm each probe fails against them. `rapp-postgres` verified -its drift check this way, by re-pinning to a bad digest and confirming exit 1; -the same discipline applies here and is not optional. - -**Acceptance:** every probe in T03 demonstrated failing before any of them is -trusted passing. - -### T05 — RLS conformance under attack (the E3 artifact) - -```task -id: WHITEHAT-WP-0001-T05 -status: wait -priority: medium -``` - -`rapp-postgres` ADR-0003 supplies an `rls_conformance` view and a template, and -states plainly that the platform's guarantee is **detection, not prevention** — -a table created by a later migration ships without a policy until something -notices. This repo is that something. - -- Query the conformance view on a cadence; any row is a finding. -- Attack what the view cannot see: a session that sets no GUC must read - nothing; a session with another tenant's value must see nothing; an insert - attributed to another tenant must be refused. -- Attempt the documented bypasses: a `SECURITY DEFINER` function owned by the - table owner, and a role holding `BYPASSRLS`. - -**Cadence is the deliverable here, not a detail.** For a detection-based -control the interval between runs *is* the exposure window, and ADR-0003 leaves -the number to this repo. Set it, and state the resulting window in the record. - -### T06 — Noisy-neighbour characterisation (the P1/P2 artifact) - -```task -id: WHITEHAT-WP-0001-T06 -status: wait -priority: medium -``` - -The framework had to reword this artifact once already: its first draft -required proof that a saturating consumer "does not breach" another's -allowance, which shared infrastructure cannot provide. - -What is achievable and therefore what this produces: a recorded baseline of -per-consumer resource usage; a run in which one consumer saturates its declared -allowance; evidence that the governance controls **bind**; and the degradation -co-residents experience, **measured and written down** rather than asserted -acceptable. - -Runs inside a declared window per T01 — on a single-node rail with a six- -consumer connection ceiling, a saturation probe is an outage if run carelessly. - -### T07 — Reporting into risk-nexus - -```task -id: WHITEHAT-WP-0001-T07 -status: wait -priority: medium -``` - -Findings leave this repo in one direction. A run produces: what was attempted, -under which attacker model, when, against which posture claim, and the outcome. -It carries no severity — that is `risk-nexus`'s. - -A **passing** run is also reported. "The attacks we thought of did not work" is -the honest claim, and recording it dated is what lets anyone see how stale the -assurance has become. - -## Sequencing - -T01 gates all. T02 shapes T03/T05/T06. T04 gates trusting any of them. T07 can -follow T03. - -## Risks - -**The facility becomes the threat.** Mitigated by T01, and by holding no -standing privilege. - -**Probes weaken silently.** A probe that starts passing after a change to -itself rather than to the system is a finding, not a fix. Probe changes are -reviewed as security changes. - -**Green is mistaken for safe.** Every report states that a pass means the -attacks attempted did not work, not that the boundary holds. - -**It drifts into fixing things.** The boundary in INTENT is load-bearing: -findings route out, work does not come in. - -## Open questions - -1. **Owner: NetKingdom** — settled 2026-08-17. Offensive security is security - work. The residual tension (NetKingdom owning both the Tenancy Posture - framework and the facility that tests conformance to it) is mitigated by - findings routing out to `risk-nexus` under separate ownership, and is - recorded in INTENT rather than argued away. -2. **Where probes run from.** In-cluster gives realistic network position; - outside gives independence from the substrate under test. Probably both, - eventually; pick one to start. -3. **Does a service get told it is being probed?** Announced runs are easier to - operate; unannounced ones test the alerting too. Build mode probably - announced, production probably not — which is itself a T01 decision.