vanguard-cli 3.1.18 → 3.1.20
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 +2 -1
- package/bin/vanguard.js +19 -30
- package/lib/commands/scan.js +44 -17
- package/lib/services/git.js +12 -2
- package/lib/services/scanner.js +217 -190
- package/lib/utils/ui.js +3 -2
- package/lib/utils/update.js +41 -0
- package/package.json +1 -1
- package/scan_output.txt +79 -0
- package/vanguard_scan.txt +107 -0
package/README.md
CHANGED
|
@@ -26,7 +26,8 @@ Modern software supply chain attacks are sophisticated. Traditional antiviruses
|
|
|
26
26
|
* 🧠 **Hybrid Intelligence:** Combines **Google Gemini 2.0**'s reasoning with a curated **Threat Intelligence DB** and **OSV.dev** vulnerability data.
|
|
27
27
|
* ⚡ **Zero-Latency Caching:** Uses SHA-256 hashing to memorize safe files. Re-scanning a project takes milliseconds.
|
|
28
28
|
* 🔒 **Privacy First:** Supports **Local Ollama**. Your code never leaves your machine if you choose local models.
|
|
29
|
-
* 🛡️ **Proactive Defense:** It doesn't just scan; it intercepts Git commands to prevent bad code from reaching your
|
|
29
|
+
* 🛡️ **Proactive Defense:** It doesn't just scan; it intercepts Git commands to prevent bad code from reaching your disk.
|
|
30
|
+
* ⚡ **Flexible Audit Modes:** Choose between a **Quick Audit** (targeting configuration and entry files) or a **Deep Audit** (full behavioral analysis of all code files).
|
|
30
31
|
|
|
31
32
|
---
|
|
32
33
|
|
package/bin/vanguard.js
CHANGED
|
@@ -8,11 +8,15 @@ import { runIntegrate } from '../lib/commands/integrate.js';
|
|
|
8
8
|
import { handlePull, handleClone } from '../lib/commands/scan.js';
|
|
9
9
|
import { showBanner, showFooter } from '../lib/utils/ui.js';
|
|
10
10
|
import config from '../lib/utils/config.js';
|
|
11
|
+
import { checkForUpdates } from '../lib/utils/update.js';
|
|
11
12
|
|
|
12
13
|
import { createRequire } from 'module';
|
|
13
14
|
const require = createRequire(import.meta.url);
|
|
14
15
|
const pkg = require('../package.json');
|
|
15
16
|
|
|
17
|
+
// Check for updates in the background
|
|
18
|
+
checkForUpdates(pkg.version);
|
|
19
|
+
|
|
16
20
|
const program = new Command();
|
|
17
21
|
|
|
18
22
|
async function handleAction(actionName, logicFn) {
|
|
@@ -35,38 +39,24 @@ async function handleAction(actionName, logicFn) {
|
|
|
35
39
|
const options = program.opts();
|
|
36
40
|
config.set('VERBOSE', !!options.verbose);
|
|
37
41
|
|
|
38
|
-
const {
|
|
42
|
+
const { mode } = await inquirer.prompt([
|
|
39
43
|
{
|
|
40
|
-
type: '
|
|
41
|
-
name: '
|
|
42
|
-
message: `🛡️ Vanguard Enterprise Edition detected a ${actionName}.
|
|
43
|
-
|
|
44
|
+
type: 'list',
|
|
45
|
+
name: 'mode',
|
|
46
|
+
message: `🛡️ Vanguard Enterprise Edition detected a ${actionName}. Select protection level:`,
|
|
47
|
+
choices: [
|
|
48
|
+
{ name: chalk.green('⚡ Quick Audit ') + chalk.dim('(Config & Entry Files)'), value: 'quick' },
|
|
49
|
+
{ name: chalk.cyan('🛡️ Deep Audit ') + chalk.dim('(Full behavioral scanning)'), value: 'deep' },
|
|
50
|
+
{ name: chalk.yellow('⚠️ Skip ') + chalk.dim('(Direct execution - RISKY)'), value: 'skip' },
|
|
51
|
+
],
|
|
52
|
+
default: 'quick',
|
|
44
53
|
},
|
|
45
54
|
]);
|
|
46
55
|
|
|
47
|
-
if (
|
|
48
|
-
console.log(chalk.yellow('⚠️ Skipping protection. Proceeding at your own risk.'));
|
|
56
|
+
if (mode === 'skip') {
|
|
57
|
+
console.log(chalk.yellow('\n⚠️ Skipping protection. Proceeding at your own risk.'));
|
|
49
58
|
|
|
50
|
-
// If the user skips Vanguard, we must execute the original git command
|
|
51
59
|
if (actionName === 'CLONE') {
|
|
52
|
-
// Reconstruct arguments
|
|
53
|
-
const args = process.argv.slice(3); // Remove node, bin, clone
|
|
54
|
-
// This is a simplified fallback. In a real integration, we'd want to execSync/spawn
|
|
55
|
-
// "git clone ..." but since we are inside a node process wrapping git,
|
|
56
|
-
// we can suggest the user run usage logic or attempt spawn.
|
|
57
|
-
|
|
58
|
-
// However, for the 'integrate' shell function, if 'vanguard' exits with 0 and no output,
|
|
59
|
-
// the shell function expects to be done.
|
|
60
|
-
// The Shell Integration logic:
|
|
61
|
-
// if [ "$1" = "clone" ] ... vanguard clone ... else git clone ...
|
|
62
|
-
|
|
63
|
-
// If we return here, Vanguard finishes. The shell wrapper won't run `git clone` because
|
|
64
|
-
// it delegated the job to `vanguard clone`.
|
|
65
|
-
|
|
66
|
-
// SO: We must actually perform the git clone ourselves now, or exit with a specific code
|
|
67
|
-
// that tells the shell wrapper to fallback (complex).
|
|
68
|
-
|
|
69
|
-
// Easiest path: Spawn 'git' directly here.
|
|
70
60
|
const { spawn } = await import('child_process');
|
|
71
61
|
const gitArgs = [actionName.toLowerCase(), ...process.argv.slice(3)];
|
|
72
62
|
|
|
@@ -74,13 +64,12 @@ async function handleAction(actionName, logicFn) {
|
|
|
74
64
|
child.on('close', (code) => {
|
|
75
65
|
process.exit(code);
|
|
76
66
|
});
|
|
77
|
-
// We return promise to await exit
|
|
78
67
|
return new Promise(() => { });
|
|
79
68
|
}
|
|
80
69
|
return;
|
|
81
70
|
}
|
|
82
71
|
|
|
83
|
-
await logicFn();
|
|
72
|
+
await logicFn(mode);
|
|
84
73
|
showFooter();
|
|
85
74
|
}
|
|
86
75
|
|
|
@@ -117,7 +106,7 @@ program
|
|
|
117
106
|
.description('Audit and pull upstream changes')
|
|
118
107
|
.option('-f, --force', 'Force merge even if threats are detected')
|
|
119
108
|
.action(async (cmdOptions) => {
|
|
120
|
-
await handleAction('PULL', () => handlePull(cmdOptions, program.opts()));
|
|
109
|
+
await handleAction('PULL', (mode) => handlePull(cmdOptions, program.opts(), mode));
|
|
121
110
|
});
|
|
122
111
|
|
|
123
112
|
program
|
|
@@ -126,7 +115,7 @@ program
|
|
|
126
115
|
.argument('<url>', 'Git URL')
|
|
127
116
|
.argument('[directory]', 'Target directory')
|
|
128
117
|
.action(async (url, directory) => {
|
|
129
|
-
await handleAction('CLONE', () => handleClone(url, directory, program.opts()));
|
|
118
|
+
await handleAction('CLONE', (mode) => handleClone(url, directory, program.opts(), mode));
|
|
130
119
|
});
|
|
131
120
|
|
|
132
121
|
showBanner(pkg.version);
|
package/lib/commands/scan.js
CHANGED
|
@@ -11,24 +11,27 @@ import { walkProject } from '../utils/walker.js';
|
|
|
11
11
|
import {
|
|
12
12
|
fetchUpstream,
|
|
13
13
|
getUpstreamDiff,
|
|
14
|
+
getUpstreamDiffFiles,
|
|
14
15
|
mergeUpstream,
|
|
15
16
|
createSandboxClone,
|
|
16
17
|
finalizeClone,
|
|
17
18
|
cleanupSandbox,
|
|
18
19
|
} from '../services/git.js';
|
|
19
20
|
|
|
20
|
-
export async function handlePull(cmdOptions, programOptions) {
|
|
21
|
+
export async function handlePull(cmdOptions, programOptions, mode = 'deep') {
|
|
21
22
|
if (programOptions.clearCache) CacheManager.clear();
|
|
23
|
+
const scanner = new VanguardScanner(programOptions.model);
|
|
22
24
|
|
|
23
25
|
const intel = new IntelligenceEngine(programOptions.verbose);
|
|
24
26
|
const spinner = createSpinner('🚀 Syncing intelligence & probing connections...').start();
|
|
25
27
|
|
|
26
28
|
const pkgContent = await fs.readFile(path.join(process.cwd(), 'package.json'), 'utf-8').catch(() => null);
|
|
27
29
|
const context = await intel.sync(pkgContent);
|
|
30
|
+
scanner.intelligenceContext = context;
|
|
28
31
|
|
|
29
32
|
spinner.text = '🔍 Auditing diff for supply chain threats...';
|
|
30
33
|
await fetchUpstream();
|
|
31
|
-
|
|
34
|
+
let diff = await getUpstreamDiff();
|
|
32
35
|
|
|
33
36
|
if (!diff || diff.trim() === '') {
|
|
34
37
|
spinner.succeed('✅ No upstream changes to audit.');
|
|
@@ -36,13 +39,28 @@ export async function handlePull(cmdOptions, programOptions) {
|
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
if (mode === 'quick') {
|
|
43
|
+
const filenames = await getUpstreamDiffFiles();
|
|
44
|
+
const highRiskFilenames = filenames.filter(f => scanner.isHighRisk(f));
|
|
45
|
+
|
|
46
|
+
if (highRiskFilenames.length === 0) {
|
|
47
|
+
spinner.succeed('✅ No high-risk files modified. Quick Scan Passed.');
|
|
48
|
+
await mergeUpstream();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(chalk.cyan(`\n⚡ Quick Audit: ${highRiskFilenames.length}/${filenames.length} modified files targeted.`));
|
|
53
|
+
// Get diff only for high risk files
|
|
54
|
+
diff = await getUpstreamDiff(highRiskFilenames);
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
let analysis;
|
|
41
58
|
try {
|
|
42
59
|
analysis = await scanner.scan('git_diff', diff, spinner);
|
|
43
60
|
} catch (err) {
|
|
44
61
|
if (err.message === 'CRITICAL_AUTH_FAILURE') {
|
|
45
|
-
process.
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
return;
|
|
46
64
|
}
|
|
47
65
|
let msg = err.message;
|
|
48
66
|
if (msg.includes('[GoogleGenerativeAI Error]')) {
|
|
@@ -67,7 +85,7 @@ export async function handlePull(cmdOptions, programOptions) {
|
|
|
67
85
|
: await inquirer.prompt([
|
|
68
86
|
{
|
|
69
87
|
type: 'confirm',
|
|
70
|
-
name: '
|
|
88
|
+
name: 'proceed',
|
|
71
89
|
message: '⚠️ BLOCK VERDICT. Force override merge?',
|
|
72
90
|
default: false,
|
|
73
91
|
},
|
|
@@ -81,7 +99,7 @@ export async function handlePull(cmdOptions, programOptions) {
|
|
|
81
99
|
}
|
|
82
100
|
}
|
|
83
101
|
|
|
84
|
-
export async function handleClone(url, directory, programOptions) {
|
|
102
|
+
export async function handleClone(url, directory, programOptions, mode = 'deep') {
|
|
85
103
|
const targetPath = directory || path.basename(url, '.git');
|
|
86
104
|
|
|
87
105
|
const intel = new IntelligenceEngine(programOptions.verbose);
|
|
@@ -93,20 +111,28 @@ export async function handleClone(url, directory, programOptions) {
|
|
|
93
111
|
const pkgContent = await fs.readFile(path.join(tempPath, 'package.json'), 'utf-8').catch(() => null);
|
|
94
112
|
const context = await intel.sync(pkgContent);
|
|
95
113
|
|
|
96
|
-
const
|
|
114
|
+
const allFiles = await walkProject(tempPath);
|
|
97
115
|
spinner.stop();
|
|
98
116
|
|
|
99
|
-
console.log(chalk.cyan(`\n📑 Batch Audit: ${files.length} files identified.`));
|
|
100
|
-
|
|
101
117
|
const scanner = new VanguardScanner(programOptions.model, context);
|
|
118
|
+
|
|
119
|
+
// Filtering based on mode
|
|
120
|
+
let filesToScan = allFiles;
|
|
121
|
+
if (mode === 'quick') {
|
|
122
|
+
filesToScan = allFiles.filter(f => scanner.isHighRisk(f));
|
|
123
|
+
console.log(chalk.cyan(`\n⚡ Quick Audit: ${filesToScan.length}/${allFiles.length} critical files targeted.`));
|
|
124
|
+
} else {
|
|
125
|
+
console.log(chalk.cyan(`\n📑 Batch Audit: ${allFiles.length} files identified.`));
|
|
126
|
+
}
|
|
127
|
+
|
|
102
128
|
let finalVerdict = 'SAFE';
|
|
103
129
|
let allThreats = [];
|
|
104
130
|
let cachedCount = 0;
|
|
105
131
|
let skippedCount = 0;
|
|
106
132
|
|
|
107
|
-
const scanSpinner = createSpinner(`🧠 Auditing ${
|
|
133
|
+
const scanSpinner = createSpinner(`🧠 Auditing ${filesToScan.length} files...`).start();
|
|
108
134
|
|
|
109
|
-
for (const file of
|
|
135
|
+
for (const file of filesToScan) {
|
|
110
136
|
const stats = await fs.stat(file);
|
|
111
137
|
|
|
112
138
|
// Enterprise Filtering
|
|
@@ -136,12 +162,12 @@ export async function handleClone(url, directory, programOptions) {
|
|
|
136
162
|
} catch (err) {
|
|
137
163
|
if (err.message === 'CRITICAL_AUTH_FAILURE') {
|
|
138
164
|
await cleanupSandbox(tempPath);
|
|
139
|
-
process.
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
return;
|
|
140
167
|
}
|
|
141
168
|
let msg = err.message;
|
|
142
|
-
// Clean up Google's noisy JSON error if it slipped through
|
|
143
169
|
if (msg.includes('[GoogleGenerativeAI Error]')) {
|
|
144
|
-
msg = msg.split('[')[0].trim();
|
|
170
|
+
msg = msg.split('[')[0].trim();
|
|
145
171
|
if (msg.includes('400')) msg = 'Invalid API Request (400). Check configuration.';
|
|
146
172
|
else if (msg.length > 100) msg = 'AI Service Error (Check connection/quota)';
|
|
147
173
|
}
|
|
@@ -153,19 +179,20 @@ export async function handleClone(url, directory, programOptions) {
|
|
|
153
179
|
}
|
|
154
180
|
}
|
|
155
181
|
|
|
156
|
-
scanSpinner.succeed(`Audit Complete: ${
|
|
182
|
+
scanSpinner.succeed(`Audit Complete: ${filesToScan.length} scanned (${cachedCount} cached, ${skippedCount} skipped).`);
|
|
157
183
|
|
|
158
184
|
if (finalVerdict === 'BLOCK') {
|
|
159
185
|
showAlert({
|
|
160
186
|
verdict: 'BLOCK',
|
|
161
187
|
risk_score: 99,
|
|
162
188
|
threats: allThreats,
|
|
163
|
-
summary:
|
|
189
|
+
summary: `Enterprise ${mode.toUpperCase()} Audit identified multiple high-risk vectors.`,
|
|
164
190
|
});
|
|
165
191
|
await cleanupSandbox(tempPath);
|
|
166
192
|
console.log(chalk.red.bold('\n🛡️ Malware Detected! Clone aborted. Your disk is safe.'));
|
|
167
193
|
} else {
|
|
168
|
-
|
|
194
|
+
const label = mode === 'quick' ? 'Quick Audit' : 'Deep Audit';
|
|
195
|
+
console.log(chalk.green(`\n✅ ${label} Passed. Finalizing clone to ${targetPath}...`));
|
|
169
196
|
await finalizeClone(tempPath, targetPath);
|
|
170
197
|
}
|
|
171
198
|
}
|
package/lib/services/git.js
CHANGED
|
@@ -17,9 +17,19 @@ export async function fetchUpstream() {
|
|
|
17
17
|
/**
|
|
18
18
|
* Gets the diff string for scanning.
|
|
19
19
|
*/
|
|
20
|
-
export async function getUpstreamDiff() {
|
|
20
|
+
export async function getUpstreamDiff(files = []) {
|
|
21
21
|
// Compare HEAD vs FETCH_HEAD (which is what was just fetched)
|
|
22
|
-
|
|
22
|
+
const args = ['HEAD..FETCH_HEAD'];
|
|
23
|
+
if (files.length > 0) args.push('--', ...files);
|
|
24
|
+
return await git.diff(args);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gets the list of filenames changed in upstream.
|
|
29
|
+
*/
|
|
30
|
+
export async function getUpstreamDiffFiles() {
|
|
31
|
+
const diffSummary = await git.diffSummary(['HEAD..FETCH_HEAD']);
|
|
32
|
+
return diffSummary.files.map(f => f.file);
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
/**
|
package/lib/services/scanner.js
CHANGED
|
@@ -1,190 +1,217 @@
|
|
|
1
|
-
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
2
|
-
import config from '../utils/config.js';
|
|
3
|
-
import fetch from 'node-fetch';
|
|
4
|
-
import fs from 'fs/promises';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import pLimit from 'p-limit';
|
|
9
|
-
|
|
10
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
-
const THREATS_PATH = path.join(__dirname, '../threats.json');
|
|
12
|
-
|
|
13
|
-
const limit = pLimit(1); // Conservative concurrency for free tier stability
|
|
14
|
-
|
|
15
|
-
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
16
|
-
|
|
17
|
-
export class VanguardScanner {
|
|
18
|
-
constructor(modelOverride, intelligenceContext = '') {
|
|
19
|
-
this.provider = config.get('AI_PROVIDER');
|
|
20
|
-
this.modelOverride = modelOverride;
|
|
21
|
-
this.intelligenceContext = intelligenceContext;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
shouldSkip(filePath, stats) {
|
|
25
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
26
|
-
const binaryExtensions = [
|
|
27
|
-
'.exe', '.dll', '.so', '.bin', '.png', '.jpg', '.jpeg', '.gif', '.pdf', '.zip', '.gz',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
if (
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
.
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return this.
|
|
103
|
-
} else
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
1
|
+
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
2
|
+
import config from '../utils/config.js';
|
|
3
|
+
import fetch from 'node-fetch';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import pLimit from 'p-limit';
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const THREATS_PATH = path.join(__dirname, '../threats.json');
|
|
12
|
+
|
|
13
|
+
const limit = pLimit(1); // Conservative concurrency for free tier stability
|
|
14
|
+
|
|
15
|
+
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
16
|
+
|
|
17
|
+
export class VanguardScanner {
|
|
18
|
+
constructor(modelOverride, intelligenceContext = '') {
|
|
19
|
+
this.provider = config.get('AI_PROVIDER');
|
|
20
|
+
this.modelOverride = modelOverride;
|
|
21
|
+
this.intelligenceContext = intelligenceContext;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
shouldSkip(filePath, stats) {
|
|
25
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
26
|
+
const binaryExtensions = [
|
|
27
|
+
'.exe', '.dll', '.so', '.bin', '.png', '.jpg', '.jpeg', '.gif', '.pdf', '.zip', '.gz',
|
|
28
|
+
'.ico', '.svg', '.woff', '.woff2', '.ttf', '.eot', '.webp', '.map', '.pyc', '.jar',
|
|
29
|
+
];
|
|
30
|
+
if (binaryExtensions.includes(ext)) return true;
|
|
31
|
+
if (stats.size > 100 * 1024) return true;
|
|
32
|
+
if (filePath.includes('node_modules')) return true;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
isHighRisk(filePath) {
|
|
37
|
+
const filename = path.basename(filePath).toLowerCase();
|
|
38
|
+
const highRiskFiles = [
|
|
39
|
+
'package.json',
|
|
40
|
+
'package-lock.json',
|
|
41
|
+
'yarn.lock',
|
|
42
|
+
'pnpm-lock.yaml',
|
|
43
|
+
'tsconfig.json',
|
|
44
|
+
'jsconfig.json',
|
|
45
|
+
'.env',
|
|
46
|
+
'install.js',
|
|
47
|
+
'postinstall.js',
|
|
48
|
+
'preinstall.js',
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
if (highRiskFiles.includes(filename)) return true;
|
|
52
|
+
if (filePath.includes('.github/workflows')) return true;
|
|
53
|
+
if (filePath.includes('.vscode')) return true;
|
|
54
|
+
|
|
55
|
+
// Common entry points
|
|
56
|
+
const entryPoints = ['index.js', 'main.js', 'server.js', 'app.js', 'cli.js'];
|
|
57
|
+
if (entryPoints.includes(filename)) return true;
|
|
58
|
+
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async getSystemInstruction() {
|
|
63
|
+
const threatsData = await fs.readFile(THREATS_PATH, 'utf-8');
|
|
64
|
+
const threats = JSON.parse(threatsData);
|
|
65
|
+
const categoriesListing = threats
|
|
66
|
+
.map((t, i) => `${i + 1}. **${t.name}:** ${t.description}`)
|
|
67
|
+
.join('\n');
|
|
68
|
+
|
|
69
|
+
return `
|
|
70
|
+
You are a Senior Security Architect & Auditor. YOUR MISSION: Prevent Supply Chain Attacks.
|
|
71
|
+
Analyze the provided code/diff with extreme scrutiny.
|
|
72
|
+
|
|
73
|
+
YOU MUST BLOCK IF YOU DETECT ANY OF THESE CATEGORIES:
|
|
74
|
+
${categoriesListing}
|
|
75
|
+
|
|
76
|
+
${this.intelligenceContext}
|
|
77
|
+
|
|
78
|
+
JSON OUTPUT RULES:
|
|
79
|
+
- risk_score: 0-100.
|
|
80
|
+
- verdict: "BLOCK" or "SAFE".
|
|
81
|
+
- threats: Array of { "file", "line", "threat", "reason" }
|
|
82
|
+
- summary: Clear explanation.
|
|
83
|
+
|
|
84
|
+
RESPONSE FORMAT (JSON ONLY):
|
|
85
|
+
{ "risk_score": 95, "verdict": "BLOCK", "threats": [], "summary": "..." }
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async scan(filePath, content, spinner = null) {
|
|
90
|
+
// Random Jitter Throttling (1s - 3s)
|
|
91
|
+
if (this.provider === 'gemini') {
|
|
92
|
+
const jitter = Math.floor(Math.random() * 2000) + 1000;
|
|
93
|
+
await sleep(jitter);
|
|
94
|
+
}
|
|
95
|
+
return limit(() => this.scanWithRetry(filePath, content, spinner));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async scanWithRetry(filePath, content, spinner, attempt = 1) {
|
|
99
|
+
const maxAttempts = 3;
|
|
100
|
+
try {
|
|
101
|
+
if (this.provider === 'gemini') {
|
|
102
|
+
return await this.scanWithGemini(content);
|
|
103
|
+
} else {
|
|
104
|
+
return await this.scanWithOllama(content);
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
const isRateLimit =
|
|
108
|
+
error.message.includes('429') ||
|
|
109
|
+
error.message.includes('Too Many Requests') ||
|
|
110
|
+
error.message.includes('Quota');
|
|
111
|
+
|
|
112
|
+
const isServerErr = error.message.includes('500') || error.message.includes('503');
|
|
113
|
+
|
|
114
|
+
if (isRateLimit && attempt <= maxAttempts) {
|
|
115
|
+
const waitTime = attempt === 1 ? 30 : 60;
|
|
116
|
+
if (spinner) {
|
|
117
|
+
const originalText = spinner.text;
|
|
118
|
+
for (let i = waitTime; i > 0; i--) {
|
|
119
|
+
// Only update once per second to prevent terminal flickering
|
|
120
|
+
if (spinner.text.includes(`${i}s`)) continue;
|
|
121
|
+
spinner.text = `❄️ Quota hit (${i}s). Waiting... (Tip: Ctrl+C -> 'vanguard config' to switch AI)`;
|
|
122
|
+
await sleep(1000);
|
|
123
|
+
}
|
|
124
|
+
spinner.text = originalText;
|
|
125
|
+
} else {
|
|
126
|
+
console.log(chalk.yellow(`\n⚠️ Rate limit hit. Cooling down for ${waitTime}s... (Tip: 'vanguard config' to switch AI)`));
|
|
127
|
+
await sleep(waitTime * 1000);
|
|
128
|
+
}
|
|
129
|
+
return this.scanWithRetry(filePath, content, spinner, attempt + 1);
|
|
130
|
+
} else if (isRateLimit) {
|
|
131
|
+
// Final failure after retries
|
|
132
|
+
console.log(chalk.blue('\n💡 Tip: Gemini Quota exceeded? Switch to local offline mode:'));
|
|
133
|
+
console.log(chalk.cyan(' vanguard config -> Select "Local Ollama"'));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const isOllamaError = error.message.includes('Ollama error') || error.message.includes('fetch failed');
|
|
137
|
+
if (isOllamaError) {
|
|
138
|
+
console.log(chalk.blue('\n💡 Tip: Local AI failing? Switch to Cloud fallback:'));
|
|
139
|
+
console.log(chalk.cyan(' vanguard config -> Select "Google Gemini"'));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const isAuthError =
|
|
143
|
+
error.message.includes('API key') ||
|
|
144
|
+
error.message.includes('400') ||
|
|
145
|
+
error.message.includes('PERMISSION_DENIED');
|
|
146
|
+
|
|
147
|
+
if (isAuthError) {
|
|
148
|
+
if (spinner) spinner.fail('Authentication Failed');
|
|
149
|
+
console.log(chalk.red('\n❌ Critical: Gemini API Key is invalid, expired, or missing permissions.'));
|
|
150
|
+
console.log(chalk.yellow('👉 Run "vanguard config" to update your credentials.'));
|
|
151
|
+
// We fail closed - do not allow the scan to proceed or return 'safe'
|
|
152
|
+
// process.exit(1) can cause UV_HANDLE_CLOSING assertion on Windows if async ops are pending.
|
|
153
|
+
// Instead, throw a specific error that the caller can catch and exit cleanly.
|
|
154
|
+
throw new Error('CRITICAL_AUTH_FAILURE');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isServerErr && attempt === 1) {
|
|
158
|
+
if (spinner) spinner.text = '🔄 AI Server hiccup. Retrying immediately...';
|
|
159
|
+
return this.scanWithRetry(filePath, content, spinner, attempt + 1);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async scanWithGemini(content) {
|
|
167
|
+
const apiKey = config.get('GEMINI_KEY');
|
|
168
|
+
if (!apiKey) throw new Error('Gemini API Key missing. Run "vanguard config"');
|
|
169
|
+
|
|
170
|
+
if (!apiKey || apiKey.trim() === '') {
|
|
171
|
+
throw new Error('API key is missing.');
|
|
172
|
+
}
|
|
173
|
+
const genAI = new GoogleGenerativeAI(apiKey.trim());
|
|
174
|
+
// Use the latest stable pro flash model for the best performance/quota ratio
|
|
175
|
+
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
|
|
176
|
+
const instruction = await this.getSystemInstruction();
|
|
177
|
+
|
|
178
|
+
const result = await model.generateContent({
|
|
179
|
+
contents: [{ role: 'user', parts: [{ text: `${instruction}\n\nFILE CONTENT:\n${content}` }] }],
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const response = await result.response;
|
|
183
|
+
return this.parseResponse(response.text());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async scanWithOllama(content) {
|
|
187
|
+
const model = this.modelOverride || config.get('OLLAMA_MODEL');
|
|
188
|
+
const url = `${config.get('OLLAMA_URL')}/api/generate`;
|
|
189
|
+
const instruction = await this.getSystemInstruction();
|
|
190
|
+
|
|
191
|
+
const response = await fetch(url, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
headers: { 'Content-Type': 'application/json' },
|
|
194
|
+
body: JSON.stringify({
|
|
195
|
+
model: model,
|
|
196
|
+
prompt: `${instruction}\n\nFILE CONTENT:\n${content}`,
|
|
197
|
+
stream: false,
|
|
198
|
+
format: 'json',
|
|
199
|
+
}),
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
if (!response.ok) throw new Error(`Ollama error: ${response.statusText}`);
|
|
203
|
+
const data = await response.json();
|
|
204
|
+
return this.parseResponse(data.response);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
parseResponse(text) {
|
|
208
|
+
try {
|
|
209
|
+
const start = text.indexOf('{');
|
|
210
|
+
const end = text.lastIndexOf('}');
|
|
211
|
+
if (start === -1 || end === -1) throw new Error('No JSON object found');
|
|
212
|
+
return JSON.parse(text.substring(start, end + 1));
|
|
213
|
+
} catch (e) {
|
|
214
|
+
throw new Error(`Invalid AI JSON format: ${e.message}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
package/lib/utils/ui.js
CHANGED
|
@@ -27,12 +27,13 @@ export function showAlert(analysis) {
|
|
|
27
27
|
? threats.map((t) => {
|
|
28
28
|
const loc = t.file ? chalk.yellow(`[${t.file}${t.line ? `:${t.line}` : ''}] `) : '';
|
|
29
29
|
const tag = t.threat ? chalk.red(`(${t.threat})`) : '';
|
|
30
|
-
|
|
30
|
+
const reason = t.reason || (typeof t === 'string' ? t : 'Potential threat detected without specific details.');
|
|
31
|
+
return `• ${loc}${tag}\n ${chalk.dim(reason)}`;
|
|
31
32
|
})
|
|
32
33
|
: [chalk.dim('• No targeted threats identified.')]),
|
|
33
34
|
'',
|
|
34
35
|
chalk.bold('📝 Auditor Summary:'),
|
|
35
|
-
summary,
|
|
36
|
+
typeof summary === 'string' ? summary : JSON.stringify(summary, null, 2),
|
|
36
37
|
].join('\n');
|
|
37
38
|
|
|
38
39
|
console.log(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import boxen from 'boxen';
|
|
4
|
+
|
|
5
|
+
export async function checkForUpdates(currentVersion) {
|
|
6
|
+
try {
|
|
7
|
+
// We use a short timeout to prevent hanging the CLI if the network is slow
|
|
8
|
+
const response = await fetch('https://registry.npmjs.org/vanguard-cli/latest', {
|
|
9
|
+
timeout: 1500,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (!response.ok) return;
|
|
13
|
+
|
|
14
|
+
const data = await response.json();
|
|
15
|
+
const latestVersion = data.version;
|
|
16
|
+
|
|
17
|
+
if (latestVersion && latestVersion !== currentVersion) {
|
|
18
|
+
const message = [
|
|
19
|
+
chalk.bold(`Update Available!`),
|
|
20
|
+
`${chalk.dim('Current:')} ${chalk.red(currentVersion)}`,
|
|
21
|
+
`${chalk.dim('Latest: ')} ${chalk.green(latestVersion)}`,
|
|
22
|
+
'',
|
|
23
|
+
chalk.cyan('Run the following to upgrade:'),
|
|
24
|
+
chalk.white.bgBlack(` npm install -g vanguard-cli@latest `),
|
|
25
|
+
].join('\n');
|
|
26
|
+
|
|
27
|
+
console.log(
|
|
28
|
+
boxen(message, {
|
|
29
|
+
padding: 1,
|
|
30
|
+
margin: 1,
|
|
31
|
+
borderStyle: 'round',
|
|
32
|
+
borderColor: 'yellow',
|
|
33
|
+
title: '🚀 Vanguard Upgrade',
|
|
34
|
+
titleAlignment: 'center',
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// Silently ignore update check failures to maintain UX
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
CHANGED
package/scan_output.txt
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
__ __ _ _ _ ____ _ _ _ ____ ____
|
|
2
|
+
\ \ / / / \ | \ | | / ___| | | | | / \ | _ \ | _ \
|
|
3
|
+
\ \ / / / _ \ | \| | | | _ | | | | / _ \ | |_) | | | | |
|
|
4
|
+
\ V / / ___ \ | |\ | | |_| | | |_| | / ___ \ | _ < | |_| |
|
|
5
|
+
\_/ /_/ \_\ |_| \_| \____| \___/ /_/ \_\ |_| \_\ |____/
|
|
6
|
+
|
|
7
|
+
🛡️ Enterprise AI Supply Chain Firewall v3.1.19
|
|
8
|
+
|
|
9
|
+
? 🛡️ Vanguard Enterprise Edition detected a CLONE. Select protection level: (Use
|
|
10
|
+
arrow keys)
|
|
11
|
+
> ΓÜí Quick Audit (Config & Entry Files)
|
|
12
|
+
🛡️ Deep Audit (Full behavioral scanning)
|
|
13
|
+
⚠️ Skip (Direct execution - RISKY) [45D[44C[2K[1A[2K[1A[2K[1A[2K[1A[2K[G? 🛡️ Vanguard Enterprise Edition detected a CLONE. Select protection level: ⚡
|
|
14
|
+
Quick Audit (Config & Entry Files)[1A[34D[112C
|
|
15
|
+
- ⬇️ Isolating repository in sandbox...
|
|
16
|
+
[1B ⚠️ Using Local Rules Only (Offline Fallback)
|
|
17
|
+
|
|
18
|
+
📦 OSV.dev Dependency Audit:
|
|
19
|
+
[90mΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ[39m
|
|
20
|
+
[90mΓöé[39m[31m Dependency [39m[90mΓöé[39m[31m Status [39m[90mΓöé[39m[31m Vulnerabilities [39m[90mΓöé[39m
|
|
21
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
22
|
+
[90mΓöé[39m @babel/core [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
23
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
24
|
+
[90m│[39m @logux/eslint-con… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
25
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
26
|
+
[90mΓöé[39m @lukeed/uuid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
27
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
28
|
+
[90mΓöé[39m @napi-rs/uuid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
29
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
30
|
+
[90m│[39m @originjs/vite-pl… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
31
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
32
|
+
[90mΓöé[39m @size-limit/file [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
33
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
34
|
+
[90m│[39m @size-limit/webpa… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
35
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
36
|
+
[90mΓöé[39m @types/node [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
37
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
38
|
+
[90mΓöé[39m actions-up [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
39
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
40
|
+
[90mΓöé[39m better-node-test [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
41
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
42
|
+
[90mΓöé[39m c8 [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
43
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
44
|
+
[90mΓöé[39m clean-publish [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
45
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
46
|
+
[90mΓöé[39m eslint [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
47
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
48
|
+
[90mΓöé[39m rndm [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
49
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
50
|
+
[90m│[39m secure-random-str… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
51
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
52
|
+
[90mΓöé[39m shortid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
53
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
54
|
+
[90mΓöé[39m size-limit [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
55
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
56
|
+
[90mΓöé[39m terser [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
57
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
58
|
+
[90mΓöé[39m tinybench [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
59
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
60
|
+
[90mΓöé[39m uid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
61
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
62
|
+
[90mΓöé[39m uid-safe [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
63
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
64
|
+
[90mΓöé[39m uuid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
65
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
66
|
+
[90mΓöé[39m vite [90mΓöé[39m 200 [90mΓöé[39m 1 [90mΓöé[39m
|
|
67
|
+
[90mΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ[39m
|
|
68
|
+
|
|
69
|
+
ΓÜí Quick Audit: 5/34 critical files targeted.
|
|
70
|
+
- 🧠 Auditing 5 files...
|
|
71
|
+
Γ£ö Audit Complete: 5 scanned (4 cached, 0 skipped).
|
|
72
|
+
|
|
73
|
+
✅ Quick Audit Passed. Finalizing clone to test-nanoid-log...
|
|
74
|
+
|
|
75
|
+
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
|
|
76
|
+
🤝 Contribute: https://github.com/bazobehram/vanguard
|
|
77
|
+
Γÿò Support: https://www.buymeacoffee.com/bazobehram
|
|
78
|
+
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
|
|
79
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
__ __ _ _ _ ____ _ _ _ ____ ____
|
|
2
|
+
\ \ / / / \ | \ | | / ___| | | | | / \ | _ \ | _ \
|
|
3
|
+
\ \ / / / _ \ | \| | | | _ | | | | / _ \ | |_) | | | | |
|
|
4
|
+
\ V / / ___ \ | |\ | | |_| | | |_| | / ___ \ | _ < | |_| |
|
|
5
|
+
\_/ /_/ \_\ |_| \_| \____| \___/ /_/ \_\ |_| \_\ |____/
|
|
6
|
+
|
|
7
|
+
🛡️ Enterprise AI Supply Chain Firewall v3.1.19
|
|
8
|
+
|
|
9
|
+
? 🛡️ Vanguard Enterprise Edition detected a CLONE. Select protection level: (Use
|
|
10
|
+
arrow keys)
|
|
11
|
+
> ΓÜí Quick Audit (Config & Entry Files)
|
|
12
|
+
🛡️ Deep Audit (Full behavioral scanning)
|
|
13
|
+
⚠️ Skip (Direct execution - RISKY) [45D[44C[2K[1A[2K[1A[2K[1A[2K[1A[2K[G? 🛡️ Vanguard Enterprise Edition detected a CLONE. Select protection level: ⚡
|
|
14
|
+
Quick Audit (Config & Entry Files)[1A[34D[112C
|
|
15
|
+
- ⬇️ Isolating repository in sandbox...
|
|
16
|
+
[1B ⚠️ Using Local Rules Only (Offline Fallback)
|
|
17
|
+
|
|
18
|
+
📦 OSV.dev Dependency Audit:
|
|
19
|
+
[90mΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ[39m
|
|
20
|
+
[90mΓöé[39m[31m Dependency [39m[90mΓöé[39m[31m Status [39m[90mΓöé[39m[31m Vulnerabilities [39m[90mΓöé[39m
|
|
21
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
22
|
+
[90m│[39m @google/generativ… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
23
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
24
|
+
[90mΓöé[39m boxen [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
25
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
26
|
+
[90mΓöé[39m chalk [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
27
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
28
|
+
[90mΓöé[39m cli-table3 [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
29
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
30
|
+
[90mΓöé[39m commander [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
31
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
32
|
+
[90mΓöé[39m conf [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
33
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
34
|
+
[90mΓöé[39m crypto-js [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
35
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
36
|
+
[90mΓöé[39m figlet [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
37
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
38
|
+
[90mΓöé[39m fs-extra [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
39
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
40
|
+
[90mΓöé[39m inquirer [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
41
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
42
|
+
[90mΓöé[39m nanoid [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
43
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
44
|
+
[90mΓöé[39m node-fetch [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
45
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
46
|
+
[90mΓöé[39m ora [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
47
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
48
|
+
[90mΓöé[39m p-limit [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
49
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
50
|
+
[90mΓöé[39m simple-git [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
51
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
52
|
+
[90mΓöé[39m @eslint/js [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
53
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
54
|
+
[90m│[39m @release-it/conve… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
55
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
56
|
+
[90mΓöé[39m eslint [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
57
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
58
|
+
[90m│[39m eslint-config-pre… [90m│[39m 200 [90m│[39m 0 [90m│[39m
|
|
59
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
60
|
+
[90mΓöé[39m eslint-plugin-node [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
61
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
62
|
+
[90mΓöé[39m globals [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
63
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
64
|
+
[90mΓöé[39m nock [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
65
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
66
|
+
[90mΓöé[39m prettier [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
67
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
68
|
+
[90mΓöé[39m release-it [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
69
|
+
[90mΓö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ[39m
|
|
70
|
+
[90mΓöé[39m vitest [90mΓöé[39m 200 [90mΓöé[39m 0 [90mΓöé[39m
|
|
71
|
+
[90mΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ[39m[90mΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ[39m
|
|
72
|
+
|
|
73
|
+
ΓÜí Quick Audit: 2/68 critical files targeted.
|
|
74
|
+
- 🧠 Auditing 2 files...
|
|
75
|
+
Γ£ö Audit Complete: 2 scanned (1 cached, 0 skipped).
|
|
76
|
+
|
|
77
|
+
╔═══════════════════════════ ⚠️ HIGH RISK DETECTED ════════════════════════════╗
|
|
78
|
+
Γòæ Γòæ
|
|
79
|
+
Γòæ Verdict: BLOCK Γòæ
|
|
80
|
+
Γòæ Risk Score: 99/100 Γòæ
|
|
81
|
+
Γòæ Γòæ
|
|
82
|
+
║ 🚨 Detailed Threat Audit: ║
|
|
83
|
+
Γòæ ΓÇó [test\fixtures\malicious\index.js:7] (Secret Exfiltration) Γòæ
|
|
84
|
+
Γòæ Reading and exfiltrating the contents of .env file to an external Γòæ
|
|
85
|
+
Γòæ endpoint. Γòæ
|
|
86
|
+
Γòæ ΓÇó [test\fixtures\malicious\index.js:14] (Obfuscation & Evasion) Γòæ
|
|
87
|
+
Γòæ Using Base64 encoding followed by eval() to execute obfuscated code. Γòæ
|
|
88
|
+
Γòæ ΓÇó [test\fixtures\malicious\index.js:23] (Spyware/Harvesting) Γòæ
|
|
89
|
+
Γòæ Collecting system and network information, which could be used for Γòæ
|
|
90
|
+
Γòæ unauthorized surveillance. Γòæ
|
|
91
|
+
Γòæ ΓÇó [test\fixtures\malicious\index.js:30] (Web3/Wallet Draining) Γòæ
|
|
92
|
+
Γòæ Simulating a fraudulent transaction request to drain cryptocurrency Γòæ
|
|
93
|
+
Γòæ wallets. Γòæ
|
|
94
|
+
Γòæ Γòæ
|
|
95
|
+
║ 📝 Auditor Summary: ║
|
|
96
|
+
Γòæ Enterprise QUICK Audit identified multiple high-risk vectors. Γòæ
|
|
97
|
+
Γòæ Γòæ
|
|
98
|
+
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
🛡️ Malware Detected! Clone aborted. Your disk is safe.
|
|
102
|
+
|
|
103
|
+
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
|
|
104
|
+
🤝 Contribute: https://github.com/bazobehram/vanguard
|
|
105
|
+
Γÿò Support: https://www.buymeacoffee.com/bazobehram
|
|
106
|
+
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
|
|
107
|
+
|