# Curtain

- **Event:** [Meta Global AI Developer Hackathon](https://cerebralvalley.ai/e/meta-ai-developer-hackathon)
- **When:** Oct 26, 12:00 PM – Nov 4, 9:00 PM (EST)
- **Where:** Online
- **Team:** [Chozharajan Mahalingam](https://cerebralvalley.ai/u/chozha-dev)
- **GitHub:** https://github.com/Chozharajan2001/curtain
- **Demo video:** https://youtu.be/LxsNCvsb2yY
- **Gallery:** https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery
- **Page:** https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2181

Curtain is a privacy gate for screenshots.

The problem: people paste support tickets, chat logs and receipts into AI
tools, and those images carry names, phone numbers, card numbers and
addresses. The usual fix is a light blur. A blur still lets the letters be
read.

What Curtain does, in four steps:
1. Find. Muse Spark 1.3 looks at the image and returns a box for every
   piece of personal data.
2. Cover. SAM 3.1 tightens each box, then Curtain paints solid black over
   it and strips the metadata.
3. Attack. A second, different model, Muse Spark Open hosted on Baseten,
   gets only the covered image and is asked to read it.
4. Decide. If any planted secret comes back, the image is refused. Nothing
   is released on a maybe.

Numbers, each printed by one command in the repo:
- 22 secrets planted across 5 synthetic images (npm run count:planted)
- Finder recall 0.909, 20 of 22, on the best saved run (E2)
- Attacker recovered 0 of 22 secrets from the covered images (E5)
- Hard set built to break the finder: recall 0.200, 2 of 10, and still
  0 of 10 leaked (E14, E15)
- 74 checks pass, exit 0 (npm run verify)
- Total spend 99 API calls, $1.18 (npm run cost)

The part I want judged: the attacker refusing is the proof. On a lightly
blurred ticket the same attacker says it cannot transcribe personal
information (runs/attack-blur2-refusal.json). That refusal shows the model
can see secrets when they are there. So when it reads nothing from a
Curtain image, that is evidence and not luck.

Everything is fail closed. An empty model reply means refused. A tampered
answer key means refused. An unparseable reply means refused. There is no
flag that skips a check.

Two ways to run it: an MCP server with inspect, mask and verify tools that
any agent can call, and a Next.js page at /verify that takes an upload and
returns the verdict.

Honest limits, all in LIMITATIONS.md: the data is synthetic, the finder
misses tiny 15px text, run to run recall moves between 0.773 and 0.909,
and the finder reads your image through the Meta API, so it is one logged
read rather than a local process. On-device finding is the next step.

## More from Meta Global AI Developer Hackathon

- [Real Smart Phone](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2178)
- [Sado](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2179)
- [Uncrumple](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2180)
- [Unscroll](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2182)
- [worldoverlay](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2183)
- [mesoloplswin](https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2184)

---

Markdown version of https://cerebralvalley.ai/e/meta-ai-developer-hackathon/hackathon/gallery/2181. Site index for agents: https://cerebralvalley.ai/llms.txt · full text: https://cerebralvalley.ai/llms-full.txt
