HelloZeroNet/ZeroNet · warning · SecurityError
Invalid path
Error message
Invalid path
What it means
parsePath rejects request paths that contain traversal sequences ('../' or './') as a security measure against path traversal attacks on zite media/file routes. It throws a SecurityError instead of a plain Exception to signal a malicious or malformed path rather than a normal routing miss. The regex for /media/ routes then only processes safe, whitelisted character sets.
Source
Thrown at src/Ui/UiRequest.py:612
origin_pattern = "http[s]{0,1}://(.*?/.*?/).*"
is_origin_full = re.match(origin_pattern, url_a)
if not is_origin_full: # Origin looks trimmed to host, require only same host
origin_pattern = "http[s]{0,1}://(.*?/).*"
origin_a = re.sub(origin_pattern, "\\1", url_a)
origin_b = re.sub(origin_pattern, "\\1", url_b)
return origin_a == origin_b
# Return {address: 1Site.., inner_path: /data/users.json} from url path
def parsePath(self, path):
path = path.replace("\\", "/")
path = path.replace("/index.html/", "/") # Base Backward compatibility fix
if path.endswith("/"):
path = path + "index.html"
if "../" in path or "./" in path:
raise SecurityError("Invalid path")
match = re.match(r"/media/(?P<address>[A-Za-z0-9]+[A-Za-z0-9\._-]+)(?P<inner_path>/.*|$)", path)
if match:
path_parts = match.groupdict()
if self.isDomain(path_parts["address"]):
path_parts["address"] = self.resolveDomain(path_parts["address"])
path_parts["request_address"] = path_parts["address"] # Original request address (for Merger sites)
path_parts["inner_path"] = path_parts["inner_path"].lstrip("/")
if not path_parts["inner_path"]:
path_parts["inner_path"] = "index.html"
return path_parts
else:
return None
# Serve a media for site
def actionSiteMedia(self, path, header_length=True, header_noscript=False):
try:
path_parts = self.parsePath(path)View on GitHub (pinned to 454c0b2e7e)
Solutions
- Remove any '../' or './' segments from the path before requesting; use absolute inner paths starting from the site root
- Normalize/resolve the URL on the client side (e.g. posixpath.normpath) and verify it has no relative segments
- If building inner_paths programmatically, sanitize with a whitelist regex like [A-Za-z0-9._-] and reject '..' components
- If you control the site, fix the offending links/templates that emit relative URLs
Example fix
// before
img_src = '../data/logo.png'
// after
import posixpath
path = posixpath.normpath('/' + img_src).lstrip('/')
assert '../' not in path and './' not in path Defensive patterns
Strategy: validation
Validate before calling
import posixpath
def is_safe_path(path):
p = path.replace('\\', '/')
normalized = posixpath.normpath(p)
return '../' not in p and './' not in p and normalized == p or '../' not in normalized Type guard
def has_no_traversal(path: str) -> bool:
return '../' not in path and './' not in path Prevention
- Always normalize request paths with posixpath.normpath before sending
- Build inner paths from whitelisted characters only ([A-Za-z0-9._-])
- Never concatenate user input directly into site/media URLs
- Use absolute paths from the site root instead of relative segments
When it happens
Trigger: Requesting a media or site URL whose path includes '../' or './' segments, e.g. /media/SiteAddress/../../etc/passwd or a link with relative segments like ./file.html; also paths using backslashes that are normalized to slashes but still contain traversal after normalization.
Common situations: Crafted/attacker-supplied links embedded in a zite, relative links generated incorrectly by site templates, proxies or clients rewriting URLs, or media inner_paths built by string concatenation without normalization.
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
AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02).
Data as JSON: /api/errors/d80bfdaf2dd6819b.
Report an issue: GitHub.