A contractor self-merged a two-line change to the nightly job that writes your production ledger. Which controls failed?
answer
- the actor was authorised
- author and approver were the same person
- the job already held the authority
- who recomputes the answer independently
- authorship is not proof of identity
basics
~20 sSeparation of duties failed on a privileged path: one person authored and approved a change to code that holds production ledger credentials. Independent review of that path, a narrower job identity, and an out-of-band reconciliation are the missing controls.
solid answer
~50 sThree failures, in order of importance. First, separation of duties: on a path whose code can move money, author and approver must be different people, and the merge shows they were the same. Second, blast radius: the job holds standing write access to the ledger, so any change to it inherits that authority — the change was two lines because it did not need to be more. Third, detection: nothing outside the job recomputes what the job produced, so a wrong ledger stays wrong until a customer notices. Note what did *not* fail. Multi-factor authentication, signed commits and identity checks all worked exactly as designed; the actor was authorised. So did the build and any provenance attached to it — it truthfully records that this artifact was built from this source. Insider risk on an authorised path is answered by separation of duties, least privilege and independent reconciliation, not by stronger authentication.
go deeper
Know the core idea: the person who writes a change to sensitive code should not be the person who approves it, and logging in successfully proves identity rather than good intent.
Explain why authentication, signing and provenance are all satisfied by an authorised insider, and what separation of duties and least-privilege job identities add that they cannot.
Demonstrate you would scope the control. Define the privileged path list by what the code can reach, add an independent recomputation as detection, and keep a loud break-glass route so the rule survives contact with an incident.
Own the organisational side: who maintains the privileged path list, how contractor access is scoped and expired, and how you answer an auditor when your only account of who acted is a commit author field.
## Read the scenario precisely A contractor with legitimate commit rights changed two lines in a batch job and approved their own change. Nothing was broken into. That single fact determines which half of your control set is relevant and which half is irrelevant, and an interviewer is listening for whether you can tell them apart. ## The controls that were never in play Every authentication and attribution control confirms that the actor is who they claim to be. The contractor *is* who they claim to be. Multi-factor authentication passed honestly. A signed commit, if required, would carry a valid signature over hostile content, because signing answers who vouches for a change and not what the change does. If the pipeline produced a provenance attestation, it is accurate: this artifact was built by this builder from this repository at this commit. Provenance closes the gap between reviewed source and shipped artifact; here the source itself carries the change, so there is no gap to close. Reproducible builds reproduce it. Dependency scanning has nothing to say, because no dependency changed. Saying this out loud is most of a good answer. Candidates who reach for stronger authentication have not noticed that the attack satisfies every authentication precondition by construction. ## Failure one: separation of duties on a privileged path Self-merge means the only content-inspecting control in the system was removed by the person the control exists to check. The requirement is not that every change needs two people — that rule collapses under its own weight — but that changes to a defined set of high-consequence paths do. Define the set by what the code can reach: anything with production write credentials, anything that moves money, anything that issues or handles keys, anything that produces a released artifact. For those paths the approver must be someone other than the author, and ideally someone from the owning team rather than whoever is available. The corollary that gets forgotten: emergency and break-glass merges must be *possible*, because a rule with no escape hatch gets routed around permanently. They should simply be loud — recorded, alerted on, and reviewed the next working day. ## Failure two: blast radius The reason two lines were enough is that the job already had the authority. It runs nightly with standing write access to the ledger, so whoever controls its code controls the ledger. Reducing that is often more tractable than reducing who can edit the code: - **Narrow the identity.** The job should hold the smallest write scope that its function requires, short-lived rather than standing, and issued at run time rather than stored. - **Constrain by invariant.** A reconciliation job that can only propose entries which a separate service validates against invariants — totals balance, no entry outside a bounded range, no entry against a closed period — turns an arbitrary write into a constrained one. - **Split the change from the run.** Deploying a change and letting it touch production are two events. An approval gate on the production run, held by a different group than the code owners, gives you a second human in the loop even when the code path had only one. ## Failure three: no independent detection If the only system that knows what the ledger should say is the system that writes it, you have no detection at all. The compensating control is an independent recomputation — a separate reconciliation against source records, run by a different service with read-only access — plus alerting on merges into the privileged path list and on runs that touch unusual volumes or accounts. These are detective controls, and they matter precisely because the preventive ones can be bypassed by an authorised person. ## The evidence problem Afterwards, the commit history is your account of what happened, and it is only as strong as your confidence in the identity behind it. A malicious contractor and a stolen contractor session produce identical history. If your investigation and your response — is this a person you dismiss, or an account you disable and a credential you rotate — depend on which one it was, then commit authorship alone cannot settle it. You need corroboration from a different system: session and device records, network origin, the timing against the person's working pattern, and where the stakes justify it, an out-of-band conversation with the human. Build that expectation before you need it; reconstructing it during an incident is how organisations end up accusing the wrong person. ## Contractor lifecycle The last thread is access shape. Contractor access should be scoped to the repositories the engagement requires, time-bounded to the engagement, and reviewed when it changes. Standing broad commit rights that outlive the work is a common finding, and it converts an ordinary staffing event into a supply chain exposure. ## What a strong answer sounds like Name the actor position and what it neutralises; name separation of duties on a defined privileged path rather than everywhere; reduce the job's standing authority; add an independent recomputation as the detective layer; and be explicit that provenance, signing and multi-factor address a different threat entirely.
- The account had multi-factor authentication and the commit was signed. Does either help here?Not for prevention. Both establish that the actor is who they claim, which the attack already assumes. They help afterwards, for attribution, and even then only if you are confident the session was not stolen — a signed commit from a hijacked session is a valid signature over someone else's actions. Treat them as evidence-quality controls, not as barriers to an authorised insider.
- Your build emits a provenance attestation for every artifact. Why does it not cover this?Provenance states how an artifact came to be — which builder, which source repository, which commit — and all of that is true here. The build honestly compiled a repository whose source had been changed by someone entitled to change it. Provenance closes tampering between source and artifact; authorisation of the source content is a different control, which is review and separation of duties.
- How would you decide which paths deserve mandatory independent review, without demanding it everywhere?Rank by what the code can reach at run time, not by how important the team feels: production write credentials, money movement, key issuance and handling, and anything that produces a released artifact. That list is usually far shorter than people expect. Everything else gets self-merge with detective controls, which keeps the mandatory rule credible enough to survive.
- Six months later you must prove to an auditor what that change did. What evidence do you want to have kept?The merged diff and who approved it, the deployment record linking that commit to the run that touched the ledger, the job's own action log with the identity it used, and the independent reconciliation output for that night. Together those let you bound the impact. Commit authorship alone answers who typed it, and only if the session was genuinely theirs.
saying these in an interview costs you the question
- Says multi-factor or signed commits would have prevented it
- Claims provenance or a build attestation covers a hostile source change
- Treats it purely as an HR or hiring-trust problem
- Proposes mandatory two-person review on every repository
- Assumes commit authorship proves which human acted