oobabooga/textgen · error · ValueError

Invalid URL: backslashes are not allowed

Error message

Invalid URL: backslashes are not allowed

What it means

Part of the SSRF guard in _validate_url(). A backslash in the URL is rejected outright because Python's urlparse and HTTP libraries can disagree about how they treat '\' (some parsers treat it as a path separator like '/'), letting an attacker craft a URL that passes validation but is fetched against a different target (GHSA-27xf-58m5-vxmc). Any URL containing '\' fails before scheme or host checks run.

Source

Thrown at modules/web_search.py:20

import ipaddress
import socket
from concurrent.futures import as_completed
from datetime import datetime
from urllib.parse import urljoin, urlparse

import requests
from ddgs import DDGS

from modules import shared
from modules.logging_colors import logger


def _validate_url(url):
    """Validate that a URL is safe to fetch (not targeting private/internal networks)."""
    # Reject characters that cause parsing discrepancies between urlparse and requests,
    # which can be exploited to bypass SSRF protections (GHSA-27xf-58m5-vxmc).
    if '\\' in url:
        raise ValueError("Invalid URL: backslashes are not allowed")

    parsed = urlparse(url)
    if parsed.scheme not in ('http', 'https'):
        raise ValueError(f"Unsupported URL scheme: {parsed.scheme}")

    if '@' in parsed.netloc:
        raise ValueError("Invalid URL: userinfo (credentials) in URLs is not allowed")

    hostname = parsed.hostname
    if not hostname:
        raise ValueError("No hostname in URL")

    # Resolve hostname and check all returned addresses
    try:
        for family, _, _, _, sockaddr in socket.getaddrinfo(hostname, None):
            ip = ipaddress.ip_address(sockaddr[0])
            if not ip.is_global:
                raise ValueError(f"Access to non-public address {ip} is blocked")

View on GitHub (pinned to ed888c71f2)

Solutions

  1. Sanitize the URL before fetching: replace backslashes with forward slashes if the intent is a path separator, or reject/percent-encode them.
  2. If the URL comes from user input, validate/normalize it client-side before submitting to the search or web-fetch API.
  3. If it comes from a redirect, this error is the guard working as intended — the target site is emitting malformed or hostile redirects; catch it and surface a friendly message.
  4. Check for copy/paste artifacts like trailing '\\' or 'https:\\example.com' (double backslash after scheme) and fix to 'https://'.

Example fix

# before
result = download_web_page('https:\\example.com\\page')  # raises ValueError

# after
url = url.strip().replace('\\', '/')
result = download_web_page(url)
Defensive patterns

Strategy: validation

Validate before calling

def is_fetchable_url(url: str) -> bool:
    return isinstance(url, str) and '\\' not in url and url.startswith(('http://', 'https://'))

url = url.strip().replace('\\', '/')  # normalize accidental Windows-style slashes
if not is_fetchable_url(url):
    raise ValueError(f'Not a fetchable http(s) URL: {url!r}')

Try / catch

try:
    resp = safe_get(url)
except ValueError as e:
    if 'backslash' in str(e):
        url = url.replace('\\', '/')
        resp = safe_get(url)  # one normalized retry, then give up
    else:
        raise

Prevention

When it happens

Trigger: Calling web-search/page-download functions (safe_get, download_web_page, etc.) with a URL containing a literal backslash, e.g. copied from Windows-style text ('https://example.com\path'), a mis-encoded redirect target, or a maliciously crafted redirect Location header containing backslashes.

Common situations: User pastes a URL copied from Windows docs or chat that uses backslashes; a search result or RSS feed contains malformed URLs; a redirect chain returns a Location value with unescaped backslashes; penetration testing / security scanning of the web-fetch endpoint.

Related errors


AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15). Data as JSON: /api/errors/62407f5c787172a9. Report an issue: GitHub.