Back to skill

Security audit

Seddo Bump

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated GitHub Gist coordination purpose, but it has review-worthy risks around untrusted agent tasks, GitHub credential handling, remote installation, and unsafe local path handling.

Install only if you are comfortable letting this skill read and update private GitHub Gists using your GitHub authentication. Keep the join Gist ID and any GH_TOKEN secret, avoid storing them in committed project files, and do not use the one-line remote installer unless you have reviewed the fetched repository. Treat all tasks and messages imported from other forks as untrusted requests that still need normal human and agent policy review.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
scripts/seddo.sh:1009
Finding

Untrusted Gist forks can inject instructions into the canonical agent task stream

Content
View full analysis
/dev/null || echo "[]") # Extract 32-char hex gist IDs (not node_id or other IDs) local fork_ids=() while IFS= read -r fid; do [[ -n "$fid" ]] && fork_ids+=("$fid") done < <(echo "$forks_json" | grep -oP '"id":\s*"\K[a-f0-9]{32}' || true) # Read current hub state local hub_inbox hub_activity hub_lessons hub_tasks hub_inbox=$(fetch_file "INBOX.md") || { echo "❌ Abort sync: fetch hub INBOX.md failed" >&2; exit 1; } hub_activity=$(fetch_file "ACTIVITY.md") || { echo "❌ Abort sync: fetch hub ACTIVITY.md failed" >&2; exit 1; } hub_lessons=$(fetch_file "LESSONS.md") || { echo "❌ Abort sync: fetch hub LESSONS.md failed" >&2; exit 1; } hub_tasks=$(fetch_file "TASKS.md") || { echo "❌ Abort sync: fetch hub TASKS.md failed" >&2; exit 1; } local merged_count=0 for fork_id in "${fork_ids[@]}"; do echo " Merging fork ${fork_id:0:8}..." local fi_inbox fi_activity fi_lessons fi_tasks fi_inbox=$(fetch_from "$fork_id" "INBOX.md" 2>/dev/null || true) fi_activity=$(fetch_from "$fork_id" "ACTIVITY.md" 2>/dev/null || true) fi_lessons=$(fetch_from "$fork_id" "LESSONS.md" 2>/dev/null || true) fi_tasks=$(fetch_from "$fork_id" "TASKS.md" 2>/dev/null || true) [[ -n "$fi_inbox" ]] && hub_inbox=$(merge_append "$hub_inbox" "$fi_inbox") [[ -n "$fi_activity" ]] && hub_activity=$(merge_append "$hub_activity" "$fi_activity") [[ -n "$fi_lessons" ]] && hub_lessons=$(merge_append "$hub_lessons" "$fi_lessons") [[ -n "$fi_tasks" ]] && hub_tasks=$(merge_tasks "$hub_tasks" "$fi_tasks") ((merged_count++)) || true done edit_files "$GIST_ID" \ "INBOX.md" "$hub_inbox" \ "ACTIVITY.md" "$hub_activity" \ "LESSONS.md" "$hub_lessons" \ "TASKS.md" "$hub_tasks" ``` The agent-faci ...[truncated 2633 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/seddo.sh:660
Finding

Remote Gist name can escape the local Seddo workspace through path traversal

