assafelovic/gpt-researcher · critical · ValueError
Unsafe blob name: {blob_name}
Error message
Unsafe blob name: {blob_name} What it means
AzureDocumentLoader._get_blob_path rejects blob names that are absolute paths or contain '..' segments, preventing path traversal outside the temp directory. This is the first guard, on the un-resolved PurePosixPath parts.
Source
Thrown at gpt_researcher/document/azure_document_loader.py:31
temp_dir = Path(tempfile.mkdtemp()).resolve()
blobs = self.container.list_blobs()
file_paths = []
for blob in blobs:
blob_client = self.container.get_blob_client(blob.name)
local_path = self._get_blob_path(temp_dir, blob.name)
local_path.parent.mkdir(parents=True, exist_ok=True)
with open(local_path, "wb") as f:
blob_data = blob_client.download_blob()
f.write(blob_data.readall())
file_paths.append(str(local_path))
return file_paths # Pass to existing DocumentLoader
@staticmethod
def _get_blob_path(temp_dir: Path, blob_name: str) -> Path:
"""Return a safe local path for an Azure blob name."""
blob_path = PurePosixPath(blob_name.replace("\\", "/"))
if blob_path.is_absolute() or ".." in blob_path.parts:
raise ValueError(f"Unsafe blob name: {blob_name}")
local_path = (temp_dir / Path(*blob_path.parts)).resolve()
if temp_dir != local_path and temp_dir not in local_path.parents:
raise ValueError(f"Unsafe blob name: {blob_name}")
return local_path
View on GitHub (pinned to 6f998577d5)
Solutions
- Sanitize blob names: strip leading '/', reject '..' segments before calling load
- If legitimate, store blobs under flat names or subpaths without traversal
- Keep this exception—do not suppress; it is a security control
Example fix
# before
loader.load(['../etc/passwd'])
# after
safe = [n.lstrip('/') for n in names if '..' not in PurePosixPath(n.replace('\\','/')).parts]
loader.load(safe) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import PurePosixPath
def safe_blob(name: str) -> bool:
p = PurePosixPath(name.replace("\\", "/"))
return not p.is_absolute() and ".." not in p.parts
names = [n for n in blob_names if safe_blob(n)] Type guard
def is_safe_blob_name(name: str) -> bool:
p = PurePosixPath(str(name).replace("\\", "/"))
return bool(name) and not p.is_absolute() and ".." not in p.parts Try / catch
try:
loader.load(blobs)
except ValueError as e:
if "Unsafe blob name" in str(e):
log_security_event(str(e)); skip_and_continue()
else: raise Prevention
- Never pass user-supplied blob names unfiltered
- Strip leading slashes and reject '..' before calling load
When it happens
Trigger: A blob named '../secrets.txt', '/etc/passwd', or 'a/../../b' supplied to load(); also Windows-style backslash variants like '..\\..\\x' after backslash-to-slash normalization.
Common situations: Blob names coming from untrusted user input or a compromised container listing; malformed metadata with leading slashes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- URL host {host!r} resolves to a non-public address ({ip_str}
- Cost must be an integer or float
- Embedding provider not found.
- Invalid retriever(s) found: {', '.join(invalid_retrievers)}.
- Set SMART_LLM or FAST_LLM = '<llm_provider>:<llm_model>' Eg
AI-assisted analysis of assafelovic/gpt-researcher@6f998577d5 (2026-08-28).
Data as JSON: /api/errors/523de8ef089fa47f.
Report an issue: GitHub.