Skip to content

Commit 7b07be6

Browse files
committed
docs: rewrite supply chain demo README
Replace defensive comparisons with a table showing what each attack phase hits and the specific component that blocks it (FsSandbox, NetworkPolicy). Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent 860b6a1 commit 7b07be6

1 file changed

Lines changed: 32 additions & 43 deletions

File tree

demos/supply-chain/README.md

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,43 @@
11
# Supply Chain Attack Demo — Mini Shai-Hulud
22

3-
A safe, educational demonstration of a supply chain attack modeled on
3+
A safe, educational reproduction of the
44
[Mini Shai-Hulud](https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html)
5-
(TeamPCP, May 2026), showing how Hyperlight micro-VM isolation contains it
6-
**even when the guest has realistic capabilities**.
5+
supply chain attack (TeamPCP, May 2026) running inside a Hyperlight micro-VM.
76

87
## Background
98

109
Mini Shai-Hulud compromised 500+ packages across npm, PyPI, and PHP — including
1110
TanStack, Mistral AI, Guardrails AI, and AntV — affecting 518M+ cumulative
12-
downloads. The attack used typosquatted/hijacked packages to:
13-
14-
1. **Steal credentials** — SSH keys, AWS creds, `.env` files, 80+ env vars
15-
2. **Probe cloud metadata** — AWS IMDS, Azure IMDS, GCP metadata (169.254.169.254)
16-
3. **Exfiltrate data** — triple-redundant C2 (custom domain, Session Protocol, GitHub dead drops)
17-
4. **Install persistence** — Claude Code `SessionStart` hooks, VS Code `runOn`, LaunchAgents
18-
5. **Self-propagate** — used stolen npm tokens to poison other packages
19-
20-
## What this demo does
21-
22-
A fake typosquatted package (`reqeusts` instead of `requests`) simulates the
23-
attack payload. A victim application imports it, triggering the malicious code.
24-
The victim app also does legitimate work: reads input from the workspace,
25-
fetches data from `example.com`, and writes output.
26-
27-
**Bare metal** — the attack succeeds: secrets stolen, exfiltrated, persistence
28-
installed. Legitimate work also succeeds.
29-
30-
**Hyperlight sandbox (scoped)** — the guest has real capabilities (`--mount`
31-
for directory access, `--net-allow example.com` for network). Legitimate work
32-
succeeds, but every malicious action is blocked by Hyperlight's security model:
33-
34-
- **Credential theft → BLOCKED**`~/.ssh/id_rsa`, `~/.aws/credentials`, etc.
35-
are outside the mounted directory. The guest has filesystem access, but only
36-
to the scoped directory (no HOME, no `/etc/passwd`).
37-
- **Environment variables → NOT SET** — host environment is never forwarded to
38-
the guest. `AWS_ACCESS_KEY_ID`, `GITHUB_TOKEN`, etc. are absent.
39-
- **C2 exfiltration → BLOCKED** — loopback addresses (127.0.0.0/8) are
40-
**always denied** regardless of network policy. The C2 server at
41-
`127.0.0.1:8080` is unreachable.
42-
- **Cloud metadata → BLOCKED** — link-local addresses (169.254.0.0/16) are
43-
**always denied**. AWS IMDS, Azure IMDS, and GCP metadata at 169.254.169.254
44-
are all blocked — a hardcoded safety net, not a user-configurable policy.
45-
- **Persistence → BLOCKED** — host dotfiles (`~/.claude/settings.json`,
46-
`~/.bashrc`) are not mounted. The guest's ramfs is destroyed on exit.
47-
48-
This is **active defense**, not just absence of resources. An empty Docker
49-
container blocks the same attacks, but only because it has nothing to attack.
50-
Hyperlight blocks them because its network policy engine and filesystem sandbox
51-
enforce scoped access even when capabilities are granted.
11+
downloads. The payload:
12+
13+
1. Steals credentials — SSH keys, AWS creds, `.env` files, 80+ env vars
14+
2. Probes cloud metadata — AWS IMDS, Azure IMDS, GCP metadata (169.254.169.254)
15+
3. Exfiltrates to triple-redundant C2 (custom domain, Session Protocol, GitHub dead drops)
16+
4. Installs persistence — Claude Code `SessionStart` hooks, VS Code `runOn`, LaunchAgents
17+
5. Self-propagates using stolen npm/PyPI publish tokens
18+
19+
## The demo
20+
21+
A typosquatted package (`reqeusts` instead of `requests`) carries a simulated
22+
version of this payload. A victim app imports it — triggering the stealer — and
23+
then does legitimate work: reads input from the workspace, fetches data from
24+
`example.com`, writes output.
25+
26+
Two runs, same code:
27+
28+
**Bare metal** — credentials stolen, C2 exfiltration sent, persistence
29+
installed, cloud metadata reached. Legitimate work also succeeds.
30+
31+
**Hyperlight micro-VM** (`--mount ./guest --net-allow example.com`) —
32+
legitimate work succeeds, every attack phase is blocked:
33+
34+
| Phase | What happens | Why |
35+
|---|---|---|
36+
| Credential theft | `~/.ssh/id_rsa`, `~/.aws/credentials` → BLOCKED | `FsSandbox` scopes access to the mounted directory. No HOME, no `/etc/passwd`. |
37+
| Env var harvesting | `AWS_ACCESS_KEY_ID`, `GITHUB_TOKEN` → NOT SET | Host environment is never forwarded into the guest. |
38+
| Cloud metadata | 169.254.169.254 → BLOCKED | `NetworkPolicy` hardcodes a link-local (169.254.0.0/16) deny. |
39+
| C2 exfiltration | 127.0.0.1:8080 → BLOCKED | `NetworkPolicy` hardcodes a loopback (127.0.0.0/8) deny. |
40+
| Persistence | `~/.claude/settings.json`, `~/.bashrc` → BLOCKED | Host dotfiles are outside the mount. Guest ramfs is destroyed on exit. |
5241

5342
## Running the demo
5443

0 commit comments

Comments
 (0)