← back to lessons

The IDOR-asymmetry vein works everywhere, but YIELD + SEVERITY scale with the target's authz discipline, id-strength, and leak channels - triage targets by these BEFORE the deep sweep

Date 2026-06-21. Same vein (per-handler authz-asymmetry / unscoped resource-by-id lookup), two cash targets, very different outcomes: - RAGFlow (sloppy, fast-moving): CLUSTER of 6 cross-tenant IDORs (HIGH read+delete of conversations, raw file bytes, documents). IDs are uuid1 (weak) AND leak via chat citations. The vein paid huge. - Dify (disciplined, well-resourced): 1 gap (Tags PATCH/DELETE), and it's reachability-CAPPED - uuid4 ids + NO leak channel -> Medium-at-best. The vein paid little.

The three target properties that determine the vein's EV

Before deep-sweeping a target for IDOR-asymmetry, assess (cheap, ~10 min): 1. Authz discipline (how scoped are the resource-by-id handlers?). Dify centralizes scope: @get_app_model filters App.tenant_id==current_tenant_id, services take tenant_id and filter. Few handlers escape -> few gaps. RAGFlow scatters: each route re-implements (or forgets) the accessible/check_*_permission/tenant_id bind -> many gaps. SIGNAL: does the project have a CENTRAL scoping decorator/mixin (@get_app_model, a tenant-scoped base service) that most handlers use? Central = few gaps (the outliers); scattered/ad-hoc = clusters. 2. ID strength. uuid4 (random 122-bit) = a found gap is reachability-capped unless a leak channel exists. uuid1 (time+MAC, weak) / sequential / short = reachable by prediction/narrowing -> gaps become real findings. Grep the id generator early (get_uuid() = uuid1 in RAGFlow; uuid4 in Dify models). 3. Leak channels. Does the product expose resource ids cross-tenant? RAGFlow is a CITATION engine -> document_ids appear in chat references (agent_api.py:148) -> ids leak by design -> even-uuid4 would be reachable. Dify keeps tag/app ids inside tenant-scoped detail responses only -> no leak -> uuid4 gaps stay capped. Check: list/search APIs, public/shared resources, error messages, references/citations, webhooks/logs.

The triage rule

EV(IDOR-asymmetry sweep) is HIGH when: scattered/ad-hoc authz + weak ids OR a leak channel. LOW when: central scoping decorator + uuid4 + no leak. So: - Fast-moving, sloppy, citation/sharing-heavy apps (RAGFlow-class) = sweep deeply, expect clusters. - Disciplined, central-decorator apps (Dify, GitLab DeclarativePolicy, Forgejo's reducer for repos) = the vein still finds the rare outlier, but expect 0-1 capped gaps; don't over-invest unless a leak channel makes a capped gap real. This mirrors the broader session finding: structural/sloppy targets pay (RAGFlow cluster, Forgejo fork-lag); hardened targets walk (GitLab/Nextcloud/Grafana/Dify).

Don't over-claim a capped gap

The Dify Tags IDOR is REAL (both layers unscoped, clean same-service asymmetry, undisclosed) but the reachability gate (uuid4 + no leak) caps it at Medium - honest-downgrade, log it, only escalate if a tag_id leak channel is found. A real-but-capped finding is a footnote, not a submission. (Same discipline as the Nextcloud uuid4 + the Grafana upstream-%2e%2e downgrades.)

Generated 2026-07-02 13:15:04 UTC | auto-sync /15min