ComposioHQ/composio · critical · UnsafePathComponentError
Refusing to write {label} containing a NUL byte: {name!r}
Error message
Refusing to write {label} containing a NUL byte: {name!r} What it means
safe_basename rejects filenames containing a NUL byte (\x00). NUL cannot appear in a filesystem path on Linux or Windows and would truncate/error at open() time; it is also a classic path-injection marker.
Source
Thrown at python/composio/utils/safe_path.py:177
both basename to ``""``, which makes an output path equal to its own
directory and surfaces as ``IsADirectoryError`` at write time.
:raises UnsafePathComponentError: when ``name`` yields no usable basename or
is unsafe to write.
"""
if not isinstance(name, str):
raise UnsafePathComponentError(
f"Refusing to write a non-string {label}: {name!r}"
)
raw_basename = PureWindowsPath(name).name
if not raw_basename or not raw_basename.strip() or set(raw_basename) == {"."}:
raise UnsafePathComponentError(
f"Path traversal detected: {label} {name!r} leaves no usable "
"basename to write to."
)
if "\x00" in raw_basename:
raise UnsafePathComponentError(
f"Refusing to write {label} containing a NUL byte: {name!r}"
)
if any(ord(char) < 32 or char in '<>:"|?*' for char in raw_basename):
raise UnsafePathComponentError(
f"Refusing to write {label} containing characters reserved by "
f"Windows: {name!r}"
)
if raw_basename.endswith((" ", ".")):
raise UnsafePathComponentError(
f"Refusing to write {label} ending in a space or dot: {name!r}"
)
basename = raw_basename.strip()
try:
encoded_length = len(os.fsencode(basename))
except UnicodeEncodeError as e:
raise UnsafePathComponentError(
f"Refusing to write {label} containing invalid Unicode: {name!r}"View on GitHub (pinned to 64b1b85502)
Solutions
- Strip or reject NUL-containing strings before filename handling
- Treat a NUL byte in any path-ish field as malicious input and drop the whole request
Example fix
# before
secure_basename_join(base, name)
# after
if "\x00" in name:
raise ValueError("invalid filename")
secure_basename_join(base, name) Defensive patterns
Strategy: validation
Validate before calling
def nul_free(v):
return isinstance(v, str) and '\x00' not in v Type guard
def is_nul_free(v: str) -> bool:
return '\x00' not in v Try / catch
from composio.exceptions import UnsafePathComponentError
try:
p = secure_basename_join(base, name)
except UnsafePathComponentError:
raise ValueError(f'malicious filename received: {name!r}') Prevention
- Reject the entire request when a filename contains NUL
- Scan untrusted strings for control characters at ingest
When it happens
Trigger: secure_basename_join(base, name) where name (or its extracted basename) contains '\x00' — e.g. 'file.txt\x00.jpg' trying to exploit NUL truncation in C-based syscalls.
Common situations: Adversarial filenames from untrusted API responses; binary garbage decoded into strings.
Related errors
- Refusing to build a path from an unsafe {label}: {value!r}.
- Refusing to write a non-string {label}: {name!r}
- Unsafe path component: {e}
- Refusing to build a path from an empty or non-string {label}
- Refusing to build a path from a {label} containing path sepa
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/e81cf830545d0746.
Report an issue: GitHub.