skip to content

On a shared CI estate, each project's build identity can read and queue sibling projects' pipelines. Where do you draw the isolation boundary?

level: principalimportance: nice to knowfreq 26%

answer

  1. shared tenant, shared identity reach
  2. queue rights, not just read rights
  3. blast radius over org chart
  4. deny by default for new projects first

basics

~20 s

Draw it by reachable blast radius, not by org chart: identities that can reach production or another team's source get a real boundary. Start deny-by-default for new projects, then inventory and expire existing cross-project grants.

solid answer

~50 s

First I name what is actually at stake: cross-project read is another team's source-code IP walking out through anyone who can land a pipeline change in a low-privilege project, and cross-project queue is a path into their release definition, which is a path to their production. Then I pick the boundary by what an identity can reach if the code running under it is hostile, not by who reports to whom — two teams that already deploy the same service need no wall, while the team that can queue the payments release does. Full tenant separation is the strongest and most expensive option, so I usually take the middle path: deny cross-project grants by default for every new project on day one, inventory the existing ones, and expire the ones touching production paths first with a named owner and a renewal date. Detection stays regardless, because exceptions accumulate.

go deeper

for a junior

Know that on a shared CI platform a project's build identity often has rights beyond its own project by default, and that reading another team's repository is a genuine loss rather than an inconvenience.

for a middle

Be able to enumerate the cross-project verbs — read, queue, download artifacts — and say what each one gives an attacker; queueing someone's release pipeline runs with their credentials, not yours.

for a senior

Show a migration you could actually run: deny-by-default for new projects, an inventory ranked by reach, and a real replacement for cross-project reads such as publishing a versioned artifact.

for a principal

Own the boundary decision and its price: isolate by reachable blast radius rather than reporting lines, fund the exception process with owners and expiry, and be able to state the residual risk to a customer or auditor.

## The situation On a shared CI platform, each project typically gets a build identity, and the platform's defaults often let that identity read — and sometimes queue — pipelines in sibling projects belonging to the same organisation or collection. It was configured that way years ago so cross-team builds would "just work". The result is that an engineer who can land a pipeline change in the least important project runs code as an identity that can read another team's repository and start another team's release. ## Name the asset before choosing a boundary This is not a customer-data breach scenario, and pretending it is leads to the wrong control. What is at risk: - **Source-code IP.** Cross-project *read* is exfiltration by an authenticated low-privilege insider or by anything executing in their pipeline. - **A path to production.** Cross-project *queue* means starting someone else's release definition, which will happily run with *their* credentials — you did not need to steal a production key, you borrowed the pipeline that already has one. - **Audit truth.** Actions attributed to a build identity are hard to trace back to the person who caused them, so the log says "project A's build service" and not who made it happen. ## The options and what they cost 1. **Full tenant isolation** — a separate CI organisation or instance per team. Strongest and most expensive: duplicated runner fleets, no shared pipeline templates, per-team administration, and genuinely cross-team builds become awkward. Reserve it for the handful of estates where the reach is unacceptable and the teams are already independent. 2. **Deny cross-project grants by default, allow explicitly** — the usual middle path. Works if the platform can express per-project grants at all; the risk is drifting into hundreds of one-off exceptions nobody can reason about. 3. **Move the crown jewels out** — keep the shared tenant, but put release definitions and their credentials in a project no build identity can queue, and promote into it via an event a human or a policy approves. Often the cheapest meaningful win. 4. **Detective only** — audit grants, alert on cross-project queues and first-time reads. Cheap, honest about what it is, and never sufficient on its own. ## The decision rule Isolate by what an identity can **reach** if the code running under it is hostile, not by the org chart. Two teams whose pipelines already deploy the same service share a blast radius; a wall between them buys nothing and costs real friction. A low-traffic internal tool whose build identity can queue the payments release is the case that matters, regardless of who its team reports to. A second rule: prefer a few coarse boundaries you can explain to many fine grants you cannot. If you cannot say in one sentence what a boundary protects and from whom, it will not survive its first exception request. ## Getting an estate to actually adopt it - **Default-deny for new projects first.** It has no migration cost and it stops the problem growing while you work on the backlog. - **Inventory, then rank by reach.** Which identities can queue something that deploys? Those go first. Which can only read a repository that is public internally anyway? Those go last. - **Expire, do not just revoke.** Each remaining grant gets a named owner and a renewal date, so the default outcome of inaction is removal rather than permanence. - **Give the legitimate case a real answer.** Most cross-project reads exist to consume a shared library. Replace them by publishing a versioned artifact both projects can pull — which is better anyway, because you then have a record of what was consumed. - **Measure one number.** "Projects whose build identity can reach a production release path" is a metric a leadership audience understands and you can drive down over quarters. ## What you tell an auditor or a customer Describe the boundary, the exception process and the detection that backs it. "We trust our engineers" is not a control, and neither is a wall with an unmanaged list of holes in it. Be willing to state the residual risk plainly: what a hostile insider in the least protected project could still reach, and what would tell you it happened.

  • A team says they need cross-project read to consume a shared library. What do you offer instead?
    Publish the library as a versioned artifact both projects can pull. The dependency becomes an immutable published thing rather than a standing grant on someone else's source, and you gain a record of exactly which version was consumed by whom.
  • How do you sequence this across two hundred existing projects?
    Default-deny for new projects immediately, since that costs nothing. Then inventory existing grants, rank them by what they can reach, and expire the ones touching production paths first with a named owner and a date. The long tail moves through renewal, not a flag day.
  • What do you keep even after the boundary is in place?
    Detection. Alert when a build identity queues outside its own project or reads a repository it has never read before. Preventive boundaries erode as exceptions accumulate, so the audit trail is what tells you whether the boundary still holds.

saying these in an interview costs you the question

  • Proposes a separate CI instance per team without costing it
  • Assumes cross-project read access is harmless
  • Draws the boundary on the org chart rather than reachability
  • Relies on trusting internal engineers as the control

context