Three Indirect-Trust Vectors In Three Weeks. The Attacker's New Doctrine Is The Artifact Layer Nobody Audits.
- Patrick Duggan
- 6 minutes ago
- 4 min read
Over the last three weeks DugganUSA's IOC index has carried receipts on three independent supply-chain compromises that, on the surface, look like three different stories. The Laravel-Lang credential stealer on May 22. The Megalodon mass GitHub Actions workflow poisoning on May 18. The Ghost CMS remote code execution disclosed earlier in May and re-surfaced this weekend with a publicly available proof-of-concept exploit. Three packaging ecosystems, three different attacker clusters, three different payload architectures. One shared structural shape that the next ten campaigns will also use, because it has crossed the confidence threshold inside the criminal market.
The shape
The shape is that the attacker compromises an indirect-trust artifact layer rather than the primary source code. The defender's eyes are on the primary artifact. The compromise happens at an adjacent layer that the primary artifact points to, references, or pulls in at execution time, and that adjacent layer is not audited between releases because nobody has built it into their review pipeline.
Laravel-Lang was tag-pointer compromise. The official PHP package repositories on GitHub were never modified; the attacker built malicious forks and rewrote over 700 historical version tags inside the official repos to point at SHAs that exist only in the malicious forks. Composer's lockfile records the SHA. The defender reviewing the lockfile diff sees a SHA change and assumes a maintainer published a new version. The trick lives in the addressing layer between the tag and the commit, which is not the layer the defender is watching.
Megalodon was workflow-file compromise. The attacker pushed 5,718 forged-identity commits directly to the default branch of 5,561 repositories using throwaway GitHub accounts and bot-impersonator email TLDs. The malicious code lives in .github/workflows/, which is a path most maintainers do not audit between releases because it is the "infrastructure" directory, the one that should not change much, the one that gets a glance instead of a read. The first time the payload runs is the next time CI fires, which on a healthy project is hours away. The trick lives in the workflow directory, which is not the directory the defender is watching.
Ghost CMS is theme compromise. The remote code execution disclosed as CVE-2026-29053 affects roughly one hundred thousand Ghost installations running versions 0.7.2 through 6.19.0. The attack vector is a malicious theme upload that turns the theme's template-rendering engine into a server-side JavaScript execution primitive. The defender reviewing a Ghost site sees the published content; the malicious code lives in the theme layer that the rendering pipeline pulls in at request time. The trick lives in the templating layer, which is not the layer the defender is watching.
Three is doctrine, not coincidence
When one attacker discovers a structural primitive, that is a probe. When three independent attacker clusters deploy the same structural primitive in different ecosystems within three weeks of each other, that is doctrine crossing into operational use. The marketplace insight that ties the three campaigns together is not the specific delivery vector; it is the realization that defender review pipelines have been built around the primary source-code artifact, and any execution-relevant artifact that lives one layer adjacent to that primary artifact is, by default, unaudited.
This is the same structural pattern as the supply-chain compromises of 2023 and 2024 that targeted post-build artifact distribution rather than source-code commits. The earlier generation hit npm postinstall scripts, PyPI metadata fields, Docker manifest tags. The current generation hits Git tag pointers, GitHub workflow files, and CMS theme directories. The vector changes; the doctrine — compromise the adjacent layer rather than the primary artifact — persists and refines.
The defender primitive that catches all three
The defensive correction is the same across all three vectors. Pin to behavior, not destination. Treat any execution-relevant artifact that lives adjacent to the primary source code as a first-class review target. Audit Git tag-to-commit reachability before install. Require explicit code-owner approval on every modification to CI workflow directories regardless of the modifier's repository privileges. Sandbox theme rendering and template execution paths with the same skepticism applied to any other untrusted code input. Inspect the egress, not the perimeter, on every system that loads adjacent-layer artifacts at runtime.
DugganUSA's IOC index now carries records on all three campaigns with structural-pattern tagging. Customers consuming the STIX feed have the specific indicators. What we are doing with this post is naming the shape, because the shape is the part of the receipt that travels. The next campaign will target a different ecosystem with a different ecosystem-specific name, and the readers who learned the shape today will recognize it before the campaign is named publicly.
The attacker's new doctrine is the artifact layer nobody audits. The defender's new operating assumption should be that every artifact layer is being audited by someone, and the question is whether that someone is the defender or the attacker. The blog timestamps are the receipts. The shape is the part that matters.
How do AI models see YOUR brand?
AIPM has audited 250+ domains. 15 seconds. Free while still in beta.
