03 the posture

the security posture, documented.

what is actually true, what is measured, and what is still open.

Most security pages describe intentions. This one describes mechanisms — the specific choke point, the specific table, the specific redactor — and where each one was found to be insufficient. The failures below are not hypotheticals. Two of them were live in production.

four rules that did the work

01

a choke point only protects what flows through it

An egress guard was built and wired into the main model path. It worked. It also protected nine of fifteen outbound paths in the tree, because six had never been counted. One was a second complete LLM path sending page context straight to a provider. Another posted directly to a provider from a legacy module. Another sent webhook payloads unscrubbed. The guard was correct — the inventory was not.

02

a local host is never evidence of a local model

Every cloud request in this fleet goes through a local proxy. A rule that decides "is this egress?" by looking only at the hostname therefore classifies everything as local — and the guard protects nothing while appearing fully configured. The decision has to be made on model family and proxy route as well as address. Anything resolving to loopback and carrying a cloud model name is cloud egress.

03

fail closed, and make a missing module fail closed too

If the redaction step throws, the request is blocked, not logged and passed through. If the redaction module is missing, the request is also blocked — because a missing module that degrades to "allow" is a silent bypass. The same rule applies to the egress tripwire: absent or malformed means no request.

04

test a redactor in both directions

Recall and precision. A redactor that masks a commit hash corrupts the diff it was meant to protect, silently, and the corruption looks like authoring. The fleet's redactor measures 13/13 on the leak battery and 4/10 → 2/10 false positives after the over-masking rules were written into it. Reporting one number without the other is lying.

the layers

network — control plane off the LAN
An nftables table accepts loopback, the tailnet, and docker, then drops and logs every other port in the AI and control-plane range. Proven by toggle attribution: a probe inside a network namespace on a fake LAN address shows the port going from reachable to dropped and back when the table is applied and removed. A firewall you have not toggled is a hypothesis.
egress — one choke point, counted
Every model request is scrubbed after the prompt is built and before it is sent, at a single point. A manifest lists every file that can put bytes on the wire; a test fails the build if an unclassified outbound call appears. The two bypasses that were found — the legacy direct post and the unscrubbed webhook — are closed and covered by the manifest.
redaction — a proxy, not a post-processor
The masker sits in front of the request, so it can refuse rather than merely redact. It runs a named-entity recogniser plus a denylist of real client names, and deterministic rules for structural cases: cards must pass Luhn, phones reject date- and clock-shaped strings, and bare hex is never masked. Secrets are refused, never substituted — a substituted secret is a credential now sitting in a log.
credentials — the agent may not type into a password field
The agent could previously type into any input[type=password] unconditionally. It now defaults to block and hand off to a human, with explicit approve and allow modes, and an unknown policy fails safe to block.
audit — a hash chain over the redacted record
Every record in a run chains to the one before it. What is hashed is the redacted record — never the raw one. An evidence bundle ships the raw chain, a verification result, and a manifest of the bundle, so the recipient can reproduce the check themselves.
secrets — caught before they leave the machine
A pre-commit secret scanner blocks a credential before it reaches history. The hook in this repo once caught the author reusing a live secret as a test fixture — the hook works. Push protection catches what the hook misses.

measured, not asserted

egress paths protected
9/15

found when the paths were counted properly for the first time. The other six are now closed.

redactor leak battery
13/13

recall on a battery of planted secrets. Precision is 2/10 false positives.

vendor allow-list
148

multi-word vendor spans, up from 86, added so real names stop being masked.

audit chain entries verified
5/5

untouched chain reports VERIFIED; one edited field localises the tamper to its sequence number.

what we do not catch

These are the open gaps. They are listed here because a security page that only reports coverage is a marketing page.

a PEM private key block is not detected redactor

A full private key block, with its header, is not matched. Whether a bare key body is caught depends on whether the surrounding text gives the field name away.

an AWS secret access key is not detected redactor

The 40-character secret half of an AWS key pair is not matched by the structural rules. The access-key-id half is. This is the classic shape of a partial rule: one half covered, the other not, and the coverage looks complete.

the mask vault evicts live placeholders open defect

The masker keeps a bounded vault of placeholder-to-original mappings. When it fills, the oldest mapping is evicted — and when a later response contains a placeholder whose original is gone, the restore step leaves the placeholder in place rather than failing. The model's output then contains a literal token that gets written into generated code as a string. It was found by inspection, not by alarm: there was no observable signal across 152,000 log lines. The real fix is to stop masking inside fenced code blocks.

masking is not de-identification legal

A redactor does not make a system HIPAA-compliant. HIPAA offers Safe Harbor — eighteen specific identifier classes — or Expert Determination, and neither is a regex. Nothing on this page is a compliance certification, and this site makes no claim to be one.

take the kit

the security kit

Eight files, all public-safe: the nftables table, the egress inventory and its anti-regression gate, the redactor rules, the audit chain spec, a 14-rule secret scanner config, and a sixteen-question DLP checklist. Everything is a template — change the interface names to match your box.

Everything in the kit is tested before it ships. The coverage gate runs green out of the box against its own fixture tree.

download the kit
nft-svc-hardening.nftthe firewall table, with the toggle-attribution proof
egress-manifest.jsthe inventory shape, and how to extend it
egress-coverage.test.jsthe gate — fails on any unmanifested outbound call
redactor-rules.mdover-masking rules and the three pattern bugs
audit-chain.mdwhat is hashed, and what the chain does not prove
gitleaks.toml14 rules, anchored to real key formats
pii-dlp-checklist.md16 questions before sending anything to a model
fixture/a tree that makes the gate pass on a fresh clone

The most useful single thing in the kit is not a control. It is a habit: count the paths before claiming coverage. The guard that protected nine of fifteen paths was not a bad guard. It was a good guard with an incomplete inventory — and the inventory was the part nobody had written down.

the incident log what it costs the services

methodology documented 2026-10-16 · no credentials, hostnames or client names published