1Panel-dev/1Panel · error · ValueError
unsafe-path
Error message
unsafe-path
What it means
Raised by the embedded Python verifier in diagnose-install.sh when an artifact path recorded in the modules manifest is rejected before any filesystem access: it is empty, absolute, contains a '..' component, or contains a backslash. It is a strict path-sanitization gate (PurePosixPath parse) that guarantees the checksum step can only touch files under the modules root.
Source
Thrown at scripts/openresty-modules/diagnose-install.sh:217
import sys
state_path = pathlib.Path(sys.argv[1])
modules_root = pathlib.Path(sys.argv[2]).resolve()
modules = json.loads(state_path.read_text(encoding="utf-8"))
failed = False
print("module\tbuild_status\ttarget_key\tartifact\texpected\tactual\tresult")
for module in modules:
for build in module.get("builds") or []:
target_key = (build.get("target") or {}).get("key", "")
for artifact in build.get("artifacts") or []:
relative = artifact.get("path", "")
expected = artifact.get("checksum", "")
result = "OK"
actual = ""
try:
pure = pathlib.PurePosixPath(relative)
if not relative or pure.is_absolute() or ".." in pure.parts or "\\" in relative:
raise ValueError("unsafe-path")
candidate = modules_root / pathlib.Path(*pure.parts)
if candidate.is_symlink():
raise ValueError("symlink-not-allowed")
full_path = candidate.resolve(strict=True)
if modules_root not in full_path.parents:
raise ValueError("outside-module-root")
if not full_path.is_file():
raise ValueError("not-regular-file")
digest = hashlib.sha256()
with full_path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
actual = digest.hexdigest()
if actual.lower() != expected.lower():
raise ValueError("checksum-mismatch")
except Exception as error:
result = str(error)
failed = TrueView on GitHub (pinned to 5ac7c80881)
Solutions
- Fix the artifact 'path' in the modules index so it is a relative POSIX path under the modules root, e.g. 'resty/http.so' with no leading '/', no '..' segments, no backslashes
- If the path came from a build log, regenerate the manifest with the build tool so paths are normalized via PurePosixPath(relative_to(modules_root))
- Re-run diagnose-install.sh and confirm the row reports result=OK before continuing the install
Example fix
// manifest before
{"path": "/opt/1panel/openresty/modules/../resty/http.so", "checksum": "..."}
// manifest after
{"path": "resty/http.so", "checksum": "..."} Defensive patterns
Strategy: validation
Validate before calling
# before calling the diagnostic, validate manifest paths
python3 - <<'PY'
import json, pathlib, sys
m = json.load(open("modules.json"))
bad = []
for mod in m:
for b in mod.get("builds") or []:
for a in b.get("artifacts") or []:
p = pathlib.PurePosixPath(a.get("path", ""))
if not str(p) or p.is_absolute() or ".." in p.parts or "\\" in str(p):
bad.append(str(p))
print("bad paths:", bad)
sys.exit(1 if bad else 0)
PY Prevention
- Generate artifact paths programmatically relative to the modules root; never hand-type them
- Normalize with PurePosixPath and reject absolute/'..'/backslash in CI before shipping the manifest
When it happens
Trigger: Run scripts/openresty-modules/diagnose-install.sh (or its embedded heredoc Python) against a modules index JSON where an artifact's 'path' field is "", starts with '/', has a segment like '../..', or uses Windows separators ('\\') such as 'lua/\\resty\\foo.so'.
Common situations: Hand-edited manifest with absolute install paths; paths copied from a Windows machine; a build step recording its output directory as '..' relative to the workspace; empty path from a build that produced no artifact but still emitted a checksum entry.
Related errors
- symlink-not-allowed
- outside-module-root
- not-regular-file
- failed to update mongodb user privileges
- aiTools.agents.allowedOriginsInvalid
AI-assisted analysis of 1Panel-dev/1Panel@5ac7c80881 (2026-08-15).
Data as JSON: /api/errors/079c63abf366bf90.
Report an issue: GitHub.