crewAIInc/crewAI · error · ValueError

Blocked unsafe URL: {e}

Error message

Blocked unsafe URL: {e}

What it means

Raised in RAGTool.add()'s per-argument loop when a value parses as a URL (urlparse yields a scheme of http, https, or file) and validate_url rejects it. Only urlparse-specific parse errors are caught silently; the guard's own ValueError always propagates, wrapped as 'Blocked unsafe URL: <reason>', so a security rejection can never be silently bypassed.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/rag/rag_tool.py:315

        for arg in args:
            source_ref = (
                str(arg.get("source", arg.get("content", "")))
                if isinstance(arg, dict)
                else str(arg)
            )

            # Check if it's a URL — only catch urlparse-specific errors here;
            # validate_url's ValueError must propagate so it is never silently bypassed.
            try:
                parsed = urlparse(source_ref)
            except (ValueError, AttributeError):
                parsed = None

            if parsed is not None and parsed.scheme in ("http", "https", "file"):
                try:
                    validate_url(source_ref)
                except ValueError as e:
                    raise ValueError(f"Blocked unsafe URL: {e}") from e
                validated_args.append(arg)
                continue

            # Check if it looks like a file path (not a plain text string).
            # Check both os.sep (backslash on Windows) and "/" so that
            # forward-slash paths like "sub/file.txt" are caught on all platforms.
            if (
                os.path.sep in source_ref
                or "/" in source_ref
                or source_ref.startswith(".")
                or os.path.isabs(source_ref)
            ):
                try:
                    resolved_ref = validate_file_path(source_ref)
                except ValueError as e:
                    raise ValueError(f"Blocked unsafe file path: {e}") from e
                # Use the resolved path to prevent symlink TOCTOU
                if isinstance(arg, dict):

View on GitHub (pinned to 754d7323be)

Solutions

  1. For local files, pass the filesystem path ('./docs/x.pdf') instead of a file:// URL — the path branch validates it separately
  2. For blocked http(s) hosts, fetch the content from an allowed context and add it as text content
  3. Read the embedded validate_url reason to see the exact rule tripped
  4. Keep agent-facing prompts away from internal hostnames to avoid repeated guard hits

Example fix

# before
rag_tool.add('file:///home/user/report.pdf')  # ValueError: Blocked unsafe URL

# after
rag_tool.add('/home/user/report.pdf')  # handled by path validation, PDF auto-detected
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
from crewai_tools.security.safe_path import validate_url

def addable_url(u: str) -> bool:
    try:
        parsed = urlparse(u)
    except ValueError:
        return False
    if parsed.scheme in ("http", "https", "file"):
        try:
            validate_url(u)
            return True
        except ValueError:
            return False
    return False

Try / catch

try:
    rag_tool.add(source_ref)
except ValueError as e:
    if "Blocked unsafe URL" in str(e):
        # local file? switch to a filesystem path so the path branch handles it
        if source_ref.startswith("file://"):
            rag_tool.add(source_ref[len("file://"):])
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: rag_tool.add('http://127.0.0.1:8080/health') or file:// URLs pointing at local files — anything whose scheme marks it a URL and whose host/scheme the SSRF guard blocks (loopback, private IP, metadata endpoints, file scheme).

Common situations: Trying to ingest file:// URLs for local documents (blocked — use a filesystem path instead); agents probing internal HTTP services during research tasks; localhost dev URLs in examples that work in docs but are blocked by the guard.

Related errors


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