Back to skill

Security audit

Seddo

Security checks for vulnerabilities and agentic risk

Overview

The skill fits its agent-coordination purpose, but its shell scripts have unsafe local path handling that can affect files outside the intended Seddo workspace.

Review before installing. Only join gists from people you trust, avoid putting secrets or regulated data in Seddo files, use a GitHub credential limited to gist access where possible, and consider patching name validation and path containment before use.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
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. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/seddo.sh:276
Finding

GitHub OAuth Token Exposed in Curl Process Arguments

Content
View full analysis
``` 3. `fork_gist` executes `gh auth token` and interpolates the returned secret into `curl` arguments. 4. While `curl` is running, a local observer monitors process command lines. 5. On a system with permissive process visibility, the observer captures the bearer token from the `Authorization` argument. 6. The observer uses the token against GitHub APIs until it expires or is revoked. Successful exploitation requires local process-observation access and a sufficiently long observation window. ### Impact Assessment A captured token may provide access to private Gists and any additional permissions granted to that GitHub credential. The exact scope depends on how the user authentic ...[truncated 507 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (25)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · install.sh (reported line 86)May include surrounding context.

sh
echo "✅ OpenClaw: skill auto-loaded from ${DEST}"
    ;;
  opencode)
    echo "📋 OpenCode — add SWARM_GIST_ID to your agent config or .env"
    ;;
  *)
    echo "📋 Generic — add to your agent's system prompt or config:"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The deletion path uses rm -rf on a path derived from user-controlled name without validating that the name is a safe basename. If an attacker or accidental user supplies traversal sequences like ../../, the script can delete arbitrary directories outside ~/.seddo.d after confirmation, causing severe local data loss.

Content

Scanner excerpt · scripts/seddo.sh (reported line 866)May include surrounding context.

sh
read -rp "   Remove « ${name} »? [y/N] → " confirm
  [[ "$confirm" != "y" ]] && exit 0

  rm -rf "${SEDDO_ROOT}/${name}"
  echo "✅ Removed « ${name} » locally."

  if [[ "$name" == "$active_name" ]]; then

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

The skill directs agents to persist coordination state under ~/.seddo.d/ and to use a GitHub Gist/fork workflow as an ongoing shared communication bus. That creates durable local and remote artifacts containing task data, messages, identities, and possibly sensitive project context, which can outlive the session and be accessed by other local users, future agent runs, or anyone with gist access if permissions are misconfigured.

Content

Scanner excerpt · AGENTS.md (reported line 45)May include surrounding context.

md
3. **Sign everything** — every entry ends with `— @your-name timestamp`.
4. **Update status promptly** — mark WIP when you start, DONE when finished.
5. **Last-write-wins** — don't edit the same file within the same minute as another agent.
6. **Write to your fork** — spokes write to their own fork gist, not the hub.

## Setup

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · OPENCODE.md (reported line 36)May include surrounding context.

md
gh repo clone dofbi/seddo /tmp/seddo-install

# Créer le dossier du skill
mkdir -p ~/.config/opencode/skills/seddo

# Copier les fichiers
cp /tmp/seddo-install/SKILL.md ~/.config/opencode/skills/seddo/

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README promotes using private GitHub gists as a coordination bus for messages, tasks, and lessons across agents, but it does not clearly warn that all shared content is transmitted to and stored on GitHub infrastructure. In an agent workflow, users may place credentials, client data, internal plans, or other sensitive material into these files, so the lack of an explicit data-sensitivity warning increases the risk of unintentional data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The installation section tells users to clone a repository and immediately execute its installer, but does not prominently disclose that this runs downloaded shell code and modifies local directories, symlinks, and configuration under the user's home directory. This is risky because shell installers execute with the user's privileges and can alter the environment in ways users may not fully understand or review first.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 85)May include surrounding context.

Quick Start

1. Create a new seddo (one agent, any machine)

bash
seddo init

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises and relies on shell execution (bash, gh, install scripts, local file writes) but does not declare an explicit tool scope such as permissions or allowed-tools. In agent environments, that mismatch can cause the orchestrator or user to underestimate the skill's execution capabilities, increasing the chance of unintended command execution and filesystem or network side effects.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
74% confidence
Finding

The skill explicitly maintains persistent state across sessions under ~/.seddo.d/, including active seddo selection and per-seddo configuration. Persistent agent state is not inherently malicious, but in a coordination skill that also uses shell and GitHub APIs it can retain sensitive identifiers, influence later agent behavior, and create cross-session trust or data-leakage risks if not clearly bounded and protected.

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

bash
# Setup
seddo init                 # Create a new hub seddo (creates a gist)
seddo join <gist-id>      # Fork and join an existing seddo
seddo list                 # Show all seddos on this machine
seddo switch <name>       # Switch to another seddo

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The installation instructions clone a remote repository into /tmp and immediately execute install.sh, which is effectively running unreviewed code from the network. This creates a direct supply-chain execution path: if the repo, branch, transport, or local temp path is compromised, arbitrary code runs with the user's privileges.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The init/join flows persist role, gist identifiers, and coordination metadata in ~/.seddo.d/<name>/config and state.json, enabling behavior to carry across future sessions. In this context, persistent coordination state tied to remote gists can affect later actions, expose operational metadata, and cause agents to interact with external resources based on old local state without fresh user review.

Content

Scanner excerpt · SKILL.md (reported line 153)May include surrounding context.

text
seddo init
  → Ask: seddo name, agent name, other agents
  → Create hub gist with all 7 files
  → Save ~/.seddo.d/<name>/config (ROLE=hub)
  → Generate join token

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · install.sh (reported line 38)May include surrounding context.

sh
echo "   Install path:   ${DEST}"
echo ""

mkdir -p "$DEST/scripts" "$DEST/templates"

cp "$REPO_DIR/SKILL.md" "$DEST/"
cp "$REPO_DIR/scripts/seddo.sh" "$DEST/scripts/"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.sh (reported line 55)May include surrounding context.

sh
echo ""
  echo "⚠️  Cannot write to ${BIN_DIR} (no sudo). Choose one:"
  echo ""
  echo "   Option A — sudo symlink:"
  echo "   sudo ln -sf ${DEST}/scripts/seddo.sh ${BIN_DIR}/seddo"
  echo ""
  echo "   Option B — user bin (no sudo):"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · install.sh (reported line 56)May include surrounding context.

sh
echo ""
  echo "⚠️  Cannot write to ${BIN_DIR} (no sudo). Choose one:"
  echo ""
  echo "   Option A — sudo symlink:"
  echo "   sudo ln -sf ${DEST}/scripts/seddo.sh ${BIN_DIR}/seddo"
  echo ""
  echo "   Option B — user bin (no sudo):"

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/seddo.sh (reported line 76)May include surrounding context.

sh
if [[ -n "$old_gist_id" ]]; then
      echo "📦 Auto-migrating old seddo config to new format..."
      mkdir -p "$SEDDO_ROOT"
      local seddo_dir="${SEDDO_ROOT}/${old_swarm_name}"
      mkdir -p "$seddo_dir"
      cat > "$seddo_dir/config" << EOF

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script performs a direct network request to api.github.com and injects the result of gh auth token into an Authorization header. Although the file generally indicates it works via GitHub Gist, this specific credential-bearing HTTP call has no local comment, prompt, or user-facing disclosure explaining that the GitHub token is being accessed and sent in a request.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/seddo.sh (reported line 281)May include surrounding context.

sh
curl -s -X POST \
    -H "Authorization: Bearer $(gh auth token)" \
    -H "Accept: application/vnd.github+json" \
    "https://api.github.com/gists/${gist_id}/forks"
}

get_gh_user() {

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The embedded protocol tells agents 'Append, don't overwrite,' but the implementation repeatedly rewrites whole files using PATCH requests after reconstructing merged content, including TASKS.md, INBOX.md, ACTIVITY.md, LESSONS.md, ROSTER.md, and PROTOCOL.md. Although intended to preserve content, the actual operation is full-file overwrite, contradicting the stated rule.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

TASKS.md is initialized with the instruction 'Append only. Do not edit others' tasks without permission,' yet later commands like claim, update, and done modify existing task blocks in place, and merge_tasks resolves conflicts with last-write-wins semantics. This is an active contradiction between documented behavior and actual mutation of prior task content.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/seddo.sh (reported line 1588)May include surrounding context.

sh
echo "Usage: seddo <command> [args]"
    echo ""
    echo "Setup:"
    echo "  init                  Create a new hub seddo (creates a gist)"
    echo "  join <gist-id>        Fork and join an existing seddo"
    echo "  list                  Show all seddos on this machine (~/.seddo.d/)"
    echo "  switch <name>         Switch to another seddo"

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This markdown file documents that the system reads and writes a shared private GitHub Gist and stores related configuration in ~/.seddo, but it does not warn users that actions will modify shared remote state or may expose repository identifiers and activity to GitHub. Under the markdown variant of SQP-2, descriptions should disclose behaviors that can affect user data, privacy, or system integrity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains user-facing skill instructions exclusively in French, including installation, usage, and troubleshooting guidance. Under the policy criteria, forcing a specific language without user opt-in can be a natural-language policy violation when no language choice or justification is provided.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a GitHub Gist-based coordination bus for agents, but the script also hashes local files (SKILL.md, the script itself, and AGENTS.md) and later publishes that hash into shared ROSTER data. This creates a capability to fingerprint local installed skill contents across machines, which is not necessary for basic message/task coordination and is not stated in the manifest.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest frames the skill as coordination through private GitHub Gists as the shared bus, but the implementation additionally manages a local workspace hierarchy, active-state tracking, and migration from an older local config format. While not dangerous, this expands behavior beyond the narrow remote coordination description and may surprise users expecting only gist-based coordination.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The roster template uses French column headers such as "Capacités", "Localisation", and "Disponibilité" with no indication that the language is optional or limited to a French-speaking context. This can violate language/locale policy because it imposes a specific language without user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.