T09 · Insecure Skill Coding Practices
- Location
scripts/_stack_tools.py:19- Finding
Unverified External Python Modules Are Executed In-Process
- Content
View full analysis
Vulnerability Details
File Location:
scripts/_stack_paths.py:74-78;scripts/_stack_tools.py:19-30
Vulnerability Type: Inadequate trust validation before dynamic code execution
Risk Level: MediumVulnerable Code
python def _assert_stack(p: Path) -> None: missing = [rel for rel in _REQUIRED_FILES if not (p / rel).is_file()] if missing: raise SystemExit(f"Invalid stack root {p}; missing: {missing}")python def load_tool(stack_root: Path, basename: str) -> ModuleType: if basename not in ALLOWED_TOOLS: raise ValueError(f"Tool not allowlisted: {basename}") path = (stack_root / "tools" / basename).resolve() expected = (stack_root / "tools" / basename).resolve() if path != expected or not path.is_file(): raise FileNotFoundError(f"Missing stack tool: {basename}") spec = importlib.util.spec_from_file_location(f"lygo_hsc_{basename[:-3]}", path) if spec is None or spec.loader is None: raise ImportError(f"Cannot load {basename}") mod = importlib.util.module_from_spec(spec) sys.modules[spec.name] = mod spec.loader.exec_module(mod) return modTechnical Analysis
LYGO_STACK_ROOTselects the directory from which Python tools are dynamically loaded. Stack validation only confirms that expected filenames exist. It does not authenticate the repository, pin an approved revision, verify file hashes or signatures, inspect ownership and permissions, or reject symbolic links.The filename allowlist limits which filenames may be selected, but it does not establish that the contents of those files are trustworthy. Moreover, the
pathandexpectedvariables are constructed and resolved identically, so the equality check provides no independent containment assurance.Calling
spec.loader.exec_module(mod)executes all top-level Python code in the selected module before the expected validation or feed function is invoked. Consequently, claims that Skill scripts ...[truncated 1404 chars]- Remediation
View remediation
Remediation Suggestions
- Pin the supported stack to an exact reviewed commit and publish a signed manifest containing hashes of every importable module.
- Before every import, verify the selected module against that manifest using a cryptographically secure digest and fail closed on mismatch.
- Verify repository provenance with a trusted signature rather than relying on marker filenames.
- Reject symlinks for the stack root,
toolsdirectory, and imported files; verify containment using independently calculated canonical paths. - Reject stack trees or modules writable by untrusted users, where the platform exposes reliable ownership and permission information.
- Prefer shipping the small validation and feed-verification implementation inside the reviewed Skill package.
- If external code must run, isolate it in a restricted process with a minimal environment, read-only filesystem access, no network access, resource limits, and a strict input/output protocol.
- Update
self_check.pyso it verifies integrity without importing or executing stack modules.
