skip to content

A policy attached to your receipts store grants read to a caller with no credential — what can an identity-attached permission never do?

level: middleimportance: must knowfreq 62%

answer

  1. two places a permission can be written
  2. one side follows the caller
  3. the other side follows the resource
  4. only one can name a stranger
  5. anonymous has no identity to attach to

basics

~20 s

A policy attached to the store itself can name callers its owner does not administer, including an anonymous one, so it grants access to a caller carrying no permission of its own. An identity-attached permission only widens what an identity you already manage may do.

solid answer

~40 s

Platform permissions can be written in two places: on the caller (an identity-attached permission) or on the thing being called (a policy attached to the store). The store-side policy is the one that can name callers the store's owner does not administer — another account's workload, or an anonymous caller presenting nothing at all. An identity-attached permission can only add power to an identity you already manage, so it can never make an object readable by someone who never authenticates. That asymmetry is why accidental public exposure always comes from the store side, and why a review that only reads identity permissions misses it. At request time both sides are gathered, and a matching explicit deny on either side ends the request.

code

json · 23 lines
json
{
  "policyAttachedTo": "store/receipts",
  "rules": [
    {
      "effect": "allow",
      "principal": "anonymous",
      "action": ["readObject"],
      "resource": "store/receipts/logos/*"
    },
    {
      "effect": "allow",
      "principal": "account:412/workload:receipt-api",
      "action": ["readObject", "writeObject"],
      "resource": "store/receipts/*"
    },
    {
      "effect": "deny",
      "principal": "anonymous",
      "action": ["listObjects"],
      "resource": "store/receipts"
    }
  ]
}

go deeper

for a junior

Remember there are two places a permission can live: on the caller, and on the store itself. Public access can only come from the store side, because an anonymous request has no identity to hang a permission on.

for a middle

Be able to explain what each side can express and how they are combined on a request: default deny, allows gathered from both sides, a matching explicit deny ending it. Name the grants only the store side can write.

for a senior

Show that you review the store side specifically, that you know an object-level grant can expose data a clean store policy hides, and that a copy into another store lands under that store's policy instead.

for a principal

The trade-off is who holds the pen. Store-side policy is usually editable by the team that owns the store, so leaving public grants technically possible is an organisational decision about blast radius, not a configuration detail.

A mobile backend keeps user-uploaded receipts in an object store and serves them to the app. Deciding who may read one of those objects is not a single setting: on every large platform the decision is assembled from permissions that can be written in two different places, and the difference between them decides who is even **expressible** as a caller. ## The two sides - An **identity-attached permission** is written on a caller you administer — a user, a group, a workload identity, a role a service assumes. It reads *this identity may perform these actions on these resources*, and it travels with the caller wherever it goes. - A **resource-attached policy** is written on the thing being called — here, the store. It reads *these callers may perform these actions on me*, and it lives and dies with the store. Delete the store and the policy goes with it; copy an object elsewhere and the policy does not follow. | | Identity-attached permission | Policy attached to the store | |---|---|---| | Lives on | a caller you administer | the store (or a single object) | | Can name | identities inside your own account | any caller, including ones you do not administer | | Anonymous caller | cannot be expressed — there is no identity to attach to | can be granted read directly | | Usually edited by | whoever administers identities | whoever owns the store | | Source of public exposure | no | yes | ## What only the store-side policy can express The store's own policy is the only place a grant can name a caller the store's owner does not administer. Two cases matter: 1. **The anonymous caller.** A request that carries no credential still arrives at the store. There is no identity to hang a permission on, so the only way it can be allowed is a rule on the store that names *anyone* as an acceptable caller. This is exactly what "the store is public" means mechanically. 2. **A caller in another account.** An external partner's workload has permissions written by its own administrators, not yours. Your store's policy is where you say that this outside caller may read — and their administrators must separately allow their own workload to try. Platforms differ in the details, but a cross-account read commonly needs a grant on **both** sides; a grant on one side alone is not enough. Both mechanisms also let the store owner attach a **condition** to the grant — that the caller be one of a named set of accounts, for example — which is evaluated as part of the rule rather than as a separate check. ## How the two combine on a request The usual model is: - start from **default deny** — an unmatched request is refused; - gather the allows that apply from **both** sides; - apply any **explicit deny** that matches, which ends the request regardless of how many allows were found. The practical consequence is that adding a broad identity-attached permission cannot rescue a caller the store explicitly denies, and cannot conjure access for a caller that has no identity at all. ## Why this is where exposure comes from Because only the store side can name an unknown caller, a store becomes world-readable through a grant written on the store side — at store level or on an individual object — and never through a permission someone attached to a user. That has three review consequences worth internalising: - an audit of identity permissions alone will pass a store that the whole internet can read; - the blast radius of a store-side mistake is not scoped to your organisation, unlike an over-broad identity grant, which at least still requires the holder to authenticate; - the person who can open the store to the world is whoever can edit the store's policy, which is frequently the product team rather than the security team. ## What to do with the distinction Use identity-attached permissions for your own services and people — that is what they are for, and they are the side that follows a caller across resources. Use the store's policy narrowly, for exactly the grants the identity side cannot express: a named external account, or a deliberate, scoped public read for assets that genuinely are public. Treat any rule on a store whose caller is *anyone* as a finding until someone explains it, and remember that the object-level equivalent exists too, so a store whose policy looks clean can still hold individual objects that were granted out one at a time.

  • Your partner's workload still cannot read the store after you added it to the store's policy. What is the likely missing half?
    The grant on their side. A cross-account read is commonly assembled from two permissions: yours saying the outside caller may read this store, and their administrators' saying their workload may attempt a read against it. Yours removes your objection; it cannot give their workload permission its own account withholds. Check which half is missing before widening either.
  • Does a policy on the store follow an object that is copied into a different store?
    No. A resource-attached policy belongs to the resource it is written on, so a copy lands under the destination store's policy instead. This is a common way data quietly changes exposure: a nightly job copying receipts into a store with a looser policy inherits that looser policy, and nothing about the source store's settings warns you.
  • If an identity-attached permission cannot open a store to the public, why review it at all?
    Because it decides what your own authenticated callers can reach, which is most day-to-day risk: an over-broad read on every store lets any compromised or curious internal caller pull the receipts. It is a different failure from public exposure — bounded to callers who can authenticate — and both reviews are needed.

saying these in an interview costs you the question

  • Says a permission on a user can make an object publicly readable
  • Thinks only one of the two sides is consulted per request
  • Assumes a cross-account read needs a grant on your side only
  • Believes the store's policy follows objects copied elsewhere
  • Treats an identity permission review as proof nothing is public