T05 · Unauthorized Access and Privilege Escalation
- Location
run.py:5- Finding
Unrestricted Target Path Allows Unauthorized Filesystem Modification
- Content
View full analysis
Vulnerability Details
File Location:
run.py, lines 5-9
Vulnerability Type: Unrestricted path resolution and unauthorized file modification
Risk Level: HighVulnerable Code
python ws=Path("/home/jason/.openclaw/workspace");t=(ws/a.task).resolve() if not Path(a.task).is_absolute() else Path(a.task).resolve() t.exists() or (print(json.dumps({"skill":"AI_AutoTester","status":"error","error":f"Target path not found: {t}"},ensure_ascii=False,indent=2)),sys.exit(1)) (td:=t/"tests").mkdir(parents=True,exist_ok=True) (tf:=td/"test_smoke.py").exists() or tf.write_text('from app.main import app\nfrom fastapi.testclient import TestClient\n\ndef test_root():\n c=TestClient(app)\n r=c.get("/")\n assert r.status_code==200\n',encoding="utf-8") (t/"requirements-test.txt").write_text("pytest==8.3.2\nhttpx==0.27.2\n",encoding="utf-8")Technical Analysis
The
--taskargument is treated as a filesystem path. Absolute paths are accepted directly, while relative paths are resolved against/home/jason/.openclaw/workspace. After resolution, the program does not verify that the resulting path remains inside the intended workspace.Consequently, a relative path containing traversal components such as
../../target, or an explicitly supplied absolute path, can select any existing directory accessible to the process. The program then:- Creates a
testsdirectory. - Creates
tests/test_smoke.pyif it does not already exist. - Unconditionally overwrites
requirements-test.txt.
Calling
Path.resolve()canonicalizes a path but does not enforce a security boundary. The absence of an allowlist or containment check violates least-privilege principles and permits modifications beyond the documented testing workspace.The
--constraintsoption does not mitigate this issue because it is parsed but never consulted before filesystem changes occur.Attack Path
- An attacker or untrusted caller invokes the ...[truncated 1119 chars]
- Creates a
- Remediation
View remediation
Remediation Suggestions
-
Reject absolute values for
--taskunless an explicitly authorized administrative mode requires them. -
Resolve both the workspace and requested target, then enforce containment:
python workspace = Path("/home/jason/.openclaw/workspace").resolve() target = (workspace / args.task).resolve() if not target.is_relative_to(workspace): raise ValueError("Target must remain within the configured workspace") -
On Python versions without
Path.is_relative_to(), use a safe containment comparison based onrelative_to(), handlingValueError. -
Consider restricting targets to an allowlist of registered project directories.
-
Verify that the target is a directory rather than merely checking that it exists.
-
Do not overwrite
requirements-test.txtunconditionally. Fail safely if it exists, create a uniquely named generated file, or require explicit confirmation. -
Require confirmation before modifying project files and clearly report every planned change.
-
Apply defenses against symlink-based boundary bypasses and revalidate paths immediately before writing where concurrent attackers are in scope.
-
Honor the supplied constraints before performing any filesystem mutation.
-
