willchen96 slams the door on a document-snooping hole in tabular review

A community-reported flaw let any user pull text out of documents they were never allowed to see.

securitydiscovery

Tabular review is the feature that runs an AI extraction across a stack of documents and lays the answers out in a grid. The problem: it trusted whatever document references a user handed it, without checking that the user was actually allowed to read those files. A free-account attacker could drop someone else's document IDs into their own review, and the server would dutifully fetch the files, run an extraction over them, and hand back the text verbatim.

The fix, imported from an outside contributor's security report, now verifies access at every point a document gets pulled - you have to own the file or be on its project to touch it. Unauthorized IDs are quietly dropped rather than throwing a loud error, which keeps older clients working but means misuse won't show up as a blocked request in the logs.

So what Anyone running Mike with multiple accounts or tenants should treat this as a must-have patch - it closes a straight path to reading other people's documents.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from willchen96/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
e261d2e4 fix(security): scope tabular-review document_ids by access (CWE-639) Aeon (aaronjmars) 2026-05-10 ↗ GitHub
commit body
The tabular-review routes accept user-supplied document_ids in
request bodies (POST /tabular-review, PATCH /:reviewId) and stale
cell rows on byte-fetching paths (POST /:reviewId/regenerate-cell,
POST /:reviewId/generate). None of those paths checked whether the
caller can read those documents - a free-account attacker could plant
foreign UUIDs into their own review and have the server fetch the
bytes from R2 + run an LLM extraction over them, returning verbatim
text via the standard review GET.

Adds filterAccessibleDocumentIds(documentIds, userId, userEmail, db)
next to the existing access helpers (owner-of-doc OR project member),
and applies it at the four entry points:

- POST /tabular-review               drop unauthorised on insert
- PATCH /:reviewId                   drop newly-added unauthorised; keep
                                     already-attached cells so non-owner
                                     collaborators don't accidentally
                                     orphan rows they can't directly
                                     access
- POST /:reviewId/regenerate-cell    refuse byte fetch when caller has
                                     no access to the underlying doc
- POST /:reviewId/generate           filter docIds before parallel LLM
                                     fetch (defense-in-depth for legacy
                                     cells planted before this fix)

Fails closed silently rather than 403'ing so legacy clients that pass
stale ids don't error out the whole review.

Detected by Aeon + manual review.
Severity: high
CWE-639 (Authorization Bypass Through User-Controlled Key)
dbbf1969 Merge pull request #51 from aaronjmars/security/tabular-document-idor cosimoastrada 2026-05-10 ↗ GitHub
fix(security): scope tabular-review document_ids by access (CWE-639)

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-580.md from inside the repo you want the changes in.

⬇ Download capture-thread-580.md