crewAIInc/crewAI · error · ValueError

file:// URLs are not allowed: '{url}'. Use a file path inste

Error message

file:// URLs are not allowed: '{url}'. Use a file path instead, or set {_UNSAFE_PATHS_ENV}=true to bypass.

What it means

URL validation guard in safe_path blocking the file:// scheme. Because file:// URLs bypass the path-containment checks (they encode arbitrary absolute paths), the validator rejects them outright and only permits http/https. The error suggests using a plain file path (which goes through validate_file_path containment) or enabling the unsafe-paths env hatch.

Source

Thrown at lib/crewai-tools/src/crewai_tools/security/safe_path.py:212

        The validated URL string.

    Raises:
        ValueError: If the URL uses a blocked scheme or resolves to a
            private/reserved IP address.
    """
    if _is_escape_hatch_enabled():
        logger.warning(
            "%s is enabled — skipping URL validation for: %s",
            _UNSAFE_PATHS_ENV,
            url,
        )
        return url

    parsed = urlparse(url)

    # Block file:// scheme
    if parsed.scheme == "file":
        raise ValueError(
            f"file:// URLs are not allowed: '{url}'. "
            f"Use a file path instead, or set {_UNSAFE_PATHS_ENV}=true to bypass."
        )

    # Only allow http and https
    if parsed.scheme not in ("http", "https"):
        raise ValueError(
            f"URL scheme '{parsed.scheme}' is not allowed. Only http and https are supported."
        )

    if not parsed.hostname:
        raise ValueError(f"URL has no hostname: '{url}'")

    try:
        addrinfos = socket.getaddrinfo(
            parsed.hostname, parsed.port or (443 if parsed.scheme == "https" else 80)
        )
    except socket.gaierror as exc:

View on GitHub (pinned to 754d7323be)

Solutions

  1. Convert file:// URLs to plain filesystem paths and pass them through the file-path API (which enforces base_dir containment): urllib.parse.urlparse(u).path.
  2. If you truly need file URLs in a trusted local context, set the documented _UNSAFE_PATHS_ENV=true — never in production or with untrusted input.
  3. Sanitize user/LLM-supplied sources before they reach the validator: rewrite file:// entries to paths or reject them with your own message.
  4. Do not attempt scheme tricks (FILE://, file:\\\) — urlparse lowercases the scheme, they are also blocked.

Example fix

# before
validate_url("file:///srv/data/doc.html")  # ValueError

# after
from urllib.parse import urlparse
u = "file:///srv/data/doc.html"
assert urlparse(u).scheme == "file"
validated_path = validate_file_path(urlparse(u).path, base_dir="/srv/data")
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def is_web_url(url: str) -> bool:
    return urlparse(url).scheme in ("http", "https") and bool(urlparse(url).hostname)

Try / catch

try:
    validated = validate_url(candidate)
except ValueError as e:
    if "file:// URLs are not allowed" in str(e):
        candidate = convert_file_url_to_path(candidate)  # urlparse(u).path + path validation
        validated = validate_file_path(candidate, base_dir=BASE)
    else:
        raise

Prevention

When it happens

Trigger: Calling a URL-validating API with file:///etc/passwd, file:///home/user/doc.html, or a source string that urlparse classifies with scheme 'file'. Happens when the same input pipe accepts both URLs and paths and a user/LLM supplies a file URL; also when local HTML is referenced as file:// during local testing.

Common situations: Local testing where developers convert local paths to file:// URLs for uniformity; LLM tool outputs producing file:// links scraped from documentation; hardening tests (pentest) probing for local file inclusion via file:// — this guard is exactly the mitigation.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/87bb0bb8d5a09378. Report an issue: GitHub.