affaan-m/ECC · error · ValueError
Path ' ' targets a system directory
Error message
Path '{path}' targets a system directory What it means
Raised by _validate_file_path in skills/continuous-learning-v2/scripts/instinct-cli.py when a user-supplied path string starts with (or equals) one of the blocked system prefixes such as /etc, /var/log, /private/etc. The CLI refuses file-path arguments that target protected OS directories to prevent instinct import/export from reading or clobbering system files. It is a prefix-based blocklist check performed before any filesystem access.
Solutions
- Pass a path outside the blocked prefixes — use a project or user directory (e.g. ~/.config/ecc-instincts/...).
- Check the path with a prefix check (path == prefix or path.startswith(prefix + '/')) before invoking the command.
- If exporting, choose an output file in the working directory instead of a system location.
- For genuinely intended system integration, install via a package manager rather than writing through this CLI.
Example fix
# before python instinct-cli.py export --file /etc/instincts.yaml # after python instinct-cli.py export --file ~/.config/ecc-instincts/instincts.yaml
Defensive patterns
Strategy: validation
Validate before calling
blocked = ["/etc", "/var", "/usr", "/private/etc", "/private/var", "/private/usr"]
p = str(path)
if any(p == b or p.startswith(b + "/") for b in blocked):
raise ValueError(f"system path not allowed: {p}") Try / catch
try:
cli_import(file=path)
except ValueError as e:
if "system directory" in str(e):
print("choose a path outside /etc, /var, /usr") Prevention
- Use project-relative or ~/.config paths for instinct files
- Prefix-check absolute paths against the blocklist before invoking
- Never point CLI file arguments at OS directories
- Validate user-supplied paths at the boundary before passing to the CLI
When it happens
Trigger: Running import/export commands with --file or path arguments equal to or under blocked prefixes like /etc, /etc/passwd, /var/log, /usr, /private/var/db (macOS private paths also blocked).
Common situations: User typo meaning to pass a relative path but typed an absolute system path; scripted automation resolving config into /etc; attempting to export instincts into /usr/local/bin deliberately.
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
- artifact path must be canonical and absolute
- ECC_ITO_CLI_EXECUTABLE must point to the canonical…
- ECC_NASIKO_CLI_EXECUTABLE must be an absolute path.
- output must have a video suffix distinct from…
- Path does not exist
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/be9cb652d0896c1a.
Report an issue: GitHub.
Appendix: source
Thrown at skills/continuous-learning-v2/scripts/instinct-cli.py:168
"""Validate and resolve a file path, guarding against path traversal.
Raises ValueError if the path is invalid or suspicious.
"""
path = Path(path_str).expanduser().resolve()
# Block paths that escape into system directories
# We block specific system paths but allow temp dirs (/var/folders on macOS)
blocked_prefixes = [
"/etc", "/usr", "/bin", "/sbin", "/proc", "/sys",
"/var/log", "/var/run", "/var/lib", "/var/spool",
# macOS resolves /etc → /private/etc
"/private/etc",
"/private/var/log", "/private/var/run", "/private/var/db",
]
path_s = str(path)
for prefix in blocked_prefixes:
if path_s.startswith(prefix + "/") or path_s == prefix:
raise ValueError(f"Path '{path}' targets a system directory")
if must_exist and not path.exists():
raise ValueError(f"Path does not exist: {path}")
return path
def _validate_instinct_id(instinct_id: str) -> bool:
"""Validate instinct IDs before using them in filenames."""
if not instinct_id or len(instinct_id) > 128:
return False
if "/" in instinct_id or "\\" in instinct_id:
return False
if ".." in instinct_id:
return False
if instinct_id.startswith("."):
return False
return bool(re.match(r"^[A-Za-z0-9][A-Za-z0-9._-]*$", instinct_id))View on GitHub (pinned to 8321021c54)