Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function executeUserScript() {
var userScript = document.getElementById('userScript').value;
eval(userScript);
}
61 changes: 61 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const express = require('express');
const axios = require('axios');
const { URL } = require('url');
const dns = require('dns').promises;
const app = express();


function isPrivateIp(ip) {
return ip === '::1' ||
/^127\./.test(ip) ||
/^10\./.test(ip) ||
/^192\.168\./.test(ip) ||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(ip) ||
ip.startsWith('fc') || ip.startsWith('fd') ||
ip.startsWith('fe80:');
}

app.get('/', (req, res) => {
res.send('Hello World');
});


app.get('/fetch', async (req, res) => {
const url = req.query.url;
let parsedUrl;
try {
parsedUrl = new URL(url);
} catch (e) {
return res.status(400).send('Invalid URL');
}
const hostname = parsedUrl.hostname;
if (!['http:', 'https:'].includes(parsedUrl.protocol) ||
hostname === 'localhost' ||
hostname === '127.0.0.1' ||
hostname === '::1' ||
/^(10|127)\./.test(hostname) ||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname) ||
/^192\.168\./.test(hostname)) {
return res.status(400).send('URL not allowed');
}
try {
// DNS resolution to prevent DNS rebinding
try {
const addresses = await dns.lookup(parsedUrl.hostname, { all: true });
for (const { address } of addresses) {
if (isPrivateIp(address)) {
return res.status(400).send('URL not allowed');
}
}
} catch (e) {
return res.status(400).send('Invalid hostname');
}

const resp = await axios.get(url);
res.send(resp.data);
Comment on lines +54 to +55

@zeropath-ai-staging zeropath-ai-staging Bot Jun 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSRF: /fetch endpoint does not validate redirect targets (Severity: MEDIUM)

Server-side request forgery (SSRF) can occur because the /fetch endpoint does not validate redirect targets, allowing attackers to access internal services. While the initial URL is checked, an attacker can host a server that redirects to internal resources, such as http://127.0.0.1:6379. This bypasses SSRF protections because axios on line 54 follows redirects by default, resulting in sensitive data from internal services being returned to the attacker via res.send(resp.data) on line 55.
View details in ZeroPath

Suggested change
const resp = await axios.get(url);
res.send(resp.data);
const resp = await axios.get(url, { maxRedirects: 0 });
res.send(resp.data);

💬 Reply @zeropath-ai false-positive because … or @zeropath-ai accepted-risk because … to triage this finding, or ask it any question.

All commands

} catch (e) {
res.status(500).send(e.message);
}
});

app.listen(3000, () => console.log('HTTP server on port 3000'));
5 changes: 5 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

echo "<h>" +$_GET["search"] + "</h>";

?>