T09 · Insecure Skill Coding Practices
- Location
local_tools/run_tool.sh:11- Finding
Unrestricted Tool Path Allows Execution of Python Files Outside the Declared Tool Set
- Content
View full analysis
&2 exit 2 fi ``` The resulting path is subsequently executed without validating that it belongs to the declared tool set: ```bash exec "$PYTHON_BIN" "$TOOL_PATH" "$@" ``` ### Technical Analysis The launcher accepts its first argument as a file path and only verifies that the resulting path points to an existing file. It does not: - Restrict the argument to the three declared adapter filenames. - Reject `..` path traversal components. - Resolve and validate the canonical path. - Verify that the resolved file remains inside `local_tools/`. - Reject symbolic links that resolve outside the tool directory. Shell metacharacter injection is mitigated by correct quoting, but path traversal remains possible. For example, an argument such as `../attacker.py` resolves outside `local_tools/` while still satisfying the `-f` check if the file exists. This violates the Skill's stated constraint that only `chembl_api.py`, `clinicaltrials_api.py`, and `search_api.py` may be executed. ### Attack Path 1. An attacker places or identifies a Python file accessible relative to the project directory. 2. The attacker influences a user, Agent, automation layer, or tool invocation to supply a traversal path: ```bash bash local_tools/run_tool.sh ../attacker.py ``` 3. The launcher constructs a path such as: ```text /project/local_tools/../attacker.py ``` 4. The `-f` validation succeeds because the file exists. 5. The launcher executes the file using the selected Python interpreter. 6. The Python file runs with the same operating-system identity, environment variables, filesystem access, and network access a ...[truncated 828 chars]- Remediation
View remediation
&2 exit 2 ;; esac ``` 2. Resolve the selected path canonically and verify that its parent is exactly `SCRIPT_DIR`: ```bash TOOL_PATH="$(realpath -- "$SCRIPT_DIR/$TOOL_NAME")" TOOL_PARENT="$(dirname -- "$TOOL_PATH")" if [ "$TOOL_PARENT" != "$SCRIPT_DIR" ]; then echo "Tool path escapes local_tools directory" >&2 exit 2 fi ``` 3. Reject arguments containing `/`, `\`, or `..`, even when an allowlist is present, as defense in depth. 4. Reject symbolic links or validate their resolved targets: ```bash if [ -L "$SCRIPT_DIR/$TOOL_NAME" ]; then echo "Symbolic-link tools are not permitted" >&2 exit 2 fi ``` 5. Run the launcher in a sandbox with minimal filesystem, environment, process, and network permissions. 6. Add regression tests confirming that paths such as `../attacker.py`, nested paths, and symlinks are rejected. ]]>
