Post-mortem
My AI was quietly reusing private emails to sound like me
The scariest leak in my system was a helpful one: private correspondence had become reusable voice context for unrelated AI work, and nothing was broken. This is the post-mortem, and the boundary check that ended it.
Key findings
- Private correspondence had quietly become reusable global voice context, making unrelated AI work cheaper in the wrong way.
- Nothing was broken, so nothing flagged it: quality alarms can't catch a helpful leak. Privacy needs its own sensor at the boundary.
- The egress check lets generalized lessons pass and blocks raw records, and reports only a category and a path, never the matched value.
My AI had turned private emails into reusable style context, so unrelated work could sound like me. Nothing was broken. The fix: a deterministic egress check at the domain boundary.
Two glosses up front. Deterministic: the same inputs always give the same result, no AI judgment in the loop. An egress check: an automated scan at the boundary where content leaves a restricted domain — a private area of the workspace whose raw records must not travel. Hold both, because this incident breaks the usual shape of a failure story. The scariest leak I've had was not a breach or a bug. It was a feature working.
_check-private-egress.py.How do private emails end up in unrelated AI work?
Through helpfulness. My system keeps a global layer any session can load, and restricted domains for private records. At some point, real correspondence was distilled into "how Ali writes" reference material for the global layer, and raw records traveled with the lesson.
The efficiency was real. Voice context makes every writing task cheaper: less re-explaining, better first drafts, an assistant that sounds like me on the first try. The incident ledger records the cost in one line: private correspondence had quietly become reusable global voice context, "making unrelated AI work cheaper in the wrong way."
Details here are generalized to protect the people involved. The pattern is exact.
Why did nothing flag it?
Because nothing failed. Outputs got better, not worse. No error, no wrong number, no suspicious diff. Every alarm I had was tuned for failure, and this was success.
Here is the critical judgment I'll stand behind: AI memory features across the industry are built to do precisely this, and they market it as personalization. The retention is the feature. If your assistant "knows you," ask what documents that knowing is made of, and where those documents can now travel.
My own rule, "cannot fail silently" beats "cannot fail," had a blind spot. A leak that improves output is silent by design. Quality sensors will never catch it, because on every quality axis it scores as an improvement. Privacy needs its own sensor, pointed at the boundary, indifferent to how helpful the crossing is.
What does the egress check actually block?
It's a read-only script, _check-private-egress.py, that scans every Markdown file in the restricted domain and in the global profile layer, then reports findings by category. The categories are the mechanism in miniature:
- Provenance leaks. Provenance is where a piece of text came from. A global-layer file that cites a private-domain source raises a raw-private-provenance finding. Lessons may cross; pointers back to raw records may not.
- Credential-shaped values. Text that looks like an access code near words like "code" or "pin" raises a raw-credential-value finding, but only when the value contains a digit and the line carries no redaction marker. Ordinary prose words don't trip it; a documented, redacted history is fine.
- Full financial identifiers, in a file's body or in its filename. The generalization line is precise: an account referenced by "ending in" its last digits passes, the full identifier blocks.
- Exact locations. A specific address or unit number in a global file blocks. A generalized description doesn't.
And the part I'd defend hardest: the check demands that the restricted domain carry a written privacy contract, with "Restricted by default" and "Never store live credentials" actually present in it. If that contract is missing or incomplete, the check blocks with exit code 2 instead of passing quietly. A privacy check that shrugs when the privacy rules are absent would be theater.
Exit 0 is clean, exit 1 is findings, exit 2 is a broken contract. Nothing in between.
How do I know the check itself doesn't leak?
Because it never repeats what it finds. Its output is a category name and a file path, never the matched value.
The self-test proves this the unfriendly way. It builds a scratch workspace, plants a fake credential, and fails itself if detection misses — or if the planted value shows up anywhere in its own output. It also takes a sha256 fingerprint (a content hash: if any byte changes, the fingerprint changes) of every file before and after a scan; any difference is a failure. The scanner guarding the boundary has to re-prove, on every self-test run, that it is read-only and value-safe.
What the fix preserved matters as much as what it blocked. Generalized lessons still cross; a system that can't keep its lessons isn't worth running. Raw records stay home. That's the whole trade, and the ledger row closes on exactly it: raw records stay private, generalized lessons survive.
So, for anyone running an AI with memory: what is it reusing right now that makes your output better? Not what's broken — what's helping. And if a private record were riding along inside that help, would anything in your setup notice the crossing?
Method & data
Method: a live privacy incident in one restricted domain and the deterministic egress check built after it: boundary scan, finding categories, privacy-contract gate, and value-safe self-test, generalizedData: patterns and methods only; no names, dollar figures, addresses, case identifiers, or confidential content · Last checked: 2026-08-14
How this was made
AI-drafted, adversarially checked, human-directed. My AI assistant wrote this from the system's own records — the egress check script and the incident's ledger row. A separate AI session then tried to break every claim against those records, and automated privacy and readability gates ran before publish. I direct this pipeline, own every boundary in it, and audit published pages on a rolling basis — if you find an error, tell me and it goes in the corrections log, dated, never silent.
I'm Ali — I run real life-and-work admin on AI agents, then check their work in the open. More at /about.
Published under my standards. Found an error? Tell me — corrections go in the corrections log, dated, never silent.
Cite this
@online{ali2026contextleak,
author = {Ali},
title = {My AI was quietly reusing private emails to sound like me},
date = {2026-08-14},
url = {https://alidoes.ai/ai-private-context-leak/}
}Caught something I got wrong? Send it directly. Confirmed corrections go in the corrections log.