An intruder runs code inside a search service — what does its fetch path decide about what they can ask the store for?
answer
- what is in the process is already gone
- the next request is the real question
- a live client is an enumeration tool
- address out of the workload raises cost
- the grant bounds it, not the address
basics
~20 sWhatever the process is already holding is lost either way. The fetch path decides whether the intruder also inherits a working store client and a live identity, and can request every name that identity's grant allows.
solid answer
~50 sStart from what is unavoidable: any credential the process is currently using can be read by code running in that process. The fetch path decides what comes **next**. If the service fetches for itself, the intruder finds the store's address, a client and a live identity, and can ask for every name the grant allows — not only the one value the service needed. If a helper or a companion resolved the value and handed it over, the workload holds values and nothing else; asking for more means finding and using the fetcher's local interface, and being served under the fetcher's identity and grant. Keeping the store's address out of the workload raises the cost of that next step; it is not a boundary, because a determined intruder on the same host can usually find the fetcher. The grant is what bounds the damage.
code
pseudocode · 8 lines// the in-application path, inside the service process
store = connect(STORE_ADDRESS, workloadIdentity)
dbPassword = store.read("search/db-password")
// an intruder with code execution reuses both, unchanged
store.list("search/") // every name the grant allows
store.read("search/report-signing-key")
store.read("payments/db-password") // refused only if the grant is narrowgo deeper
Recall that code running inside a process can read whatever that process is holding, so the credential in use is gone as soon as the process is compromised.
Explain what else is in the process under each path — an address, a client, a live identity — and why that turns one compromise into the ability to make further requests.
Work the blast radius concretely: name the grant the intruder would inherit, whether it permits listing, and which names sit inside it. Say what removing the address does and does not buy.
Set the expectation that grants, not fetcher placement, bound this, and that the estate needs a way to see how wide each fetcher's grant has drifted since it was written.
## What is already lost The moment an attacker executes code inside a process, every secret that process is currently using is theirs: the database password in a connection pool, the signing key held for the life of the service, whatever sits in an inherited environment value. No fetch path changes that. Candidates who answer this question by arguing about where the value was written have answered a different question. The interesting question is the **next request**. The intruder has a foothold in one workload; how much more of the estate does the fetch path hand them for free? ## What the fetch path decides next | | Service fetches for itself | Companion beside the workload | Helper on the host | |---|---|---|---| | In the process | store address, client, live identity | resolved values only | resolved values only | | Next request costs | nothing, the client is right there | find and use the local interface | find and use the local interface | | Served under | the service's identity | the companion's identity | the helper's identity | | Ceiling on what can be asked for | that service's grant | that workload's grant | the union across that host | Read the last two rows together, because they pull in opposite directions. Self-fetch is the most convenient path for an intruder and usually the **narrowest** ceiling, since the grant was written for one service. A host-wide helper is less convenient and usually the **widest** ceiling, since its grant is the union of everything on the machine. There is no ordering of the three paths by safety that survives contact with the grants; the grant is the number. ## Why a live client is an enumeration tool What a self-fetching service leaves behind is not just a secret — it is the ability to ask questions. With a configured address and a valid identity in the process, an intruder can try names, and where the grant permits listing, can enumerate a branch of the name space outright. That matters because the right to **list** discloses what exists even where reads are refused: names tell you which systems exist, which teams own them, and where to aim next. A service that needed exactly one value, but whose grant covers a whole branch, has converted one compromised process into a map. ## What removing the address actually buys Three honest statements, in order: 1. **It buys time and noise.** With nothing in the process pointing at the store, the intruder must discover the fetcher on the host and work out how to talk to it. That is effort, and effort produces activity that can be noticed. 2. **It does not buy a boundary.** The fetcher reaches the store from that same host, so a path exists. Treating an address as a secret is obscurity; useful obscurity, but it is not the control. 3. **It changes whose grant applies.** Once the intruder is talking to the fetcher, the ceiling is the fetcher's grant, not the workload's. On a shared helper that is often a *worse* ceiling than the service's own. ## The control that bounds this The bound is the grant attached to whichever identity the intruder ends up using, plus how much the credential itself opens once obtained. Narrowing that grant to the names the caller genuinely needs — and treating the right to list as disclosure, not as a harmless extra — does more here than any choice of fetcher. Short-lived credentials help too, by bounding how long what was taken keeps working, but that is a property of the credential rather than of the fetch path. One direction to keep straight afterwards: replacing the compromised value puts a **new** value in place; it does not undo a read that already happened, and it does not stop the old value until the old value is withdrawn from the system that accepts it. A response that only rotates has done half the work. ## Checking your own answer If you claim a fetch path limited the blast radius, you should be able to name the grant that did the limiting: which names that identity may read, whether it may list, and what the intruder would have got if the grant had been one level broader. If you cannot name it, the claim is about the diagram rather than about the system.
- Does a companion process stop the intruder reaching the store at all?No. It removes the address and the client from the workload, so the intruder has to find the local interface the companion exposes and is then served under the companion's identity. That is friction plus a different ceiling — one workload's names — rather than a boundary.
- Which fetcher gives an intruder the widest set of names to request?Whichever one holds the widest grant, which is usually a helper serving a whole machine, because its grant is the union of the workloads there. A self-fetching service is the most convenient to abuse but normally the narrowest. Convenience and reach are different axes.
- What single change reduces this exposure most, whatever path you use?Narrow the grant of the identity that will be used, and treat the right to list as disclosure rather than as a lesser read. A fetcher that can read one name gives up one name; one that can list a branch gives up a map of the estate.
saying these in an interview costs you the question
- Says hiding the store's address stops an intruder on that host
- Claims a companion process protects the value already in memory
- Assumes the intruder can only get the one value the service uses
- Treats the fetcher's local interface as authenticated by default
- Thinks replacing the value undoes a read that already happened
- Calls listing a harmless subset of reading