My First Ethical Open Redirect Scanner: From Zero to Shipped
Source: Dev.to
Introduction
I built an ethical open‑redirect vulnerability scanner in Node.js. The tool automates the detection of open‑redirect parameters, includes async parallel scanning, rate‑limiting to avoid denial‑of‑service, and exports results as JSON for easy logging.
Features
- Batch testing – reads URLs from a text file for efficient scans.
- Async parallel scans – maximises speed while staying responsible.
- Rate limiting – adds delays between requests to prevent accidental DoS.
- JSON export – automatically generates
results.jsonwith scan outcomes.
Installation
git clone https://github.com/ethicals7s/ethicals7s-redirect-hunter
cd ethicals7s-redirect-hunter
npm install
Usage
-
Create a
urls.txtfile with one URL per line (use only safe, permission‑based targets). Example:https://www.google.com/url?q=https://evil.com https://example.com https://www.koni-store.ru/bitrix/redirect.php?event1=&event2=&event3=&goto=https://google.com -
Run the scanner:
node index.js scan
Example Output
Scanning for open redirects (ethical tests only)...
https://www.google.com/url?q=https://evil.com is VULNERABLE.
https://example.com is SAFE.
https://www.koni-store.ru/bitrix/redirect.php?event1=&event2=&event3=&goto=https://google.com is VULNERABLE.
results.json (auto‑generated):
[
"https://www.google.com/url?q=https://evil.com",
"https://example.com",
"https://www.koni-store.ru/bitrix/redirect.php?event1=&event2=&event3=&goto=https://google.com"
]
Code Snippet (index.js)
// index.js
const MALICIOUS_DOMAIN = 'evil.com';
const INPUT_FILE = 'urls.txt';
const fs = require('fs').promises;
const fetch = require('node-fetch');
async function checkForOpenRedirect(url) {
try {
const testUrl = `${url}?redirect=https://${MALICIOUS_DOMAIN}`;
const response = await fetch(testUrl, { redirect: 'manual' });
const isVulnerable = response.headers.get('location')?.includes(MALICIOUS_DOMAIN);
return { url, status: isVulnerable ? 'VULNERABLE' : 'SAFE' };
} catch (error) {
console.error(`Error checking ${url}: ${error.message}`);
return { url, status: 'ERROR' };
}
}
async function main(file = INPUT_FILE) {
try {
const data = await fs.readFile(file, 'utf8');
const urls = data.split('\n').filter(Boolean);
const results = await Promise.all(urls.map(checkForOpenRedirect));
console.log('Scanning for open redirects (ethical tests only)...');
results.forEach(r => console.log(`${r.url} is ${r.status}.`));
await fs.writeFile('results.json', JSON.stringify(urls, null, 2));
} catch (err) {
console.error(`Input file not found: ${file}`);
}
}
// CLI handling
if (require.main === module) {
const command = process.argv[2];
if (command === 'scan') {
main();
} else {
console.log('Usage: node index.js scan');
}
}
Ethical Use
- Permission‑based testing only – run scans only on domains you own or have explicit consent to test.
- Report any findings responsibly to the affected parties.
- Do not use this tool for production scans without proper authorization.