T09 · Insecure Skill Coding Practices
Warning
- Location
- librarian.sh:103
- Finding
- Predictable Temporary File Allows Symlink-Based File Overwrite## Vulnerability Details **File Location**: `librarian.sh`, lines 103–104 **Vulnerability Type**: Predictable temporary file and unsafe file creation **Risk Level**: Medium ### Vulnerable Code ```bash local tmp_json="/tmp/librarian-$$.json" if ! eval "$cmd" 2>/dev/null > "$tmp_json"; then ``` ### Technical Analysis The wrapper stores research output in a predictable PID-derived path under the shared `/tmp` directory. Shell redirection opens this path without exclusive creation, ownership validation, or symbolic-link protection. A local attacker can anticipate or enumerate the process ID and create `/tmp/librarian-<PID>.json` as a symbolic link before the redirection occurs. The shell then follows the link and truncates or overwrites its target with the research process output. Although `eval` is unnecessary and increases command-execution complexity, the command is generated using Bash `%q` escaping in the reviewed implementation. The confirmed vulnerability is therefore the unsafe temporary-file operation, not a demonstrated command-injection path. ### Attack Path 1. A local attacker identifies that the victim uses this Skill. 2. The attacker predicts or enumerates a likely wrapper process ID. 3. The attacker creates `/tmp/librarian-<PID>.json` as a symbolic link to a file writable by the victim. 4. The victim invokes `librarian.sh`. 5. Shell redirection follows the attacker-created symbolic link. 6. The linked file is truncated and replaced with the research command's output. 7. The wrapper subsequently processes and removes the temporary pathname, but this does not reverse corruption of the linked target. ### Impact Assessment Exploitation requires local filesystem access and sufficient timing or PID prediction. It does not independently grant elevated privileges. An attacker can overwrite files writable by the account running the Skill. Depending on the selected target, this could cause: ...[truncated 354 chars]
- Remediation
- ## Remediation Suggestions 1. Create temporary files atomically with `mktemp` rather than constructing a PID-based filename: ```bash local tmp_json tmp_json="$(mktemp "${TMPDIR:-/tmp}/librarian.XXXXXX")" || { echo "ERROR_TEMPFILE_CREATION" exit "$EXIT_BROKEN" } ``` 2. Register cleanup immediately so the file is removed on normal exit, errors, and signals: ```bash trap 'rm -f -- "$tmp_json"' EXIT HUP INT TERM ``` 3. Avoid serializing the command and executing it through `eval`. Build and execute a Bash array directly: ```bash local cmd=( python3 "$RESEARCH_PY" "$query" ) if [[ "$scope_type" == "topic" ]]; then cmd+=(--topic "$scope_value") elif [[ "$scope_type" == "book" ]]; then cmd+=(--book "$scope_value") else echo "ERROR_INVALID_SCOPE" exit "$EXIT_BROKEN" fi cmd+=(--top-k "$top_k") if ! "${cmd[@]}" >"$tmp_json" 2>/dev/null; then echo "ERROR_EXECUTION_FAILED" exit "$EXIT_BROKEN" fi ``` 4. Apply restrictive permissions with `umask 077` before creating the file if the search output may contain sensitive excerpts. 5. Preserve validation exit codes before cleanup rather than relying on `$?` after `rm`, ensuring malformed output cannot be reported as success.
