T09 · Insecure Skill Coding Practices
- Location
scripts/compaction-extract.sh:12- Finding
Unvalidated Session Identifier Enables Path Traversal and Unsafe File Writes
- Content
View full analysis
/dev/null) [ -z "$SESSION_ID" ] && SESSION_ID="${NC_SESSION:-}" [ -z "$SESSION_ID" ] && echo '{"continue":true}' && exit 0 SESSION_DIR="${SESSIONS_DIR}/${SESSION_ID}" HANDOFFS_DIR="${SESSION_DIR}/handoffs" STATE_FILE="${SESSION_DIR}/compaction-extract.json" mkdir -p "$HANDOFFS_DIR" # Track stop count STOP_COUNT=0 if [ -f "$STATE_FILE" ]; then STOP_COUNT=$(jq -r '.stop_count // 0' "$STATE_FILE" 2>/dev/null) fi STOP_COUNT=$((STOP_COUNT + 1)) # Update state TMP="${STATE_FILE}.${$}.tmp" jq -n --argjson count "$STOP_COUNT" '{"stop_count":$count}' > "$TMP" mv "$TMP" "$STATE_FILE" # Only extract every N stops if [ $((STOP_COUNT % EXTRACT_INTERVAL)) -ne 0 ]; then echo '{"continue":true}' exit 0 fi # Extract last assistant message as knowledge to preserve LAST_MSG=$(echo "$INPUT" | jq -r '.last_assistant_message // ""' 2>/dev/null | head -c 5000) [ -z "$LAST_MSG" ] && echo '{"continue":true}' && exit 0 TIMESTAMP=$(date +%s) HANDOFF_FILE="${HANDOFFS_DIR}/pre-compact-${TIMESTAMP}.md" cat > "$HANDOFF_FILE" << EOF # Pre-Compaction Knowledge Extract Timestamp: $(date -u +"%Y-%m-%dT%H:%M:%SZ") Session: ${SESSION_ID} Stop count: ${STOP_COUNT} ## Context Summary ${LAST_MSG} EOF ``` ### Technical Analysis The session identifier comes directly from hook input or the `NC_SESSION` environment variable. It is concatenated into filesystem paths without validation, canonicalization, containment checks, or symlink checks. A value containing `../` components can cause `SESSION_DIR` to resolve outside `~/.openclaw/shared-context/sessions`. The script then performs several filesystem operations using the escaped path: - Recursive directory creation through `mkdir -p`. - Reading ...[truncated 1655 chars]- Remediation
View remediation
