privacy notes
july 2026
report 02
We tried five ways to filter a coding session. Two made it into the demo.
Some runs scored well and still turned "how is kashyab" into a secret. This is how we rebuilt the data, what failed, and what now runs in the public demo.
what it has to do
Coding sessions mix private data with identifiers that must stay intact. A good filter removes a password and leaves the adjacent Git commit, UUID, stack trace, and syntax alone.
This report covers one job: finding and removing exact strings of sensitive text. Deciding whether a whole section is too personal to share is a separate problem, not evaluated here. We do not claim that this filter anonymizes a session.
01 / data
How we built the training set
We built a catalogue of 18,457 realistic sensitive values: provider secrets, weak and strong passwords, default and database credentials, and network identifiers. SecretBench showed us the formats real secrets take. PWLDS and SecLists supplied public password lists. Every value is synthetic; we never copied live leaked credentials.
Five larger teacher models then wrote fresh coding scenarios around those values, rotating the ecosystem, developer role, incident type, and leak mechanism. No sentence gets reused with a different value swapped in. That template habit is what broke the earlier corpus.
| Input | Train | Dev | Test | Role |
|---|---|---|---|---|
| Public PII | 7,918 | 1,051 | 2,300 | A split-disjoint sample derived from AI4Privacy OpenPII. |
| Grounded secrets | 2,262 | 280 | 300 | Provider keys, passwords, database credentials, network identifiers, and matched clean controls. |
| Short names | 495 | 98 | 100 | Lowercase and diverse names inside short, independently written conversations. |
| Session-style sections | 3,972 | n/a | n/a | Conversation, source code, logs, configuration, terminal output, and rushed writing. Train only. |
02 / experiments
Pitfalls
we did not ship
The first dataset taught a bad shortcut. The next model scored tokens instead of complete spans. Bidirectional attention made that model better, but names still broke apart. Each result looked reasonable until we checked the exact text it removed.
More examples taught the wrong shortcut
An earlier model looked strong on broad test suites and still turned "how is kashyab" into a secret. The old corpus held 3,354 lowercase single-word secrets and just one comparable person name, so the model learned that a lone lowercase word is probably a secret. Repetitive template sentences around the values made that shortcut even easier to learn.
We stopped treating corpus size as the fix. The replacement data plants realistic values inside independently written scenarios and mixes in harmless lookalikes and short conversational names, so the model has to tell them apart instead of guessing by shape.
A 4B token classifier had excellent token accuracy and poor spans
We trained a Qwen3-4B LoRA to label every token with one of 33 BIOES tags, on 77,044 train rows. Validation token accuracy reached 98.48%. That number looked reassuring and was nearly useless: most tokens are not sensitive, so a model can score high while missing the ones that matter.
Measured on complete spans, exact typed F1 was 37.07% on OpenPII and 4.91% on names. It scored zero on eight user-reported probes and kept splitting names and credentials into fragments. We rejected it.
Bidirectional attention helped, but not enough
We replaced Qwen's causal mask with true banded bidirectional attention, so the model could read both directions around each token, and kept the same labeling head. In a controlled comparison, exact F1 improved from 35.66% to 45.78%, a real 28% relative gain.
The full 2,700-row sealed test landed at 45.62% typed F1. Person F1 was 19.30% and secret F1 was 44.91%. It processed 98.44 rows per second, but speed could not rescue broken boundaries. We rejected this model too.
03 / result
What finally worked
Generating exact values worked better than predicting every token
The Qwen design that worked writes answers instead of labeling tokens. It reads the section and returns a short JSON list of the exact sensitive strings it found, each with a label. The server accepts a value only when that exact string exists in the source, so a hallucinated value redacts nothing.
On the same sealed set it reached 94.48% precision, 96.69% recall, and 95.57% typed F1. A more compact values-only variant was faster in bulk evaluation, but it failed the long payment-configuration probe. We kept the typed extractor.
The two models cover different failures
The live Extra mode runs our OpenAI Privacy Filter checkpoint and the Qwen extractor in parallel. The OpenAI model returns the first usable redaction fast. Qwen adds its exact-matched spans as they arrive, without blocking the interface.
On the sealed set, their union reached 97.14% character precision, 99.66% recall, and 98.39% character F1. Typed exact-span precision was lower at 85.52%. The union favors catching leaks and can redact too much, which is why the UI exposes feedback and model status.
04 / deployment
What runs in the demo
private deployments
OpenAI Privacy Filter runs in our private RunPod worker. The Qwen3-4B LoRA runs as a private Fireworks deployment. Browser code never receives either provider key. Extra mode launches both requests at once and shows each model’s state.
Qwen returns copied values rather than character offsets. The server finds those values in the original text and discards any proposal that does not match exactly. A narrow structural guard covers high-confidence credentials such as database passwords embedded inside connection URLs.
Demo inputs are not added to the training corpus. Both services can scale to zero, so a cold request can be much slower than a warm inference. The interface reports that separately instead of hiding the wait inside the first model’s timing.
05 / limits
What still goes wrong
The test is internal
The final split is value- and text-disjoint, but earlier failures shaped later datasets. Treat these numbers as engineering evidence, not an independent certification.
The data is mostly synthetic and English
Public PII and external Loghub probes help, but they do not establish equal quality across languages, communities, or real organizations.
The union can over-redact
High character recall is useful for leak prevention. It also means the two-model union sometimes removes more context than a strict exact-span scorer would prefer.
Redaction is not anonymization
A missed secret is still possible, and surrounding context can remain identifying. This filter lowers exposure risk; it is not a compliance guarantee.
06 / sources