← ClaudeAtlas

api-mongo-agg-facet-bypasslisted

Bypass a MongoDB aggregation-pipeline stage allowlist by nesting disallowed read stages inside $facet, then $unionWith/$lookup sibling collections to exfiltrate secrets (invite tokens, creds, hashes). Load when: an endpoint accepts a user-supplied `pipeline` (or errors like "operator-form queries not accepted, use the pipeline parameter"), a Node/Express + MongoDB backend, 24-hex `_id`s, or an "advanced query" API. Authorized targets only.
NoorQureshi/ronin · ★ 15 · API & Backend · score 76
Install: claude install-skill NoorQureshi/ronin
# MongoDB aggregation injection — $facet allowlist bypass → cross-collection read ## When it applies - An API runs a user-controlled **aggregation pipeline** on a fixed collection (`db.collection('x').aggregate(userPipeline)`), usually exposed as a `pipeline` query/body parameter for "advanced" search. - The server defends with a **stage allowlist** — only screens the *top-level* stage names (`$match/$project/$sort/$limit/$facet` allowed; `$lookup/$unionWith/$group/…` rejected with something like `"invalid or disallowed pipeline stage"`). - Tell-tale that a `pipeline` param even exists: sending the normal search term as a Mongo **operator object** (`?q[$ne]=x`) returns a hint such as `"Operator-form queries not accepted on 'q'. Use the 'pipeline' parameter…"`. ## Why it works The allowlist inspects only the outermost stage keys. **`$facet` runs sub-pipelines whose stages are never re-screened** by the app, so a disallowed read stage placed inside a `$facet` sub-pipeline reaches MongoDB unchecked. MongoDB itself still forbids a few stages inside `$facet` (`$out/$merge/$collStats/$indexStats/$listCatalog/$documents`), but it **permits `$lookup` and `$unionWith`** there — and those read *other collections in the same database*. That turns a "search our metadata" endpoint into "read any collection in this DB". ## Method 1. **Confirm the pipeline sink & allowlist.** Baseline `?pipeline=[{"$limit":1}]` returns docs; `?pipeline=[{"$count":"n"}]` / `$group` / top-le