T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/merge.sh:8
- Finding
- Sensitive agent memory is stored in an insecure temporary directory and exposed through output logs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/merge.sh`, lines 8-38 **Vulnerability Type**: Unsafe temporary-file handling and plaintext sensitive-data exposure **Risk Level**: Medium ### Vulnerable Code ```bash STAGING_DIR="/tmp/clawng-merge-$$" cd "$WORKSPACE" mkdir -p "$STAGING_DIR" echo "[merge] Fetching all remote branches..." git fetch origin # Collect MEMORY.md from each agent branch AGENT_BRANCHES=$(git branch -r | grep 'origin/agent/' | sed 's|.*origin/||' | tr -d ' ') if [ -z "$AGENT_BRANCHES" ]; then echo "[merge] No agent branches found." rm -rf "$STAGING_DIR" exit 0 fi for branch in $AGENT_BRANCHES; do agent_id=$(echo "$branch" | sed 's|agent/||') memory=$(git show "origin/$branch:MEMORY.md" 2>/dev/null || echo "") if [ -n "$memory" ]; then echo "=== $agent_id ===" >> "$STAGING_DIR/all-memories.txt" echo "$memory" >> "$STAGING_DIR/all-memories.txt" echo "" >> "$STAGING_DIR/all-memories.txt" fi done echo "[merge] Staged memory files from: $AGENT_BRANCHES" echo "[merge] Output at: $STAGING_DIR/all-memories.txt" cat "$STAGING_DIR/all-memories.txt" ``` ### Technical Analysis The script creates a predictable temporary directory using its process ID: ```bash STAGING_DIR="/tmp/clawng-merge-$$" mkdir -p "$STAGING_DIR" ``` This construction does not provide atomic, secure temporary-directory creation. An attacker with local access may be able to predict the process ID and create the path before the script does. Depending on operating-system protections and account permissions, this can cause denial of service or facilitate unsafe path manipulation. The script also does not set a restrictive `umask` or explicitly assign owner-only permissions. It writes aggregated contents from every remote agent's `MEMORY.md` into a plaintext file. These files may contain user context, operational information, private conversations, or other sensitive long-term memory. The temporary directory is removed only when no ...[truncated 1935 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Create the temporary directory atomically with `mktemp`. 2. Set an owner-only `umask` before creating files. 3. register an `EXIT` trap immediately so cleanup occurs on success, error, or interruption. 4. Do not print memory contents to standard output. 5. If a downstream process requires the generated file, pass its path through a protected channel and delete it immediately after use. 6. Explicitly create files with owner-only permissions where portability permits. 7. Ensure cron, CI, and service logs do not retain memory content. Example hardening: ```bash umask 077 STAGING_DIR=$(mktemp -d "${TMPDIR:-/tmp}/clawng-merge.XXXXXXXX") trap 'rm -rf -- "$STAGING_DIR"' EXIT HUP INT TERM OUTPUT_FILE="$STAGING_DIR/all-memories.txt" : > "$OUTPUT_FILE" chmod 600 "$OUTPUT_FILE" # Populate OUTPUT_FILE without printing its contents. echo "[merge] Memory collection completed." ``` A more robust design would avoid writing the aggregate to disk and instead stream it directly to the authorized synthesis process through a pipe or protected standard input. ]]>
