The compromise of the Axios npm package through social engineering highlights a critical vulnerability in the software supply chain: the security of your dependencies is only as strong as the people who maintain them. Attackers from UNC1069 used fake Slack and Microsoft Teams environments to deploy WAVESHAPER malware, compromising a package downloaded nearly 100 million times weekly. This breach wasn't due to a code vulnerability—it was a result of a conversation that went wrong.
If your organization relies on open-source packages, you need a maintainer security program. Here's how to build one.
The Problem: Social Engineering vs. Code Exploits
Traditional supply chain security often focuses on scanning dependencies for known vulnerabilities. However, this approach overlooks a primary attack vector: compromising the humans who publish packages. A single successful phishing attempt against a maintainer with npm publish rights can give attackers direct access to millions of downstream installations.
Your current dependency scanning won't catch this. By the time malicious code appears in a package version, it's already distributed through your CI/CD pipeline.
Preparing for Implementation
Access and Inventory:
- Compile a complete list of direct and transitive dependencies (use
npm list --alloryarn list --all). - Gather maintainer contact information for your top 20 dependencies by usage.
- Secure your organization's npm registry credentials and publish permissions.
- Verify the current MFA status for all accounts with package publish rights.
Tooling:
- Ensure SBOM generation capability (use
syftorcdxgen). - Use package provenance verification tools (
npm audit signaturesin npm 8.15+). - Implement dependency monitoring (Dependabot, Renovate, or Snyk).
- Deploy endpoint detection and response (EDR) on developer machines.
Policies:
- Define trust tiers for dependencies.
- Establish an approval workflow for new dependencies.
- Develop an incident response plan for compromised packages.
Step-by-Step Implementation
Phase 1: Secure Your Own Publishing (Week 1)
Enable npm provenance for packages you publish:
npm publish --provenance --access public
This creates a signed attestation linking your package to its source repository and build environment, allowing downstream consumers to verify authenticity.
Enforce MFA on all npm accounts:
npm profile enable-2fa auth-and-writes
Require MFA for publish operations. Use hardware tokens (YubiKey) for maintainers with publish rights to critical internal packages.
Implement IP allowlisting for npm publish:
Configure your npm enterprise account to only accept publishes from known CI/CD infrastructure IPs, preventing compromised developer laptops from publishing directly.
Phase 2: Dependency Trust Assessment (Week 2)
Generate your dependency graph:
npm ls --all --json > dependency-tree.json
For each package in your top 20 by usage, document:
- Number of maintainers with publish rights.
- Last maintainer activity date.
- Presence of a security policy (SECURITY.md).
- GitHub security settings (2FA required for org).
- Funding sources (corporate backing vs. volunteer).
Flag high-risk patterns:
- Single maintainer with no backup.
- Maintainer account inactive for 6+ months.
- No public security contact.
- Maintained by an individual, not an organization.
For packages matching two or more high-risk criteria, consider forking and maintaining internally or identifying alternatives.
Phase 3: Runtime Verification (Week 3)
Implement package signature verification:
In npm 8.15+, verify signatures on install:
npm config set audit-signatures true
Add to your CI/CD pipeline:
- name: Verify package signatures
run: |
npm audit signatures
if [ $? -ne 0 ]; then
echo "Unsigned packages detected"
exit 1
fi
Pin exact versions in production:
Avoid using semver ranges (^ or ~) in production. Use exact versions:
{
"dependencies": {
"axios": "1.6.8" // not "^1.6.8"
}
}
Generate and store SBOMs:
syft packages dir:. -o cyclonedx-json > sbom.json
Store these with each deployment. When a compromise is announced, you can instantly identify affected systems.
Phase 4: Developer Environment Hardening (Week 4)
Block credential-stealing malware patterns:
Configure EDR to alert on:
- New processes reading
.npmrcor.yarnrc.yml. - Outbound connections from Node processes to non-standard registries.
- File system access to browser credential stores by Node processes.
Isolate package installation:
Run npm install in containers, not directly on developer machines:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
Separate credentials by environment:
Use different npm tokens for development, CI/CD, and production. Scope tokens to minimum required permissions. A compromised developer machine should not have credentials that can publish packages.
Validation: Ensuring Effectiveness
Test your provenance verification:
Attempt to install a package without valid provenance in your CI/CD pipeline. The build should fail.
Simulate a compromised maintainer:
Create a test package. Attempt to publish from an unauthorized IP address or without MFA. Verify the publish is blocked.
Verify your SBOM coverage:
Run syft against a production deployment. Confirm it captures all runtime dependencies, including transitive ones. Cross-reference against your package-lock.json.
Test your incident response:
Pick a package from your dependency tree. Assume it was compromised today. Time how long it takes to:
- Identify all affected systems.
- Determine the blast radius.
- Deploy a remediation.
If this takes more than 4 hours, your SBOM generation or deployment tracking needs improvement.
Maintenance: Ongoing Tasks
Weekly:
- Review new dependencies added in merged PRs.
- Check for unsigned packages in your dependency tree.
- Monitor maintainer activity for your top 20 dependencies.
Monthly:
- Audit npm account permissions and tokens.
- Review and rotate CI/CD npm credentials.
- Update your high-risk dependency list.
Quarterly:
- Re-assess trust tiers for all dependencies.
- Review and update security contact information for critical packages.
- Test your compromised package incident response procedure.
When a compromise is announced:
- Query your SBOM archive for affected package and version.
- Follow your incident response plan.
- Document lessons learned and update procedures.
The Axios compromise succeeded because social engineering bypassed technical controls. Your defense requires both technical measures that limit blast radius and organizational processes that reduce human vulnerability. Neither alone is sufficient.



