Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ Security toolkit protecting Node.js developers from npm supply chain attacks (Ph
- **npm-audit-lib.sh** - Shared library with common functions

**Pre-Installation:**
- **package-validator.js** - Pre-installation risk assessment with typosquatting detection
- **npm-install-monitor.js** - Network monitoring during installation
- **package-validator.sh** - Pre-installation risk assessment with typosquatting detection

**Response & Automation:**
- **credential-rotation-script.sh** - Post-compromise incident response guide
Expand All @@ -33,6 +32,8 @@ Security toolkit protecting Node.js developers from npm supply chain attacks (Ph
### Deprecated

- **deprecated/recursive-audit-script.sh** - Replaced by `npm-scanner.sh scan --project`
- **deprecated/package-validator.js** - Replaced by `package-validator.sh`
- **deprecated/npm-install-monitor.js** - Not integrated, limited value over scan commands

## Constraints

Expand Down Expand Up @@ -60,7 +61,7 @@ Security toolkit protecting Node.js developers from npm supply chain attacks (Ph

- NEVER add package.json, package-lock.json, or node_modules to this project
- This toolkit audits npm packages - depending on them creates supply chain risk
- Use only: bash scripts, standalone Node.js files, and system tools (jq, curl, etc.)
- Use only: bash scripts and system tools (jq, curl, etc.)
- CI will fail if npm dependency files are detected

## File Structure
Expand Down
File renamed without changes.
File renamed without changes.
11 changes: 9 additions & 2 deletions docs/npm-install-monitor.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# npm-install-monitor.js

**Type:** Real-Time Installation Monitor
**Language:** Node.js
> **DEPRECATED:** This script has been moved to `deprecated/npm-install-monitor.js`.
>
> **Reason:** Not integrated into the main `npm-scanner.sh` workflow and provides limited value over the `scan` commands. The network monitoring approach requires platform-specific tooling (lsof) and real-time process management that doesn't fit the project's Bash-based architecture.
>
> For pre-installation security checks, use `npm-scanner.sh validate <package>` instead.

**Type:** Real-Time Installation Monitor
**Language:** Node.js
**Location:** `deprecated/npm-install-monitor.js`
**Dependencies:** child_process, fs, lsof (Unix)

---
Expand Down
165 changes: 102 additions & 63 deletions docs/package-validator.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# package-validator.js
# package-validator.sh

**Type:** Pre-Installation Security Validator
**Language:** Node.js
**Dependencies:** https (built-in), child_process (built-in)
**Type:** Pre-Installation Security Validator
**Language:** Bash
**Dependencies:** curl, jq, npm-audit-lib.sh

---

Expand All @@ -15,28 +15,38 @@ Pre-installation risk assessment tool that validates npm packages before install
### 5.1 Risk Scoring System

**Risk Weights:**
```javascript
RISK_WEIGHTS = {
MALICIOUS_DOMAIN: 100, // Known malicious infrastructure
HTTP_DEPENDENCY: 50, // Remote dynamic dependencies
NEW_PACKAGE: 20, // < 30 days old
SINGLE_MAINTAINER: 10, // Only one maintainer
LOW_DOWNLOADS: 15, // < 100 weekly downloads
INSTALL_SCRIPTS: 25, // Lifecycle scripts present
RECENT_VERSION: 10 // Latest version < 7 days
}
```bash
RISK_WEIGHTS=(
[MALICIOUS_DOMAIN]=100 # Known malicious infrastructure
[MALICIOUS_IP]=100 # Known malicious IP addresses
[ATTACKER_PATTERN]=100 # Known attacker email/username patterns
[HTTP_DEPENDENCY]=50 # Remote dynamic dependencies
[DISPOSABLE_EMAIL]=40 # Disposable email domain
[SUSPICIOUS_EMAIL_PATTERN]=30 # Suspicious email patterns
[PRIVACY_RELAY_EMAIL]=15 # Privacy relay email (anonymous)
[NEW_PACKAGE]=20 # < 30 days old
[SINGLE_MAINTAINER]=10 # Only one maintainer
[LOW_DOWNLOADS]=15 # < 100 weekly downloads
[INSTALL_SCRIPTS]=25 # Lifecycle scripts present
[RECENT_VERSION]=10 # Latest version < 7 days
[TYPOSQUATTING]=30 # Similar to popular package name
# Positive modifiers (reduce risk)
[TRUSTED_TOP1K]=-10 # Email from top 1k domain
[TRUSTED_TOP10K]=-5 # Email from top 10k domain
[TRUSTED_TOP100K]=-2 # Email from top 100k domain
)
```

**Risk Levels:**
- `CRITICAL` (80): Do not install
- `HIGH` (50): Extreme caution
- `MEDIUM` (25): Proceed with caution
- `LOW` (10): Some concerns
- `CRITICAL` (>=80): Do not install
- `HIGH` (>=50): Extreme caution
- `MEDIUM` (>=25): Proceed with caution
- `LOW` (>=10): Some concerns
- `SAFE` (<10): Appears safe

### 5.2 Package Age Analysis

**Function:** `checkPackageAge()`
**Function:** `check_package_age()`

**Checks:**
1. **Package Creation Date**
Expand All @@ -46,22 +56,30 @@ RISK_WEIGHTS = {
2. **Latest Version Age**
- < 7 days: MEDIUM risk (+10 points)

**Data Source:** `packageData.time.created`, `packageData.time[version]`
**Data Source:** npm registry API `time.created`, `time[version]`

### 5.3 Maintainer Analysis

**Function:** `checkMaintainers()`
**Function:** `check_maintainers()`

**Checks:**
1. **Maintainer Count**
- 0 maintainers: HIGH risk (+20 points)
- 1 maintainer: LOW risk (+10 points)

2. **Email Pattern Analysis**
- Suspicious patterns: `temp|disposable|trash|fake|test\d+`
- Match: HIGH risk (+30 points)
2. **Email Domain Analysis** (via npm-audit-lib.sh)
- Disposable email domains: HIGH risk (+40 points)
- Privacy relay domains: LOW risk (+15 points)
- Trusted domains: Negative points (reduces risk)

3. **Email Pattern Analysis**
- Suspicious patterns: `temp|disposable|trash|fake|test[0-9]+`
- Match: MEDIUM risk (+30 points)

**Purpose:** Identify potential throwaway/fake accounts
4. **Attacker Pattern Matching**
- Known attacker patterns: CRITICAL risk (+100 points)

**Purpose:** Identify potential throwaway/fake accounts and known malicious actors

**Output Format:**
```
Expand All @@ -70,15 +88,13 @@ RISK_WEIGHTS = {
Risk points: +10
```

Note: The package name is shown in the report header, so findings only include the maintainer information.

### 5.4 Download Statistics

**Function:** `checkDownloads()`
**Function:** `check_downloads()`

**Implementation:**
```javascript
npm view ${packageName} dist.last-week --json
```bash
curl -sL "https://api.npmjs.org/downloads/point/last-week/${package}"
```

**Threshold:** < 100 weekly downloads = MEDIUM risk (+15 points)
Expand All @@ -87,23 +103,24 @@ npm view ${packageName} dist.last-week --json

### 5.5 Dependency Analysis

**Function:** `checkDependencies()`
**Function:** `check_dependencies()`

**Checks:**
1. **HTTP/HTTPS URL Dependencies**
- Detects: `version.match(/^https?:\/\//)`
- Known malicious: CRITICAL (+100 points)
- Known malicious domain: CRITICAL (+100 points)
- Known malicious IP: CRITICAL (+100 points)
- Other HTTP URLs: HIGH (+50 points)

2. **Malicious Domains**
2. **Malicious Indicators** (from npm-audit-lib.sh):
- `packages.storeartifact.com`
- `storeartifact.com`
- `54.173.15.59`

**Scope:** dependencies, devDependencies, peerDependencies

### 5.6 Lifecycle Script Detection

**Function:** `checkScripts()`
**Function:** `check_scripts()`

**Monitored Scripts:**
- `preinstall`
Expand All @@ -116,32 +133,34 @@ npm view ${packageName} dist.last-week --json

### 5.7 Typosquatting Detection

**Function:** `checkTyposquatting()`
**Function:** `check_typosquatting()`

**Algorithm:** Levenshtein Distance
**Algorithm:** Levenshtein Distance (pure Bash implementation)

**Popular Packages List:**
```javascript
['express', 'react', 'vue', 'angular', 'lodash', 'axios',
'webpack', 'babel', 'eslint', 'typescript', 'prettier',
'jest', 'mocha']
**Popular Packages List:** (from npm-audit-lib.sh TYPOSQUATTING_TARGETS)
```bash
express react vue angular lodash axios webpack
babel eslint typescript prettier jest mocha
chalk moment uuid commander debug request
async bluebird underscore q colors minimist
yargs glob rimraf
```

**Threshold:** Edit distance 2 = HIGH risk (+30 points)
**Threshold:** Edit distance <= 2 = HIGH risk (+30 points)

**Examples:**
- `expres` (distance: 1) typosquatting
- `reactt` (distance: 1) typosquatting
- `expres` (distance: 1) -> typosquatting alert
- `reactt` (distance: 1) -> typosquatting alert

### 5.8 Report Generation

**Function:** `printReport()`
**Function:** `print_report()`

**Format:**
```
═══════════════════════════════════════════════
===============================================
Package Security Validation Report
═══════════════════════════════════════════════
===============================================

Package: example-package
Risk Score: 45
Expand All @@ -150,60 +169,80 @@ Risk Level: MEDIUM
Findings:

[MEDIUM] Package Age
Package is 25 days old (created Mon Oct 06 2025)
Package is 25 days old (created 2025-10-06)
Risk points: +20

[MEDIUM] Install Scripts
Package has lifecycle scripts that run automatically:
install: node postinstall.js
Risk points: +25

═══════════════════════════════════════════════
===============================================
Recommendation
═══════════════════════════════════════════════
===============================================

⚠️ MEDIUM RISK - Proceed with caution
MEDIUM RISK - Proceed with caution
Review the findings and verify the package legitimacy.
```

## Input Parameters

```bash
Usage: node package-validator.js <package-name>
Usage: package-validator.sh <package-name> [--json]

Arguments:
package-name # Name of npm package to validate
package-name Name of npm package to validate
--json Output results in JSON format

Examples:
node package-validator.js express
node package-validator.js @babel/core
./npm-scanner.sh validate express
./npm-scanner.sh validate @babel/core
./npm-scanner.sh validate lodash --json
```

## Output Format

**Exit Codes:**
- `0`: SAFE or LOW risk
- `0`: SAFE, LOW, or MEDIUM risk
- `1`: HIGH or CRITICAL risk, or error

**Colors:**
- RED: Critical/High severity
- YELLOW: Medium severity
- BLUE: Low severity
- GREEN: Safe
- GREEN: Safe/Info

**JSON Output:**
```json
{
"package": "example-package",
"riskScore": 45,
"riskLevel": "MEDIUM",
"findingsCount": 2,
"findings": [
{
"severity": "MEDIUM",
"category": "Package Age",
"message": "Package is 25 days old",
"points": 20
}
]
}
```

## Performance Characteristics

- **API Calls:** 1-2 to npm registry
- **API Calls:** 2 to npm registry (package data + downloads)
- **Execution Time:** 1-3 seconds
- **Memory Usage:** < 30MB
- **Memory Usage:** Minimal (shell script)

## Use Cases

1. **Pre-Install Check:** `node package-validator.js suspicious-pkg`
1. **Pre-Install Check:** `./npm-scanner.sh validate suspicious-pkg`
2. **CI/CD Gate:** Exit code determines pass/fail
3. **Manual Review:** Before adding new dependencies
4. **JSON Integration:** `./npm-scanner.sh validate pkg --json | jq .riskLevel`

---

[← Back to scheduled-audit-script.sh](scheduled-audit-script.md) | [Next: npm-install-monitor.js →](npm-install-monitor.md)

[Back to scheduled-audit-script.sh](scheduled-audit-script.md) | [Next: npm-install-monitor.js](npm-install-monitor.md)
2 changes: 1 addition & 1 deletion npm-scanner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ cmd_validate() {
exit 0
fi
warn_data_status || return 1
node "$SCRIPTS_DIR/package-validator.js" "$@"
"$SCRIPTS_DIR/package-validator.sh" "$@"
}

cmd_list_iocs() {
Expand Down
Loading