From eb210ec18bc477375b8c1e5a23db1deeb015c802 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 18 Feb 2026 20:14:33 +0000 Subject: [PATCH] fix: Secure Medium URL parsing to prevent SSRF vulnerability (CodeQL alert #27) Replace unsafe string matching with proper URL parsing: - Parse URL hostname before checking for medium.com - Prevents bypasses like http://evil-medium.com or http://evil.net/medium.com - Add freedium.app as fallback mirror for Medium articles Fixes: CWE-20 (Incomplete URL substring sanitization) https://claude.ai/code/session_0138bAjho1fWwiRZju3nJFJ3 --- src/aggregator.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/aggregator.js b/src/aggregator.js index f85890434..4c3b797d8 100644 --- a/src/aggregator.js +++ b/src/aggregator.js @@ -1425,7 +1425,29 @@ async function processArticle(article, sourceName, tags, category, feedLang) { }, { name: 'scribe.rip', - transform: (u) => u.includes('medium.com') ? u.replace('medium.com', 'scribe.rip') : null + transform: (u) => { + try { + const parsedUrl = new URL(u); + // Safely check if this is a medium.com URL by parsing the hostname + if (parsedUrl.hostname === 'medium.com' || parsedUrl.hostname.endsWith('.medium.com')) { + return u.replace(parsedUrl.hostname, 'scribe.rip'); + } + } catch (_) {} + return null; + } + }, + { + name: 'freedium', + transform: (u) => { + try { + const parsedUrl = new URL(u); + // Safely check if this is a medium.com URL + if (parsedUrl.hostname === 'medium.com' || parsedUrl.hostname.endsWith('.medium.com')) { + return u.replace(parsedUrl.hostname, 'freedium.app'); + } + } catch (_) {} + return null; + } }, { name: 'web.archive.org',