Skip to content

Commit eabb995

Browse files
kamiazyaclaude
andauthored
feat: implement multi-layered supply chain attack defense (#617)
* feat: implement multi-layered supply chain attack defense Implement comprehensive protection against npm supply chain attacks (such as Shai-Hulud 2.0) using a three-layer defense strategy. Layer 1: New Package Release Delay - Add minimumReleaseAge (48 hours) to pnpm-workspace.yaml - Blocks installation of recently published packages - Provides time buffer for community to detect malicious updates Layer 2: Install Script Prevention - Configure ignore-scripts=true in .npmrc - Prevents execution of preinstall/postinstall scripts - Includes whitelist support via onlyBuiltDependencies (currently unused) Layer 3: Continuous Vulnerability Scanning - Add OSV-Scanner workflow for dependency scanning - Integrate security scan into CI/CD pipeline - Fail builds on detected vulnerabilities Documentation: - Add comprehensive supply chain protection section to SECURITY.md - Document configuration, trade-offs, and compromise detection - Include references to defense resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: pin OSV-Scanner action to specific commit SHA Pin google/osv-scanner-action to v2.3.0 (b77c075) instead of using floating ref @main for improved security and reproducibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: correct pnpm whitelist configuration key Change onlyBuiltDependencies to only-built-dependencies (kebab-case) to match pnpm's actual configuration format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: correct typo in malicious repo search example Change "Sha1-Hulud" to "Shai-Hulud" to match the actual attack name. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add inline comment clarifying minimumReleaseAge unit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: add changeset for supply chain defense 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 25d49ee commit eabb995

File tree

6 files changed

+153
-0
lines changed

6 files changed

+153
-0
lines changed

.changeset/supply-chain-defense.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"web-csv-toolbox": patch
3+
---
4+
5+
## Supply Chain Attack Defense
6+
7+
Added multi-layered protection against npm supply chain attacks (such as Shai-Hulud 2.0).
8+
9+
### Defense Layers
10+
11+
1. **New Package Release Delay**: Blocks packages published within 48 hours via `minimumReleaseAge` setting
12+
2. **Install Script Prevention**: Disables preinstall/postinstall scripts via `ignore-scripts=true`
13+
3. **Continuous Vulnerability Scanning**: Integrates OSV-Scanner into CI/CD pipeline
14+
15+
These changes only affect the development environment and CI/CD configuration. No changes to library code.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Security Scan
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
osv-scanner:
8+
name: Scan dependencies for vulnerabilities
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
security-events: write
13+
steps:
14+
- name: Checkout Repo
15+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
16+
17+
- name: Run OSV-Scanner
18+
uses: google/osv-scanner-action/osv-scanner-action@b77c075a1235514558f0eb88dbd31e22c45e0cd2 # v2.3.0
19+
with:
20+
scan-args: |-
21+
--lockfile=pnpm-lock.yaml
22+
--format=json
23+
--output=osv-results.json
24+
continue-on-error: true
25+
26+
- name: Upload OSV-Scanner results
27+
uses: github/codeql-action/upload-sarif@v3
28+
if: always()
29+
with:
30+
sarif_file: osv-results.json
31+
continue-on-error: true
32+
33+
- name: Check for vulnerabilities
34+
run: |
35+
if [ -f osv-results.json ]; then
36+
echo "OSV-Scanner results:"
37+
cat osv-results.json
38+
# Fail the job if vulnerabilities are found
39+
if grep -q '"vulns"' osv-results.json; then
40+
echo "⚠️ Vulnerabilities detected in dependencies"
41+
exit 1
42+
fi
43+
fi

.github/workflows/main.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ permissions: read-all
1313

1414
jobs:
1515

16+
security_scan:
17+
name: Security Scan
18+
uses: ./.github/workflows/.security-scan.yaml
19+
permissions:
20+
contents: read
21+
security-events: write
22+
1623
static_tests:
1724
name: Static Tests
1825
uses: ./.github/workflows/.static-tests.yaml
@@ -26,6 +33,7 @@ jobs:
2633
secrets:
2734
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
2835
needs:
36+
- security_scan
2937
- static_tests
3038

3139
dynamic_tests:
@@ -62,6 +70,7 @@ jobs:
6270
id-token: write
6371
pages: write
6472
needs:
73+
- security_scan
6574
- static_tests
6675
- build
6776
- dynamic_tests

.npmrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
ignore-workspace-root-check=true
2+
3+
# Prevent execution of install scripts to mitigate malicious code execution
4+
# This blocks preinstall/postinstall scripts from all packages
5+
ignore-scripts=true
6+
7+
# Whitelist specific packages that require build scripts
8+
# Add packages here that legitimately need to run scripts (e.g., native modules)
9+
# Currently this project builds WASM from source, which doesn't require npm scripts
10+
# If you need to allow scripts for specific packages, use:
11+
# only-built-dependencies[]=package-name

SECURITY.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,78 @@ If you discover a security vulnerability in web-csv-toolbox, please report it pr
2424

2525
We provide security updates for the latest minor version only.
2626

27+
## Supply Chain Attack Protection
28+
29+
This project implements a multi-layered defense approach to protect against npm supply chain attacks (such as Shai-Hulud 2.0 and similar threats).
30+
31+
### Defense Layers
32+
33+
#### Layer 1: New Package Release Delay
34+
35+
**Configuration:** `pnpm-workspace.yaml`
36+
37+
```yaml
38+
minimumReleaseAge: 2880 # 48 hours
39+
```
40+
41+
Blocks installation of packages published within 48 hours. This time buffer allows the community to detect and report malicious package updates before they reach our dependencies.
42+
43+
**Trade-offs:**
44+
- ✅ Prevents zero-day supply chain attacks
45+
- ⚠️ Delays access to legitimate bug fixes and security patches
46+
47+
**When to adjust:** If you need to install a newly published package immediately, temporarily comment out this setting, then re-enable it after installation.
48+
49+
#### Layer 2: Install Script Prevention
50+
51+
**Configuration:** `.npmrc`
52+
53+
```
54+
ignore-scripts=true
55+
```
56+
57+
Prevents execution of `preinstall`, `postinstall`, and `install` scripts from all packages. Even if a compromised package is installed, its malicious code cannot execute during installation.
58+
59+
**Whitelist for native modules (if needed):**
60+
```
61+
only-built-dependencies[]=package-name
62+
```
63+
64+
**Current status:** This project requires no install scripts. WASM builds use `wasm-pack` which runs manually via `pnpm build:wasm`.
65+
66+
#### Layer 3: Continuous Vulnerability Scanning
67+
68+
**Configuration:** `.github/workflows/.security-scan.yaml`
69+
70+
Uses Google's OSV-Scanner to continuously scan dependencies for known vulnerabilities, aggregating data from multiple sources (GitHub Advisory Database, NVD, etc.).
71+
72+
The CI pipeline fails if vulnerabilities are detected, preventing vulnerable code from being merged or deployed.
73+
74+
### Checking for Compromise
75+
76+
If you suspect your local environment may be compromised by supply chain attacks, check for these indicators:
77+
78+
**1. Search for malicious GitHub repositories:**
79+
```bash
80+
gh search repos "Shai-Hulud: The Second Coming"
81+
```
82+
83+
**2. Check for malicious workflow files:**
84+
```bash
85+
find . -name "discussion.yaml" -path "*/.github/workflows/*"
86+
```
87+
88+
**3. Search for known payload files:**
89+
```bash
90+
find . -name "setup_bun.js" -o -name "bun_environment.js" -o -name "cloud.json"
91+
```
92+
93+
### Additional Resources
94+
95+
- [npm Supply Chain Attack Defense Guide](https://zenn.dev/hand_dot/articles/04542a91bc432e) (Japanese)
96+
- [OSV-Scanner Documentation](https://google.github.io/osv-scanner/)
97+
- [pnpm Security Features](https://pnpm.io/feature-comparison#security-features)
98+
2799
## Secure Usage Guidelines
28100

29101
⚠️ **Critical for Production Applications**

pnpm-workspace.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ packages:
44
- examples/*
55
- '!examples/deno'
66

7+
# Supply chain attack mitigation: Block packages published within 48 hours
8+
# This provides a time buffer to detect malicious package updates before they are installed
9+
minimumReleaseAge: 2880 # 48 hours in minutes
10+
711
catalogs:
812
default:
913
# Build Tools

0 commit comments

Comments
 (0)