T09 · Insecure Skill Coding Practices
- Location
scripts/seddo.sh:627- Finding
Remote Gist Name Allows Local Path Traversal and File Overwrite
- Content
View full analysis
"$seddo_config" echo "$name" > "$SEDDO_ACTIVE_FILE" seddo_name="$name" } save_state_json() { local name="$1" local state_file="${SEDDO_ROOT}/${name}/state.json" mkdir -p "$(dirname "$state_file")" cat > "$state_file" } ``` The workspace name is extracted from remotely controlled Gist content: ```bash local swarm_name swarm_name=$(echo "$raw" | grep -m1 '^# Roster\|^# Protocol\|^# Tasks\|^# .*—' \ | head -1 | sed 's/^# //' | sed 's/ —.*//' | xargs) [[ -z "$swarm_name" ]] && swarm_name="seddo" ``` It is then used directly as a filesystem path component in both join branches: ```bash local local_name="${swarm_name}" local counter=1 while [[ -d "${SEDDO_ROOT}/${local_name}" ]] && [[ "$counter" -lt 100 ]]; do local_name="${swarm_name}-${counter}" ((counter++)) done ``` ```bash save_seddo_config "$local_name" <- Remediation
View remediation
&2 return 1 fi [[ "$name" != "." && "$name" != ".." ]] || return 1 printf '%s' "$name" } ``` Use it immediately after extracting the name: ```bash swarm_name=$(sanitize_seddo_name "$swarm_name") || exit 1 ``` Add a second containment check at every filesystem sink: 1. Canonicalize `SEDDO_ROOT`. 2. Canonicalize or safely construct the proposed destination. 3. Verify that the destination begins with the canonical root followed by `/`. 4. Refuse symlinked workspace directories or use file-descriptor-based safe creation where practical. 5. Open configuration files with restrictive permissions, such as mode `0600`. Do not rely exclusively on removing `../`; use a positive allowlist and canonical path containment checks. ]]>
