T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/write_ref_stub.py:13
- Finding
- Unrestricted Reference-Stub Path Allows Existing Files to Be Overwritten<![CDATA[ ## Vulnerability Details **File Location**: `scripts/write_ref_stub.py:13-33` **Vulnerability Type**: Unrestricted file write and overwrite **Risk Level**: Medium ### Vulnerable Code ```python ap.add_argument("--out", type=Path, required=True) ap.add_argument("--title", required=True) ap.add_argument("--lines", nargs="*", default=[]) ap.add_argument("--resonance-to", help="Outer brain label for lyra-brain style edge") args = ap.parse_args() lines = [ f"Title: {args.title}", f"Last updated: {datetime.now(timezone.utc).date()}", "", ] if args.resonance_to: day = datetime.now(timezone.utc).strftime("%Y%m%d") lines.insert(0, f"SESSION_{day} --resonance--> {args.resonance_to}") for line in args.lines: lines.append(line) lines.append("") out = args.out out.parent.mkdir(parents=True, exist_ok=True) out.write_text("\n".join(lines), encoding="utf-8") ``` ### Technical Analysis The `--out` argument accepts an unrestricted absolute or relative filesystem path. The destination is not constrained to an approved workspace or reference directory. The script also does not validate the expected `.ref.txt` or `.md` extension, reject symbolic links, or refuse an existing destination. `Path.write_text()` opens the destination for truncating write. Consequently, an existing writable file is silently replaced. This behavior conflicts with the additive-only and no-overwrite guarantees declared in: - `SKILL.md:3` - `references/AGENT_CONTRACT.md:9,15` - `references/SECURITY.md:9,12` The vulnerability does not independently elevate operating-system privileges; it operates with the permissions of the invoking process. However, within that permission boundary, it provides an unrestricted file-overwrite primitive. ### Attack Path 1. An attacker influences a command, automation input, or agent-generated invocation of `write_ref_stub.py`. 2. The attacker supplies an existing writable file through `--out`, such as a project configuration, agent stat ...[truncated 1115 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require an explicit approved workspace root and resolve both root and destination: ```python root = args.root.resolve(strict=True) out = (root / args.out).resolve(strict=False) if not out.is_relative_to(root): raise SystemExit("Output must remain inside the approved root") ``` 2. Require `--out` to be relative and restrict writes to an intended directory such as `reference/` or `memory/reference/`. 3. Enforce allowed filename suffixes, preferably `.ref.txt` and optionally `.md`. 4. Reject existing destinations by creating the file exclusively: ```python with out.open("x", encoding="utf-8") as handle: handle.write(content) ``` 5. If replacement is genuinely required, place it behind a separate `--force` option and require explicit confirmation. 6. Reject symbolic links in the destination and relevant parent components. 7. Use a temporary file followed by an atomic rename for approved replacement operations. 8. Add tests covering absolute paths, `../` traversal, existing files, symlink destinations, and destinations outside the approved root. ]]>
