TENANT DATA · WHO OWNS WHAT

Tenant data: principal versus resource ownership

An agent reads invoices, an HR file and a user’s folder for ana at acme. Decide where the tenant comes from, what is checked and with whose credential.

Computed experiment · sixty inspection seconds

Your experiment

ana, a member of tenant acme, works with an agent whose tools read invoices, files and HR documents. Six operations follow: two of acme’s shared invoices, an HR file private to bob, a guessed globex invoice id, a listing for tenant globex written after an injected instruction, and a listing of ana’s own folder. The opening tools trust the tenant argument and use the agent’s service credential.

Play replays the computed run over sixty inspection seconds; Next event steps, Restart rewinds, and Inspection time scrubs. Any input change recomputes the run and rewinds it without autoplay.

Event trace

    Computed data

    Final metrics

    Fictional stores and ids. With the delegated credential the store is assumed to enforce ana’s own permissions on single reads, while listings are prefix scans over keys built by joining ids, as described in the linked article. No identity provider or store is called.

    Principal and resource

    Every read has two sides: the principal asking, ana at acme from a verified token, and the resource, which has a tenant and sometimes a private owner. Tenant used for checks takes the tenant from that token or from a tool argument the model writes. Ownership check compares tenants, also requires private items to belong to the user, or does nothing. Tools call the store with the agent’s broad service credential or ana’s delegated one. Storage keys joins tenant and user into a prefix, or encodes it with a trailing delimiter.

    The opening run: three disclosures

    The tenant check stops the guessed globex invoice, D3. But D2, bob’s private HR file, is in acme, so a tenant-only check returns it. D4 is a listing for tenant globex that the model wrote after reading an injected instruction; the check compares globex with the argument globex and passes. D5 lists ana’s folder with the prefix acme/ana, which also matches acme/anais, so two of anais’s files are listed. Shared invoices D1 and D6 work as intended.

    Fixing each side

    Set Tenant used for checks to The verified token: D4 is denied, because the model cannot choose the tenant any more. Same tenant, and private items owned by the user denies D2. Encoded, ending in a delimiter makes the listing prefix acme/ana/, so D5 lists only ana’s four files. With all three, nothing leaks and both invoices are still returned. Setting Ownership check to None returns the guessed globex invoice as well: four disclosures.

    Failure boundary: the confused deputy

    From the opening, switch Tools call the store with to The user’s delegated credential: the store refuses bob’s file and every globex read itself, even with the model-written argument, because ana’s credential does not allow them. One disclosure remains, D5, because the listing permission covers the joined prefix that overlaps anais’s folder. An agent holding a service credential is a deputy that can be confused; act with the user’s authority where possible, and build keys that cannot overlap.

    Reading the run and its limits

    Play replays the six operations, each decision and the outcome over sixty inspection seconds; the table shows the resource, the decision and whether it was correct. Next event, Restart, Speed and Inspection time control the replay. The store’s enforcement for delegated credentials is an assumption; check what your store actually enforces, and test with two tenants and two users whose ids share a prefix.