T09 · Insecure Skill Coding Practices
- Location
scripts/seed_kernel.py:220- Finding
Unvalidated Egg Identifier Allows Registry Directory Escape and Arbitrary File Placement
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill mostly does what it says locally, but its seeding script has under-scoped file-write behavior that can escape the intended registry path.
Review this skill before installing. Use it only with trusted, simple egg IDs, explicit safe seed roots, and non-secret input files; avoid the mutable npx @latest installer path unless you can verify the installer version and provenance.
scripts/seed_kernel.py:220Unvalidated Egg Identifier Allows Registry Directory Escape and Arbitrary File Placement
scripts/seed_kernel.py:252Incomplete Rollback Can Destroy Existing Eggs and Leave Registry State Inconsistent
SKILL.md:44Documented Installation Command Executes an Unpinned Mutable npm Package
The code is a read-only registry listing script. It parses CLI flags, locates a registry file, loads it, and prints egg metadata or JSON output. It does not perform insertion, seeding, self-verification on insert, consent checks, sovereign sealing, or agent kernel installation across a stack. While it references registry and Merkle-root-related metadata, that is only for display. Therefore the declared description materially overstates and misrepresents the actual behavior of this code chunk.
Referenced artifact was not completely inspected
| `SKILL.md` | Agent instructions (this file) |
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
try:
note = tmp / "module.txt"
note.write_text("LYGO sovereign seed smoke\n", encoding="utf-8")
env = os.environ.copy()
env["LYGO_KERNEL_SEED_CONSENT"] = "yes"
env["LYGO_SEED_ROOT"] = str(tmp)
r1 = subprocess.run(
The skill advertises and instructs use of Python scripts, local file operations, environment variables, and shell commands, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization and review gap: an agent may grant broader filesystem, environment, or shell access than a user expects, increasing the chance of unsafe execution of local scripts or writes to attacker-influenced paths.
Using npx clawhub@latest install ... relies on a moving, unpinned package version at execution time. This introduces a supply-chain risk: if the upstream package is compromised or a breaking/malicious release is published, users may execute attacker-controlled install logic simply by following the documented command.
This is a manifest file, so vague-trigger checks apply. The description uses broad, marketing-style language like "sovereign kernel eggs" and "for agents across the LYGO stack" without stating when the skill should or should not be invoked, making activation scope ambiguous.
The output root is controlled by --root or environment variables, allowing writes outside a fixed application-owned seed store. In agent or automation contexts this becomes an arbitrary file-write surface within the process's permissions, enabling unintended persistence in sensitive directories and making it easier to overwrite or plant files where the caller did not expect.
The seeder accepts arbitrary caller-supplied file paths, reads their contents, and may embed full file data inline as base64 in the generated egg. In an agent setting, this creates a clear local file exfiltration/over-collection primitive: a user or upstream workflow can cause sensitive local files to be packaged into persistent artifacts, which is broader than a narrowly scoped kernel-seeding function.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
env = os.environ.copy()
env["LYGO_KERNEL_SEED_CONSENT"] = "yes"
env["LYGO_SEED_ROOT"] = str(tmp)
r1 = subprocess.run(
[
sys.executable,
str(HERE / "seed_kernel.py"),
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print(r1.stderr, file=sys.stderr)
print("SMOKE_FAIL seed", r1.returncode)
return 1
r2 = subprocess.run(
[sys.executable, str(HERE / "verify_seed.py"), "--root", str(tmp), "--json"],
capture_output=True,
text=True,
In --manifest mode, the script creates eggs/<egg_id>.seed.txt via write_text, which is a file write affecting the user's filesystem. Although the script requires consent globally, this specific write is not accompanied by a user-facing disclosure at the point of action or a comment/docstring explaining that a placeholder file will be created.
The script writes persistent JSON files to eggs/<egg_id>.egg.json and registry.json using atomic_write_json, which changes local state. The code has a consent check, but it does not clearly warn the user before the write about which files will be created or modified; the paths are only shown after success.
No suspicious patterns detected.