Content
View full analysis
— Seddo Protocol" local swarm_name swarm_name=$(gh gist view "$hub_gist_id" -f PROTOCOL.md 2>/dev/null \ | head -1 | sed 's/^# //' | sed 's/ —.*//' | xargs 2>/dev/null || true) [[ -z "$swarm_name" ]] && swarm_name=$(echo "$raw" \ | grep -m1 '^# Roster\|^# Protocol\|^# Tasks\|^# .*—' \ | sed 's/^# //' | sed 's/ —.*//' | xargs 2>/dev/null || true) [[ -z "$swarm_name" ]] && swarm_name="seddo" ``` The remote value is then used as a path component without the strict filtering used by `cmd_init`: ```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 save_seddo_config "$local_name" < "$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" } ``` ### Technical Analysis `cmd_init` sanitizes locally supplie ...[truncated 2267 chars]
Remediation
View remediation
&2 exit 1 fi ``` 2. Reject empty names, `.`, `..`, slashes, backslashes, control characters, and leading hyphens. 3. Resolve both `SEDDO_ROOT` and the intended workspace path to canonical absolute paths. 4. Verify that the canonical destination starts with the canonical `SEDDO_ROOT/` prefix before creating any directory or file. 5. Treat a remote display name separately from the local directory name. Generate a safe local identifier rather than reusing remote text. 6. Create the workspace with restrictive permissions and fail if an unexpected path already exists. 7. Add tests covering `../`, absolute paths, repeated separators, Unicode separator lookalikes, whitespace, control characters, and symlinked workspace roots. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/seddo.sh:276
Finding

GitHub authentication token is exposed through curl process arguments

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (19)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

rm -rf "${SEDDO_ROOT}/${name}" deletes a path influenced by user input without validating that name is a simple workspace name or canonical child of SEDDO_ROOT. An attacker or confused user could supply path traversal values such as ../... and cause deletion outside the intended workspace root, especially because the only existence check also uses the same unsanitized path.

Content

Scanner excerpt · scripts/seddo.sh (reported line 955)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
85% confidence
Finding

The skill explicitly instructs agents to persist coordination state under ~/.seddo.d/ and to maintain an active session across runs, which creates local session persistence. In a multi-agent, cross-machine coordination tool, persistent state can expose task contents, agent identities, gist IDs, and workflow metadata to other local users or later processes if not protected, and can also cause unintended reuse of stale coordination context.

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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide tells users to create a GitHub token with gist scope and export it directly in the shell, but it does not clearly warn that this token is a sensitive credential. Users may paste a long-lived token into shell history or leave it exposed in environment dumps, terminal logs, or shared sessions, which could let an attacker read or modify private gists used as the coordination channel.

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 · 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/

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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README presents the join token/gist ID as something to share with other agents, but does not clearly warn that possession of that identifier enables access to the shared private gist and therefore to messages, tasks, and coordination data. In this skill’s context, the gist is the entire communication bus, so accidental disclosure to humans, logs, prompts, screenshots, or checked-in docs can expose sensitive operational context and allow unauthorized participants to join.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README instructs users to place SWARM_GIST_ID directly into CLAUDE.md, which is commonly stored alongside project files and may be committed, synced, or shared with collaborators. Because the gist ID identifies the private coordination channel, embedding it in project documentation increases the chance of unintended disclosure of the swarm’s communication endpoint and associated data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill clearly instructs users to run shell commands and install executable scripts, but it does not declare any explicit tool scope such as allowed shell access. This weakens the host agent's safety boundary because consumers cannot easily tell that the skill requires command execution and networked GitHub operations before reading the body.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description emphasizes cross-machine and cross-account coordination via private GitHub Gists but does not prominently warn that task data, messages, agent names, and activity logs will be stored on GitHub infrastructure and replicated across accounts. This can lead users to place sensitive operational data into a third-party service without informed consent or data-classification controls.

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 · SKILL.md (reported line 55)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 one-liner clones a remote repository into /tmp and immediately executes install.sh, which is a classic supply-chain and arbitrary code execution pattern. Because the script is fetched at runtime from a mutable remote source and run without pinning, verification, or warning, a compromised repo or MITM-like trust failure could execute attacker-controlled code on the host.

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 · SKILL.md (reported line 154)May include surrounding context.

text
seddo init [--name <name>] [--agent <agent>] [--others "agent1,agent2"]
  → 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 · SKILL.md (reported line 163)May include surrounding context.

text
seddo join <gist-id> [--agent <name>] [--role spoke|hub]
  → Fork the hub gist (gives write access)
  → Save ~/.seddo.d/<name>/config (ROLE=spoke, FORK_OF=<hub-id>)
  → Auto-register in hub's REGISTRY.md
  → Log arrival in hub's INBOX.md

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

When ~/.seddo exists, the script automatically creates directories and config files, writes a new active selection, and renames the original file to a backup. These are state-changing local filesystem operations, and while there is a progress message, there is no prior warning or confirmation before modifying the user's local configuration.

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 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
85% confidence
Finding

The script retrieves a credential with gh auth token and injects it into an HTTP Authorization header for a direct curl call to the GitHub API. Although this is part of gist forking functionality, there is no explicit user-facing warning in this file at the point of use that the skill accesses and transmits the user's GitHub auth token to perform network operations.

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() {

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 1709)May include surrounding context.

sh
echo "  inbox                 Read messages"
    echo "  send @agent msg       Send a message"
    echo "  tasks                 List tasks"
    echo "  add \"title\" [PRI] [@agent]  Create a task"
    echo "  claim T-XXX           Claim a task"
    echo "  update T-XXX STATUS   Update task status"
    echo "  done T-XXX [output]   Mark task as DONE"

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file instructs the user to create directories under ~/.config and ~/.local/bin, copy files, create a symbolic link, and modify PATH. While these actions are part of installation, the document does not explicitly warn that it will alter the user's local configuration and shell environment.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.