Get this on every PR automatically. Webhook fires, AI reviews, you approve.
Install on axios/axios →
// reviewed by pulllight
PullLight found 2 issues
2 critical
// convert to your repo
PullLight caught 2 2 critical on this PR.
Install on axios/axios to get this on every PR automatically — 60 seconds.
Findings
2 issues
critical
injection
**SSRF via fetch() with request-derived URL**: `const response = await fetch(req.body.callbackUrl)` passes a request-derived URL directly to an HTTP client. An attacker who controls this value can make the server fetch internal services (metadata APIs, databases, Redis, internal dashboards) or enumerate private network addresses — potentially leading to credential theft, data exfiltration, or lateral movement.
**Fix**: Validate the URL's hostname against an explicit allowlist before making any outbound request:
```js
const parsed = new URL(callbackUrl);
if (!ALLOWED_HOSTS.includes(parsed.hostname)) throw new Error('SSRF: host not allowed');
```
Or use a library like `ssrf-req-filter` or `private-ip` to block RFC-1918 addresses. Never pass request-derived values directly to `fetch`, `axios`, or `http.get`.
// src/adapters/fetch.js:34
⚡ Suggested fix
// TODO: define ALLOWED_FETCH_HOSTS = ['api.example.com', 'hooks.example.com']
const _fetchUrl = new URL(req.body.callbackUrl);
if (!ALLOWED_FETCH_HOSTS.includes(_fetchUrl.hostname)) throw new Error('SSRF: host not allowed');
const response = await fetch(req.body.callbackUrl, { method: 'POST', body: JSON.stringify(payload) });
critical
injection
**SSRF via axios request with request-derived URL**: `await axios.post(req.query.notifyUrl, data)` passes a query parameter directly to axios without hostname validation. An attacker can supply `http://169.254.169.254/latest/meta-data/` (AWS metadata) or `http://localhost:6379/` (Redis) as the notification URL, causing the server to exfiltrate sensitive internal data or probe the private network.
**Fix**: Validate the URL's hostname against an explicit allowlist before making any outbound request:
```js
// TODO: define ALLOWED_FETCH_HOSTS = ['api.example.com']
const _axiosUrl = new URL(req.query.notifyUrl);
if (!ALLOWED_FETCH_HOSTS.includes(_axiosUrl.hostname)) throw new Error('SSRF: host not allowed');
```
// src/adapters/fetch.js:51
⚡ Suggested fix
// TODO: define ALLOWED_FETCH_HOSTS = ['api.example.com']
const _axiosUrl = new URL(req.query.notifyUrl);
if (!ALLOWED_FETCH_HOSTS.includes(_axiosUrl.hostname)) throw new Error('SSRF: host not allowed');
await axios.post(req.query.notifyUrl, data);