skip to content

A leaked pipeline credential made only read calls all year — why is that not the scope of what it reached?

level: seniorimportance: must knowfreq 55%

answer

  1. entitlement, not traffic
  2. your logs describe your own jobs
  3. list every right, then follow each
  4. check for a second acceptor
  5. reads that return further credentials

basics

~20 s

Scope follows the rights the credential carried, not the calls your own jobs happened to make. Enumerate every action and object it was entitled to, everywhere the value was accepted; observed traffic describes your usage, never a stranger's limit.

solid answer

~40 s

Your call history is a description of your own jobs. Whoever holds the leaked value is not bound by it: they get everything the credential is entitled to do. So scoping starts from the entitlement — what the counterparty would have accepted from that credential — and not from the traffic. That means listing every action it could perform, every object it could reach, any rights it inherited through a group or role, and every place the same value was configured, because a value reused in a second environment doubles the reach silently. Then follow the one-hop cases: a read that returns another credential or an endpoint extends reach beyond the service. The output is a written statement of what a holder could have done, and for how long.

code

json · 13 lines
json
{
  "credential": "pipeline-scoring",
  "acceptedBy": ["scoring-service", "scoring-service-second-environment"],
  "rightsDirect": ["score:read", "batch:submit", "batch:cancel"],
  "rightsInherited": ["dataset:list", "delivery:write"],
  "observedCalls": ["score:read"],
  "oneHopReach": {
    "delivery:write": "can point result delivery at another address",
    "dataset:list": "discloses every dataset name and size"
  },
  "scopeBuiltFrom": "rightsDirect + rightsInherited, in every acceptedBy",
  "note": "observedCalls describes our jobs, not the holder's options"
}

go deeper

for a junior

Remember that a leaked credential gives its holder every right it carries, not the subset your own code uses. Read access is still access to everything readable.

for a middle

Explain how effective rights are assembled — the direct grant plus anything inherited — and why the same value accepted in a second place widens reach with nothing visible in either entitlement view.

for a senior

Demonstrate the scoping artefact itself: actions, objects, places, interval, plus the boundary you could not enumerate. Show how you separate evidence of use from the reach it is laid on top of.

for a principal

Weigh deliberate over-scoping against the cost of a second incident under the same root cause, and decide what the estate must be able to enumerate about any credential before it is issued at all.

The reflex after an exposure is to open your own logs and describe what the credential did. That number is almost always comforting and almost always the wrong number. ## Traffic describes you, entitlement describes them A credential's call history is a record of the jobs *you* wrote against it. A stranger holding the same value is constrained by exactly one thing: what the service on the other end will accept from that credential. The gap between those two sets is the part of the exposure nobody sees unless they go looking. A pipeline credential that spent a year issuing one kind of read may also be entitled to submit work, cancel it, list what exists, or change where results are delivered — none of which your jobs ever needed. So the scoping question is not "what did it do?" but "what would have been accepted from it?", asked of every place the value was accepted. ## Where the rights actually live - **The grant attached to the credential at the counterparty.** The direct list of actions it may perform. - **Anything inherited.** If the credential belongs to an account, and that account sits in a group or carries a role, the effective rights are the union, and the direct grant alone understates it. - **A second acceptor.** The same value configured in a second environment, a second service, or an older system nobody retired doubles the reach without appearing in any entitlement view you happen to open first. - **Listing and metadata rights.** The right to enumerate discloses what exists — names, volumes, structure — even where reading the contents is denied. Listing is disclosure, not a harmless subset of read. - **Reads that return more than data.** A response that carries another credential, a connection target or a delivery address extends the reach one hop past the service itself; that hop has to be scoped too. - **Rights that change the future.** Anything that lets the holder redirect results, register a new delivery address or leave behind a further means of access outlives the credential's own life, and belongs in the scope even though it looks like a configuration change rather than a data touch. ## What each source can establish | Source | Establishes | Where it stops | |---|---|---| | Your own call logs | What your jobs did with it | Says nothing about anyone else | | The counterparty's entitlement view | What would have been accepted | May omit rights inherited via a group | | Your inventory of where the value was configured | How many acceptors exist | Only as good as the inventory | | The counterparty's usage record | What was actually called | Bounded by their retention | Read across that table and the shape of the answer appears: the first and fourth rows are about *use*, the second and third about *reach*. Scope is built from reach, and use is evidence laid on top of it. ## Two traps worth naming The first is the **read-only fallacy**: "it could only read, so nothing happened." A read is a disclosure of everything readable, permanently, to whoever made it. If the credential could read a year of scoring inputs, the scope of the exposure is a year of scoring inputs, whether or not anyone did. The second is **reuse**. The same string typed into a second environment's configuration, or handed to a neighbouring team once, makes the entitlement view you are reading an understatement. This is why the inventory of where a value was configured is a scoping artefact and not paperwork; without it, the honest scope statement has to say "everywhere we know of, and we do not know how many places there are." ## What scoping produces The deliverable is a written statement in one shape: *a holder of this value could have performed these actions against these objects, in these places, for this interval*. It is what the declaration decision rests on, what the counterparty is told, and what drives the re-examination of anything the rights could have changed. It is also the honest place to record what you could not enumerate — an un-enumerable boundary is itself a finding, and the same gap will block the next response exactly as hard. Where the rights cannot be listed at all, scope to the container: the account the credential belongs to, and everything that account can do. Over-scoping costs you work; under-scoping costs you a second incident under the same root cause.

  • Your jobs only ever called one endpoint. Does that narrow what you tell the counterparty?
    No. You tell them the entitlement, because that is what a holder of the value could have exercised on their side. They are the party who can then check what was actually called, including calls that never came from you. Reporting your own usage pattern as the scope invites them to close the matter on evidence that was never about the attacker.
  • How do you scope a credential whose rights nobody can enumerate?
    Scope to the container it belongs to — the account, and everything that account can do — and state plainly that the boundary could not be enumerated. That is deliberately pessimistic, and it is defensible. Record the inability itself as a finding: it is the same gap that will block the next response, and it is cheaper to fix in daylight than at 2am.
  • Does the credential's age change the scope?
    Not the reach, but it changes what reach means in practice. A value in place for a year has had a year of objects pass under those rights, so a read right covers a year of material rather than a week's. Age also raises the odds of a second acceptor, since long-lived values accumulate copies and configurations nobody records.

saying these in an interview costs you the question

  • It only had read access, so nothing was at risk.
  • Our logs show the calls it made, so that is the blast radius.
  • An outsider would not know which service accepts it.
  • If nothing was modified, nothing was reached.
  • The service raised no alerts, so the scope is empty.