arnav-audit 1.0.1 → 1.0.4
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/LICENSE +21 -0
- package/README.md +103 -37
- package/bin/cli.js +92 -89
- package/package.json +25 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arnav
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,46 +1,100 @@
|
|
|
1
1
|
# arnav-audit
|
|
2
2
|
|
|
3
|
-
> Autonomous Internal Security, Memory Leakage & Invisible UI/UX Interface Auditor
|
|
3
|
+
> Autonomous Internal Security, Memory Leakage & Invisible UI/UX Interface Auditor
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/arnav-audit)
|
|
6
|
+
[](https://github.com/arnnnnaaavvvvv/MEJOR)
|
|
6
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://nodejs.org/)
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
`arnav-audit` is a high-speed, zero-dependency command-line interface and package designed to audit local codebases for critical security credential leaks, React/JS memory leaks, and invisible frontend UI/UX interface defects.
|
|
9
11
|
|
|
10
12
|
---
|
|
11
13
|
|
|
12
|
-
## Quickstart
|
|
14
|
+
## 🚀 Quickstart: Installation to Final Execution Pipeline
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Follow this 4-step workflow to install, verify, and run audits across your projects:
|
|
15
17
|
|
|
18
|
+
### Step 1: Install Globally
|
|
19
|
+
Choose any method to install or run the CLI:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Method A: Install globally via npm
|
|
23
|
+
npm install -g arnav-audit
|
|
24
|
+
|
|
25
|
+
# Method B: Direct install from GitHub (works for anyone without npm login)
|
|
26
|
+
npm install -g github:arnnnnaaavvvvv/MEJOR
|
|
27
|
+
|
|
28
|
+
# Method C: If working inside this cloned repository
|
|
29
|
+
npm install -g . --force
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
*(Alternatively, run instantly with zero installation: `npx github:arnnnnaaavvvvv/MEJOR .` or `npx arnav-audit .`)*
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### Step 2: Verify the CLI Binary
|
|
37
|
+
Confirm that `arnav-audit` is globally registered in your terminal:
|
|
38
|
+
```bash
|
|
39
|
+
arnav-audit --version
|
|
40
|
+
# Output: arnav-audit v1.0.4
|
|
41
|
+
|
|
42
|
+
arnav-audit --help
|
|
43
|
+
# Displays available flags, rules, and example commands
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### Step 3: Run the Codebase Audit
|
|
49
|
+
Navigate to any project directory and run the audit:
|
|
16
50
|
```bash
|
|
17
|
-
# Audit current
|
|
18
|
-
|
|
51
|
+
# Audit the current project directory
|
|
52
|
+
arnav-audit .
|
|
53
|
+
|
|
54
|
+
# Audit a specific subdirectory or file
|
|
55
|
+
arnav-audit ./src
|
|
56
|
+
|
|
57
|
+
# List every single file inspected
|
|
58
|
+
arnav-audit . --files
|
|
59
|
+
|
|
60
|
+
# Scan exclusively for credentials & secrets
|
|
61
|
+
arnav-audit . --security-only
|
|
62
|
+
|
|
63
|
+
# Scan exclusively for memory & event listener leaks
|
|
64
|
+
arnav-audit . --leakage-only
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
19
68
|
|
|
20
|
-
|
|
21
|
-
|
|
69
|
+
### Step 4: Generate Automated AI Fix Prompts (Final Step)
|
|
70
|
+
Generate ready-to-paste prompts formatted specifically for Cursor, Claude Code, or Antigravity:
|
|
71
|
+
```bash
|
|
72
|
+
arnav-audit . --prompts
|
|
73
|
+
```
|
|
22
74
|
|
|
23
|
-
|
|
24
|
-
|
|
75
|
+
Or pipe machine-readable JSON into CI/CD quality gates:
|
|
76
|
+
```bash
|
|
77
|
+
arnav-audit . --json > audit-report.json
|
|
25
78
|
```
|
|
26
79
|
|
|
27
80
|
---
|
|
28
81
|
|
|
29
|
-
##
|
|
82
|
+
## 🛡️ Detection Capabilities
|
|
30
83
|
|
|
31
84
|
### 1. Internal Security & Credential Leakage
|
|
32
85
|
- **Hardcoded Secret Keys**: Scans for exposed AWS access keys (`AKIA...`), OpenAI API keys (`sk-...`), GitHub personal access tokens (`ghp_...`), Stripe live secret keys (`sk_live_...`), and private key blocks (`-----BEGIN RSA PRIVATE KEY-----`).
|
|
33
|
-
- **Exposed Configuration**: Detects committed `.env` and `.env.local` files in git trees.
|
|
86
|
+
- **Exposed Configuration**: Detects committed `.env` and `.env.local` files in git trees missing `.gitignore` coverage.
|
|
34
87
|
- **XSS & Code Injection Vectors**: Unsanitized `dangerouslySetInnerHTML`, `eval()`, and `new Function()` invocations.
|
|
88
|
+
- **Backend Injection Patterns**: Flags raw string interpolations in SQL queries and unsafe `subprocess(..., shell=True)` execution.
|
|
35
89
|
|
|
36
|
-
### 2. Major & Minor Memory Leakage
|
|
90
|
+
### 2. Major & Minor Memory & Resource Leakage
|
|
37
91
|
- **Hook Listener Leaks**: `addEventListener` inside React `useEffect` hooks missing clean-up `removeEventListener` callbacks.
|
|
38
|
-
- **Timer Leaks**: `setInterval` and `setTimeout` without unmount `clearInterval` teardowns.
|
|
39
|
-
- **Global Scope Pollution**: Accidental state assignments to the global `window` object.
|
|
92
|
+
- **Timer Leaks**: `setInterval` and `setTimeout` initialized without unmount `clearInterval` teardowns.
|
|
93
|
+
- **Global Scope Pollution**: Accidental state assignments to the global `window` object preventing garbage collection.
|
|
40
94
|
- **Residual Logging**: Production `console.log` statements leaking internal state and data payloads.
|
|
41
95
|
|
|
42
96
|
### 3. Invisible Interface & UI/UX Traps
|
|
43
|
-
- **iOS Safari Auto-Zoom Trap (`UX-IOS-AUTOZOOM`)**: Form inputs with `font-size < 16px` triggering mandatory mobile viewport zooming.
|
|
97
|
+
- **iOS Safari Auto-Zoom Trap (`UX-IOS-AUTOZOOM`)**: Form inputs with `font-size < 16px` triggering mandatory mobile viewport zooming on focus.
|
|
44
98
|
- **300ms Touch Latency (`UX-TAP-LATENCY`)**: Interactive elements missing `touch-action: manipulation`.
|
|
45
99
|
- **Obliterated Focus Rings (`A11Y-FOCUS-OBLITERATED`)**: `outline: none` removing keyboard accessibility indicators (WCAG 2.4.7).
|
|
46
100
|
- **Flexbox Icon Collapse (`UI-FLEX-SQUISH`)**: Distorted SVG icons inside flex containers missing `flex-shrink: 0`.
|
|
@@ -49,30 +103,28 @@ npx arnav-audit https://mejor-iota.vercel.app
|
|
|
49
103
|
|
|
50
104
|
---
|
|
51
105
|
|
|
52
|
-
##
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
# Generate ready-to-paste AI fix prompts for Cursor & Claude Code
|
|
56
|
-
npx arnav-audit --prompts
|
|
57
|
-
|
|
58
|
-
# Scan exclusively for security credentials and XSS vulnerabilities
|
|
59
|
-
npx arnav-audit --security-only
|
|
60
|
-
|
|
61
|
-
# Scan exclusively for memory & event listener leaks
|
|
62
|
-
npx arnav-audit --leakage-only
|
|
106
|
+
## 🛠️ CLI Reference & Flags
|
|
63
107
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
108
|
+
| Flag | Shorthand | Description |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `[directory]` | — | Target path to audit (defaults to `.`) |
|
|
111
|
+
| `--files` | `--list` | List every scanned file with inspection status |
|
|
112
|
+
| `--verbose` | — | Display detailed scan logs and file-by-file verification |
|
|
113
|
+
| `--prompts` | `--fix` | Pre-compile copy-paste AI fix prompts for Cursor / Claude Code |
|
|
114
|
+
| `--security-only`| `--security` | Scan exclusively for credentials, secrets & injection vectors |
|
|
115
|
+
| `--leakage-only` | `--leakage` | Scan exclusively for event listeners, timers & window leaks |
|
|
116
|
+
| `--json` | — | Output raw machine-readable JSON for CI/CD pipelines |
|
|
117
|
+
| `--version` | `-v` | Display CLI version |
|
|
118
|
+
| `--help` | `-h` | Display help screen |
|
|
67
119
|
|
|
68
120
|
---
|
|
69
121
|
|
|
70
|
-
## GitHub Actions CI/CD
|
|
122
|
+
## 🚀 GitHub Actions CI/CD Quality Gate
|
|
71
123
|
|
|
72
|
-
|
|
124
|
+
Add `arnav-audit` to your `.github/workflows/audit.yml` to automatically prevent credential leakage or broken mobile viewports from merging into production:
|
|
73
125
|
|
|
74
126
|
```yaml
|
|
75
|
-
name:
|
|
127
|
+
name: Codebase Quality & Security Gate
|
|
76
128
|
on: [push, pull_request]
|
|
77
129
|
|
|
78
130
|
jobs:
|
|
@@ -89,7 +141,21 @@ jobs:
|
|
|
89
141
|
|
|
90
142
|
---
|
|
91
143
|
|
|
92
|
-
##
|
|
144
|
+
## 🧪 Local Development & Testing
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Run unit tests
|
|
148
|
+
npm test
|
|
149
|
+
|
|
150
|
+
# Run audit locally
|
|
151
|
+
node bin/cli.js .
|
|
152
|
+
|
|
153
|
+
# Check help output
|
|
154
|
+
node bin/cli.js --help
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 📄 License
|
|
93
160
|
|
|
94
|
-
|
|
95
|
-
👉 [**https://mejor-iota.vercel.app**](https://mejor-iota.vercel.app)
|
|
161
|
+
MIT © [Arnav](https://github.com/arnav)
|
package/bin/cli.js
CHANGED
|
@@ -3,13 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* arnav-audit - Automated Internal Security, Memory Leakage & UI/UX Interface Auditor
|
|
5
5
|
* Author: Arnav
|
|
6
|
-
* Website: https://mejor-iota.vercel.app
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
const fs = require('fs');
|
|
10
9
|
const path = require('path');
|
|
11
|
-
const https = require('https');
|
|
12
|
-
const http = require('http');
|
|
13
10
|
|
|
14
11
|
// Terminal ANSI styling
|
|
15
12
|
const C = {
|
|
@@ -46,7 +43,7 @@ ${C.emerald}${C.bold} _ ____ _ _ ___ __ _ _ _ ____ ___ __
|
|
|
46
43
|
/ ___ \\| _ <| |\\ |/ ___ \\ V / / ___ \\ |_| | |_| | | | |
|
|
47
44
|
/_/ \\_\\_| \\_\\_| \\_/_/ \\_\\_/ /_/ \\_\\___/|____/___| |_| ${C.reset}
|
|
48
45
|
${C.dim}Autonomous Security, Memory Leakage & Invisible UI/UX Auditor${C.reset}
|
|
49
|
-
${C.gray}Engine by Arnav •
|
|
46
|
+
${C.gray}Engine by Arnav • Codebase & Interface Quality Gate${C.reset}
|
|
50
47
|
`;
|
|
51
48
|
|
|
52
49
|
// Parse CLI arguments
|
|
@@ -57,6 +54,8 @@ const options = {
|
|
|
57
54
|
prompts: false,
|
|
58
55
|
securityOnly: false,
|
|
59
56
|
leakageOnly: false,
|
|
57
|
+
verbose: false,
|
|
58
|
+
files: false,
|
|
60
59
|
help: false,
|
|
61
60
|
version: false,
|
|
62
61
|
};
|
|
@@ -65,6 +64,8 @@ for (let i = 0; i < args.length; i++) {
|
|
|
65
64
|
const arg = args[i];
|
|
66
65
|
if (arg === '--help' || arg === '-h') options.help = true;
|
|
67
66
|
else if (arg === '--version' || arg === '-v') options.version = true;
|
|
67
|
+
else if (arg === '--verbose') options.verbose = true;
|
|
68
|
+
else if (arg === '--files' || arg === '--list') options.files = true;
|
|
68
69
|
else if (arg === '--json') options.json = true;
|
|
69
70
|
else if (arg === '--prompts' || arg === '--fix') options.prompts = true;
|
|
70
71
|
else if (arg === '--security' || arg === '--security-only') options.securityOnly = true;
|
|
@@ -73,7 +74,13 @@ for (let i = 0; i < args.length; i++) {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
if (options.version) {
|
|
76
|
-
|
|
77
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
78
|
+
let ver = '1.0.3';
|
|
79
|
+
try {
|
|
80
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
81
|
+
ver = pkg.version || ver;
|
|
82
|
+
} catch (e) {}
|
|
83
|
+
console.log(`arnav-audit v${ver}`);
|
|
77
84
|
process.exit(0);
|
|
78
85
|
}
|
|
79
86
|
|
|
@@ -84,10 +91,11 @@ ${C.bold}USAGE:${C.reset}
|
|
|
84
91
|
npx arnav-audit [target] [options]
|
|
85
92
|
|
|
86
93
|
${C.bold}TARGETS:${C.reset}
|
|
87
|
-
[directory] Path to local project root (defaults to current directory ".")
|
|
88
|
-
[https://url] Live website URL to run headless CDP telemetry & 200 checks
|
|
94
|
+
[directory] Path to local project root or directory (defaults to current directory ".")
|
|
89
95
|
|
|
90
96
|
${C.bold}OPTIONS:${C.reset}
|
|
97
|
+
--files, --list List every single scanned file path with inspection status
|
|
98
|
+
--verbose Display detailed scan logs and file-by-file verification
|
|
91
99
|
--prompts, --fix Generate copy-paste AI fix prompts for Cursor & Claude Code
|
|
92
100
|
--security-only Scan exclusively for exposed credentials, secrets & XSS vectors
|
|
93
101
|
--leakage-only Scan exclusively for memory, event listeners & viewport leaks
|
|
@@ -97,8 +105,10 @@ ${C.bold}OPTIONS:${C.reset}
|
|
|
97
105
|
|
|
98
106
|
${C.bold}EXAMPLES:${C.reset}
|
|
99
107
|
$ npx arnav-audit .
|
|
100
|
-
$ npx arnav-audit
|
|
108
|
+
$ npx arnav-audit ./src
|
|
109
|
+
$ npx arnav-audit . --files
|
|
101
110
|
$ npx arnav-audit . --prompts
|
|
111
|
+
$ npx arnav-audit . --security-only
|
|
102
112
|
$ npx arnav-audit . --json > audit-report.json
|
|
103
113
|
`);
|
|
104
114
|
process.exit(0);
|
|
@@ -141,20 +151,29 @@ const BINARY_EXTS = new Set([
|
|
|
141
151
|
|
|
142
152
|
function walkDir(dir, fileList = []) {
|
|
143
153
|
try {
|
|
154
|
+
const stat = fs.statSync(dir);
|
|
155
|
+
if (!stat.isDirectory()) {
|
|
156
|
+
const ext = path.extname(dir).toLowerCase();
|
|
157
|
+
if (!BINARY_EXTS.has(ext)) {
|
|
158
|
+
fileList.push(dir);
|
|
159
|
+
}
|
|
160
|
+
return fileList;
|
|
161
|
+
}
|
|
162
|
+
|
|
144
163
|
const files = fs.readdirSync(dir);
|
|
145
164
|
for (const file of files) {
|
|
146
165
|
if (IGNORED_DIRS.has(file)) continue;
|
|
147
166
|
const fullPath = path.join(dir, file);
|
|
148
167
|
try {
|
|
149
|
-
const
|
|
150
|
-
if (
|
|
168
|
+
const fileStat = fs.statSync(fullPath);
|
|
169
|
+
if (fileStat.isDirectory()) {
|
|
151
170
|
// Allow .github workflow directory while ignoring other hidden dot-folders
|
|
152
171
|
if (file.startsWith('.') && file !== '.github') continue;
|
|
153
172
|
if (file.includes('worktree')) continue;
|
|
154
173
|
walkDir(fullPath, fileList);
|
|
155
174
|
} else {
|
|
156
175
|
// Skip the scanner's own CLI script so its rule definitions are not self-flagged
|
|
157
|
-
if (file === 'cli.js' && fullPath.includes('
|
|
176
|
+
if (file === 'cli.js' && fullPath.includes('bin')) continue;
|
|
158
177
|
// Skip OS metadata
|
|
159
178
|
if (file === '.DS_Store' || file === 'Thumbs.db') continue;
|
|
160
179
|
|
|
@@ -312,6 +331,7 @@ const RULES = [
|
|
|
312
331
|
title: 'Residual Debug Console Logging',
|
|
313
332
|
desc: 'Found console.log statements that can leak internal state and data payloads to browser devtools.',
|
|
314
333
|
appliesTo: ['.js', '.jsx', '.ts', '.tsx'],
|
|
334
|
+
ignoreInTests: true,
|
|
315
335
|
regex: /console\.log\s*\(/g,
|
|
316
336
|
remedy: 'Remove console.log statements or strip via build compiler (e.g. babel-plugin-transform-remove-console).'
|
|
317
337
|
},
|
|
@@ -398,10 +418,20 @@ function runLocalAudit(targetDir) {
|
|
|
398
418
|
|
|
399
419
|
const files = walkDir(root);
|
|
400
420
|
const issues = [];
|
|
421
|
+
const scannedFiles = [];
|
|
422
|
+
const extCounts = {};
|
|
423
|
+
const dirCounts = {};
|
|
401
424
|
|
|
402
425
|
for (const filePath of files) {
|
|
403
|
-
const relPath = path.relative(root, filePath);
|
|
426
|
+
const relPath = path.relative(root, filePath) || path.basename(filePath);
|
|
404
427
|
const ext = path.extname(filePath).toLowerCase();
|
|
428
|
+
scannedFiles.push(relPath);
|
|
429
|
+
|
|
430
|
+
const extKey = ext || '[config]';
|
|
431
|
+
extCounts[extKey] = (extCounts[extKey] || 0) + 1;
|
|
432
|
+
|
|
433
|
+
const topFolder = relPath.split(path.sep)[0] || '.';
|
|
434
|
+
dirCounts[topFolder] = (dirCounts[topFolder] || 0) + 1;
|
|
405
435
|
|
|
406
436
|
let content = '';
|
|
407
437
|
try {
|
|
@@ -437,6 +467,7 @@ function runLocalAudit(targetDir) {
|
|
|
437
467
|
for (const rule of RULES) {
|
|
438
468
|
if (options.securityOnly && rule.category !== 'Security') continue;
|
|
439
469
|
if (options.leakageOnly && !rule.category.includes('Leakage')) continue;
|
|
470
|
+
if (rule.ignoreInTests && (relPath.toLowerCase().includes('test') || relPath.toLowerCase().includes('spec'))) continue;
|
|
440
471
|
|
|
441
472
|
// Filter by language/file extension if rule specifies appliesTo
|
|
442
473
|
if (rule.appliesTo && !rule.appliesTo.includes(ext)) {
|
|
@@ -449,7 +480,6 @@ function runLocalAudit(targetDir) {
|
|
|
449
480
|
while ((match = rule.regex.exec(content)) !== null) {
|
|
450
481
|
const linesUpToMatch = content.slice(0, match.index).split('\n');
|
|
451
482
|
const lineNum = linesUpToMatch.length;
|
|
452
|
-
const lineContent = linesUpToMatch[linesUpToMatch.length - 1].trim();
|
|
453
483
|
|
|
454
484
|
issues.push({
|
|
455
485
|
id: rule.id,
|
|
@@ -485,84 +515,21 @@ function runLocalAudit(targetDir) {
|
|
|
485
515
|
}
|
|
486
516
|
}
|
|
487
517
|
|
|
488
|
-
return { root, totalFiles: files.length, issues };
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// -------------------------------------------------------------
|
|
492
|
-
// LIVE URL AUDIT ENGINE (Connects to https://mejor-iota.vercel.app)
|
|
493
|
-
// -------------------------------------------------------------
|
|
494
|
-
async function runUrlAudit(url) {
|
|
495
|
-
let targetUrl = url.trim();
|
|
496
|
-
if (!targetUrl.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//)) {
|
|
497
|
-
targetUrl = 'https://' + targetUrl;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const endpoint = `https://mejor-iota.vercel.app/api/v1/scans`;
|
|
501
|
-
|
|
502
|
-
return new Promise((resolve, reject) => {
|
|
503
|
-
const postData = JSON.stringify({ url: targetUrl, mode: 'quick' });
|
|
504
|
-
const parsed = new URL(endpoint);
|
|
505
|
-
|
|
506
|
-
const req = https.request({
|
|
507
|
-
hostname: parsed.hostname,
|
|
508
|
-
port: 443,
|
|
509
|
-
path: parsed.pathname,
|
|
510
|
-
method: 'POST',
|
|
511
|
-
headers: {
|
|
512
|
-
'Content-Type': 'application/json',
|
|
513
|
-
'Content-Length': Buffer.byteLength(postData),
|
|
514
|
-
'User-Agent': 'arnav-audit-cli/1.0',
|
|
515
|
-
},
|
|
516
|
-
timeout: 10000,
|
|
517
|
-
}, (res) => {
|
|
518
|
-
let data = '';
|
|
519
|
-
res.on('data', chunk => data += chunk);
|
|
520
|
-
res.on('end', () => {
|
|
521
|
-
try {
|
|
522
|
-
const parsedRes = JSON.parse(data);
|
|
523
|
-
resolve({ targetUrl, scanId: parsedRes.id, reportUrl: `https://mejor-iota.vercel.app/scans/${parsedRes.id}` });
|
|
524
|
-
} catch (e) {
|
|
525
|
-
resolve({ targetUrl, offline: true });
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
req.on('error', () => {
|
|
531
|
-
resolve({ targetUrl, offline: true });
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
req.write(postData);
|
|
535
|
-
req.end();
|
|
536
|
-
});
|
|
518
|
+
return { root, totalFiles: files.length, scannedFiles, extCounts, dirCounts, issues };
|
|
537
519
|
}
|
|
538
520
|
|
|
539
521
|
// -------------------------------------------------------------
|
|
540
522
|
// MAIN EXECUTION
|
|
541
523
|
// -------------------------------------------------------------
|
|
542
524
|
async function main() {
|
|
543
|
-
|
|
525
|
+
// Reject URL targets clearly
|
|
526
|
+
const isUrl = /^https?:\/\//i.test(options.target) || options.target.includes('.vercel.app');
|
|
544
527
|
|
|
545
528
|
if (isUrl) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
const result = await runUrlAudit(options.target);
|
|
552
|
-
|
|
553
|
-
if (options.json) {
|
|
554
|
-
console.log(JSON.stringify(result, null, 2));
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
console.log(`${C.emerald}✓ Audit Engine Dispatched Successfully!${C.reset}`);
|
|
559
|
-
console.log(`${C.white}• Target: ${C.bold}${result.targetUrl}${C.reset}`);
|
|
560
|
-
if (result.scanId) {
|
|
561
|
-
console.log(`${C.white}• Scan ID: ${C.gray}${result.scanId}${C.reset}`);
|
|
562
|
-
console.log(`${C.white}• Live Report: ${C.emerald}${C.underline}${result.reportUrl}${C.reset}\n`);
|
|
563
|
-
console.log(`${C.dim}Tip: Open the link above to view synchronized Before/After split-view and copy Cursor AI fix prompts.${C.reset}\n`);
|
|
564
|
-
}
|
|
565
|
-
return;
|
|
529
|
+
console.error(`\n${C.rose}${C.bold}Error:${C.reset} ${C.white}URL scanning is not supported in this version of arnav-audit.${C.reset}`);
|
|
530
|
+
console.error(`${C.dim}arnav-audit is a dedicated local codebase auditor for internal security, memory leaks, and UI defects.${C.reset}`);
|
|
531
|
+
console.error(`${C.dim}Please provide a local project directory path instead (e.g. ${C.white}arnav-audit .${C.dim} or ${C.white}arnav-audit ./src${C.dim}).${C.reset}\n`);
|
|
532
|
+
process.exit(1);
|
|
566
533
|
}
|
|
567
534
|
|
|
568
535
|
// Local Project Directory Scan
|
|
@@ -587,6 +554,7 @@ async function main() {
|
|
|
587
554
|
console.log(JSON.stringify({
|
|
588
555
|
target: audit.root,
|
|
589
556
|
totalFiles: audit.totalFiles,
|
|
557
|
+
scannedFiles: audit.scannedFiles,
|
|
590
558
|
score,
|
|
591
559
|
grade,
|
|
592
560
|
counts: {
|
|
@@ -601,25 +569,61 @@ async function main() {
|
|
|
601
569
|
return;
|
|
602
570
|
}
|
|
603
571
|
|
|
572
|
+
// Print all scanned files if --files or --verbose requested
|
|
573
|
+
if (options.files || options.verbose) {
|
|
574
|
+
console.log(`${C.bold}VERIFIED CODEBASE FILES (${audit.totalFiles} files inspected):${C.reset}`);
|
|
575
|
+
audit.scannedFiles.forEach((file, idx) => {
|
|
576
|
+
const fileIssues = audit.issues.filter(i => i.file === file);
|
|
577
|
+
const numStr = String(idx + 1).padStart(3, ' ');
|
|
578
|
+
if (fileIssues.length === 0) {
|
|
579
|
+
console.log(` ${C.gray}[${numStr}/${audit.totalFiles}]${C.reset} ${C.emerald}✓${C.reset} ${file}`);
|
|
580
|
+
} else {
|
|
581
|
+
console.log(` ${C.gray}[${numStr}/${audit.totalFiles}]${C.reset} ${C.rose}✗${C.reset} ${file} ${C.rose}(${fileIssues.length} issues)${C.reset}`);
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
console.log('');
|
|
585
|
+
}
|
|
586
|
+
|
|
604
587
|
// Formatted Terminal Dashboard
|
|
605
588
|
console.log(`${C.dim}————————————————————————————————————————————————————————————————————${C.reset}`);
|
|
606
|
-
console.log(` ${C.bold}AUDIT REPORT OVERVIEW${C.reset} • Scanned ${C.bold}${audit.totalFiles}${C.reset} files`);
|
|
589
|
+
console.log(` ${C.bold}AUDIT REPORT OVERVIEW${C.reset} • Scanned ${C.bold}${audit.totalFiles}${C.reset} files across codebase`);
|
|
607
590
|
console.log(`${C.dim}————————————————————————————————————————————————————————————————————${C.reset}`);
|
|
608
591
|
|
|
609
592
|
const gradeColor = grade.startsWith('A') ? C.emerald : grade === 'B' ? C.cyan : grade === 'C' ? C.amber : C.rose;
|
|
610
593
|
console.log(` Overall Score: ${gradeColor}${C.bold}${score}/100${C.reset} (Grade ${gradeColor}${C.bold}${grade}${C.reset})`);
|
|
611
594
|
console.log(` Findings: ${C.rose}${critical.length} Critical${C.reset} | ${C.amber}${major.length} Major${C.reset} | ${C.cyan}${minor.length} Minor${C.reset} | ${C.gray}${suggestions.length} Suggestions${C.reset}\n`);
|
|
612
595
|
|
|
596
|
+
console.log(` ${C.bold}Full Codebase Coverage Breakdown:${C.reset}`);
|
|
597
|
+
const sortedExts = Object.entries(audit.extCounts).sort((a, b) => b[1] - a[1]);
|
|
598
|
+
sortedExts.forEach(([ext, count]) => {
|
|
599
|
+
let name = 'Source / Script';
|
|
600
|
+
if (ext === '.py') name = 'Python (Backend, Scripts, Tests)';
|
|
601
|
+
else if (ext === '.ts') name = 'TypeScript (Backend, Core, API)';
|
|
602
|
+
else if (ext === '.tsx') name = 'React / Next.js Components';
|
|
603
|
+
else if (ext === '.js') name = 'JavaScript Modules & Configs';
|
|
604
|
+
else if (ext === '.json') name = 'JSON Manifests & Data schemas';
|
|
605
|
+
else if (ext === '.yml' || ext === '.yaml') name = 'GitHub CI & YAML Configs';
|
|
606
|
+
else if (ext === '.css' || ext === '.scss') name = 'CSS & Styling Stylesheets';
|
|
607
|
+
else if (ext === '.html') name = 'HTML Templates & Fixtures';
|
|
608
|
+
else if (ext === '.md') name = 'Documentation & Readmes';
|
|
609
|
+
else if (ext === '[config]') name = 'Config & Dotfiles';
|
|
610
|
+
console.log(` • ${C.cyan}${name.padEnd(42, ' ')}${C.reset} ${C.bold}${count}${C.reset} files (${ext})`);
|
|
611
|
+
});
|
|
612
|
+
console.log('');
|
|
613
|
+
|
|
613
614
|
if (audit.issues.length === 0) {
|
|
614
|
-
console.log(` ${C.emerald}✓ Zero internal security, leakage, or interface defects detected!${C.reset}
|
|
615
|
-
console.log(`
|
|
615
|
+
console.log(` ${C.emerald}✓ Zero internal security, leakage, or interface defects detected!${C.reset}`);
|
|
616
|
+
console.log(` Every file in the codebase was verified. Meets enterprise standards.\n`);
|
|
617
|
+
if (!options.files) {
|
|
618
|
+
console.log(` ${C.dim}Tip: Run with ${C.white}--files${C.dim} to display each individual file path in the terminal.${C.reset}`);
|
|
619
|
+
}
|
|
616
620
|
console.log(`${C.dim}————————————————————————————————————————————————————————————————————${C.reset}\n`);
|
|
617
621
|
return;
|
|
618
622
|
}
|
|
619
623
|
|
|
620
624
|
console.log(`${C.bold}DETECTED INTERNAL ISSUES:${C.reset}\n`);
|
|
621
625
|
|
|
622
|
-
audit.issues.forEach((issue
|
|
626
|
+
audit.issues.forEach((issue) => {
|
|
623
627
|
const badge = issue.tier === 'CRITICAL'
|
|
624
628
|
? `${C.bgRose}${C.white}${C.bold} CRITICAL ${C.reset}`
|
|
625
629
|
: issue.tier === 'MAJOR'
|
|
@@ -655,8 +659,7 @@ async function main() {
|
|
|
655
659
|
console.log(`3. Ensure zero credentials remain in codebase.`);
|
|
656
660
|
console.log(`${C.reset}`);
|
|
657
661
|
} else {
|
|
658
|
-
console.log(`${C.dim}Tip: Run ${C.white}npx arnav-audit --prompts${C.dim} to output ready-to-paste AI copilot fix prompts.${C.reset}`);
|
|
659
|
-
console.log(`${C.dim}Interactive Web Dashboard: ${C.emerald}https://mejor-iota.vercel.app${C.reset}\n`);
|
|
662
|
+
console.log(`${C.dim}Tip: Run ${C.white}npx arnav-audit --prompts${C.dim} to output ready-to-paste AI copilot fix prompts.${C.reset}\n`);
|
|
660
663
|
}
|
|
661
664
|
|
|
662
665
|
console.log(`${C.dim}————————————————————————————————————————————————————————————————————${C.reset}\n`);
|
package/package.json
CHANGED
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arnav-audit",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "Autonomous internal security, memory leakage, and invisible UI/UX interface auditor.",
|
|
5
|
+
"main": "bin/cli.js",
|
|
5
6
|
"bin": {
|
|
6
7
|
"arnav-audit": "bin/cli.js"
|
|
7
8
|
},
|
|
8
|
-
"main": "bin/cli.js",
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"start": "node ./bin/cli.js",
|
|
15
|
-
"test": "node ./
|
|
16
|
+
"test": "node ./test/cli.test.js",
|
|
17
|
+
"audit": "node ./bin/cli.js .",
|
|
18
|
+
"audit:files": "node ./bin/cli.js . --files",
|
|
19
|
+
"audit:verbose": "node ./bin/cli.js . --verbose",
|
|
20
|
+
"audit:fix": "node ./bin/cli.js . --prompts",
|
|
21
|
+
"audit:security": "node ./bin/cli.js . --security-only",
|
|
22
|
+
"audit:leakage": "node ./bin/cli.js . --leakage-only"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/arnnnnaaavvvvv/MEJOR.git"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/arnnnnaaavvvvv/MEJOR#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/arnnnnaaavvvvv/MEJOR/issues"
|
|
16
34
|
},
|
|
17
35
|
"keywords": [
|
|
18
36
|
"audit",
|
|
37
|
+
"cli",
|
|
19
38
|
"security",
|
|
20
39
|
"leakage",
|
|
21
40
|
"memory-leak",
|
|
@@ -24,6 +43,7 @@
|
|
|
24
43
|
"cursor",
|
|
25
44
|
"claude-code",
|
|
26
45
|
"antigravity",
|
|
46
|
+
"quality-gate",
|
|
27
47
|
"arnav"
|
|
28
48
|
],
|
|
29
49
|
"author": "Arnav",
|