#10 Supply Chain Attack is placed at exactly one point in a path: the Trust Acceptance Event, the moment a third-party artifact becomes authoritative inside the target domain. Because #10 is a bridge cluster, that step also carries a boundary operator naming the context and the two responsibility spheres it crosses. Everything that happens after the trust is accepted classifies on its own merits — usually #7, sometimes #2 or #3 — and is a separate step.
The question this answers
Ask three analysts to write the attack path for a poisoned dependency and you will get three different answers. One puts #10 where the vendor was breached. One puts it where the malicious code ran. One sprinkles it across the whole chain because "the whole thing was a supply-chain attack". All three paths are unusable for comparison, which defeats the point of having a notation at all.
TLCTC resolves this with a placement rule and a boundary operator. Together they answer two questions that a bare cluster number cannot: at which moment did the trust relationship become causal, and between whose domains did it operate.
#10 is a bridge cluster, so it carries a boundary
The ten clusters split into two topologies. Clusters #1–#7 are internal: they describe an attacker acting against a component inside a domain. Clusters #8, #9 and #10 are bridge clusters: each one describes a crossing between domains — physical, human, and trust respectively.
A bridge step that does not say what it bridged is incomplete. So every bridge cluster step carries a boundary operator:
||[context][@Source→@Target]||
#10 ||[update][@Vendor→@Org]|| third-party update accepted by the org
#9 ||[human][@External→@Org]|| a person inside the org is manipulated
#8 ||[physical][@External→@Org]|| hardware reached physically
The operator is not an alternative to the cluster number and not a "more operational" view of it. It is part of the same step. Writing #10 alone leaves the reader to guess which boundary was crossed; writing the operator alone leaves out the cause.
R-SUPPLY: the Trust Acceptance Event
The placement rule is normative and short:
#10 Supply Chain Attack MUST be placed at the Trust Acceptance Event (TAE) — the moment the third-party trust link is honored and the trust artifact becomes authoritative inside the target domain.
Two consequences follow, and both are places analysts routinely go wrong.
The vendor's own compromise is not your #10. When an attacker breaches a software vendor, that breach is a path of its own inside the vendor's sphere — perhaps #9 → #4 → #1. It is not a supply-chain step, because nothing has yet been accepted anywhere. Your #10 begins when your systems honour the trust link.
The payload running is not your #10 either. Acceptance and execution are different moments with different generic vulnerabilities, so by Axiom VI they are different steps. Trust acceptance is #10; foreign executable content running is #7, recorded at the execution moment per R-EXEC.
A step is a genuine #10 if removing the third-party trust link would have broken the path at that point. If the attack still works with the trust relationship deleted, you are looking at something else — most often #1, #2 or #7 wearing a vendor's logo.
What the operator carries
The operator has three slots. The context names the kind of boundary; the two spheres name who was accountable on each side, written source first.
Contexts and spheres are Layer 2 of the framework — the reference registry — which means they are organisation-specific by design. The published reference registry defines seventeen contexts, and an organisation is expected to extend the list to match how its own responsibilities are actually divided:
| Context | Boundary it names |
|---|---|
human | Human decision / manipulation boundary (bridged by #9) |
physical | Physical domain boundary (bridged by #8) |
update | Third-party update / dependency boundary (bridged by #10) |
dev | Build / CI-CD responsibility boundary |
auth | Identity provider / authentication responsibility boundary |
api | API integration / service-to-service boundary |
cloud | Cloud shared responsibility boundary |
messaging, email | Messaging and email transport boundaries |
cdn, network, signaling, media | Delivery and network infrastructure boundaries |
browser, exploit, legal, admin | Rendering, delivery-infrastructure, jurisdictional and management-plane boundaries |
Spheres follow the same logic: @Org, @Vendor, @External, @Cloud, @MSP, @Partner and so on. The registry is a starting point, not a closed vocabulary — the useful question is always "who was accountable for this side of the boundary", and that answer differs between organisations.
Transit is not a supply-chain step
A party that merely relays an attack has accepted nothing. Carrying is not trusting, so a relay is marked with the transit operator ⇒, not with #10:
#9 ||[messaging][@Attacker⇒@SMSProvider→@Victim]||
the SMS provider relays the phishing link — transit, not #10
#10 ||[dev][@External→@Org]||
the org installs the package — trust accepted, so #10
The related trap is vendor code running on your own device. Under R-TRANSIT-3, a browser or messaging client on the victim's phone is not a transit party — it is the attack surface, and it classifies by the role of the flawed component under R-ROLE, normally #3.
Worked examples
SolarWinds / SUNBURST
The published Layer 3 record for this incident is four steps. Note where #10 starts and stops:
#10 ||[update][@Vendor→@Org]|| →[Δt=instant] #7 + [DRE: C] →[Δt=~14d] #4 →[Δt=~2h] #1 + [DRE: C]
The signed Orion update carrying the backdoor is accepted and installed: that is the Trust Acceptance Event, and it is the only #10 in the path. The DLL was digitally signed and passed every trust check, which is precisely why the step is a supply-chain step rather than an exploitation one — nothing was broken, the trust link was honoured exactly as designed.
Fourteen days later the backdoor executes: separate step, #7. Forged SAML tokens follow: #4. Then abuse of legitimate cloud functionality with those tokens: #1. The compromise of SolarWinds' own build system does not appear in this path at all — it belongs to a path inside @Vendor.
The two [DRE: C] tags repay a closer look, because their placement is easy to get wrong. The first sits on #7, not on #4: host profiling went out over the C2 channel and the token-signing certificate was taken during that step, and Axiom X puts the acquisition of credential material on the enabling cluster. The second sits on #1, where mail is actually read through the designed APIs.
#4 carries no DRE at all. Authenticating with a forged token discloses nothing, alters nothing and denies nothing — it opens a door. Tagging it with C would count the same exfiltration twice and would judge the step by what the attacker eventually obtained rather than by what the step did, which is the consequence-side form of the mistake Axiom III exists to prevent.
A poisoned package
A typosquatted dependency is published, a developer installs it, and its post-install script runs:
#10 ||[dev][@External→@Org]|| → #7
Publishing the package to the registry is the attacker acting in their own sphere; it creates no step against the target. Installation is the TAE. Execution of the install script is #7 with fec_executed: true, per R-EXEC.
A compromised update channel
Where the vendor is breached first, two paths exist and only one is yours:
inside @Vendor: #2 → #4 → #1 (the vendor's own incident)
inside @Org: #10 ||[update][@Vendor→@Org]|| → #7
If instead the update is tampered with in flight rather than at the vendor, the cause is different and so is the path: an on-path attacker is #5, and there is no #10, because no trust artifact from the vendor was subverted — the channel was.
Four ways this goes wrong
- #10 as an outcome bucket. "It was a supply-chain attack" describes a story, not a step. Only the trust acceptance is #10.
- #10 spread across the chain. One TAE, one #10. If a second genuinely occurs — a compromised dependency inside a compromised vendor product — it is a second, separately justified step.
- #10 without a boundary operator. A bridge step that does not name what it bridged cannot be checked, aggregated, or argued with.
- Vendor breach filed as your #10. It is a path in their sphere. Yours starts at acceptance.
Recording it in Layer 3
The notation has a machine-readable twin. In the Layer 3 attack-path schema, the boundary is a topology_boundary object on the step, and the falsifiability test belongs in the step notes:
{
"step_id": "s1-supply-chain",
"cluster": "#10",
"topology_boundary": {
"context": "update",
"source_sphere": "@Vendor",
"target_sphere": "@Org"
},
"delta_t_to_next": "instant",
"notes": "Trust Acceptance Event: signed vendor update accepted and installed.
Falsifiability test: removing the third-party trust link (not accepting
the update) would have prevented this step."
}
Records validate against the Layer 3 schema, and the worked example above is published in full as solarwinds-2020.json.
The definitions this rests on
Quoted verbatim from the canonical dictionary, tlctc-framework.v2.5.json, which is the normative source for cluster wording:
| Cluster | Definition | Generic vulnerability |
|---|---|---|
| #10 Supply Chain Attack | An attacker compromises systems by subverting third-party software, hardware, services, or update mechanisms that the target trusts and integrates, so that the subverted artifact is accepted as authoritative inside the target's domain. | Trust in third-party components and update channels can be subverted. |
| #7 Malware | Recorded at the execution moment, per R-EXEC — the step where foreign executable content actually runs. | |
| #5 Man in the Middle | The cause when the communication path itself is subverted, rather than a trusted artifact. | |
R-SUPPLY, R-EXEC, R-ROLE and R-TRANSIT-3 are part of the nineteen-rule registry in the core paper; the full notation grammar is in §11 of the practitioner handbook. Boundary contexts and responsibility spheres are Layer 2 and are meant to be adapted to your organisation.
Why the placement rule earns its keep
A rule that forces one supply-chain step per accepted artifact makes paths comparable across incidents and across organisations — which is the whole purpose of a taxonomy that claims to be non-overlapping. It also puts the control question in the right place. Controls that would have broken the SolarWinds path at step one are provenance controls: artifact signing you actually verify, SBOM checks, staged rollout, build attestation. Controls aimed at the malware are aimed at step two, and by then the trust decision has already been made.
That is the practical payoff of insisting the notation name a moment rather than a mood.