Back to skill

Security audit

rotifer-self-evolving-agent

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly transparent and purpose-aligned, but running agents can execute an unpinned npm fallback, so it deserves review before installation.

Install only if you are comfortable with Rotifer modifying project Gene files and executing Gene code. Before using /evolve run-agent, install and review a pinned @rotifer/playground CLI version so the unpinned npx fallback is not used; also review any proposed Gene replacement like a dependency because Genes are unsigned third-party code.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
| **Executes** | `/evolve run-agent` runs an Agent's Genes, inside the WASM sandbox. This Skill cannot disable that sandbox. Each run appends a line to `~/.rotifer/run-logs/<gene>.jsonl` and updates a fitness file beside the Agent — both local, neither transmitted. |
| **Writes** | Genes into `genes/` (`/evolve upgrade`) and Agent definitions into `.rotifer/agents/` (`/evolve create-agent`) — both are project files, written under the project root, not into your home directory. That root defaults to the directory you are in and is an argument the install tool accepts, so it is whichever project the call names; these commands name the current one, and `rotifer.json`'s `genes_dir` can rename `genes/`. Plus a run log at `~/.rotifer/run-logs/<gene>.jsonl` when you run an Agent, and an update-check cache at `~/.config/rotifer/update-check.json`. Nothing outside those four. |
| **Sends** | Gene and Arena queries to the public Rotifer API, and one version check per day to `registry.npmjs.org`. **When you are logged in, each MCP tool call is also logged to Rotifer Cloud** — the tool's name, the Gene it acted on, whether it succeeded, how long it took, and your Rotifer user id. **Logged out, no usage record is sent** — but installing a Gene bumps that Gene's public install counter either way, one request carrying the Gene id and no identity. `ROTIFER_TELEMETRY=0` stops all three. Argument values, file contents, environment variables and your local configuration are not sent. |
| **Credentials** | It does not read your environment variables or other tools' secrets. Public data needs no login. If you do log in, your Rotifer session token is written to `~/.rotifer/credentials.json` with `0600` permissions and sent only to the Rotifer API. Genes and Agents do not live there — they are project files. |

**Every replacement is confirmed by you.** `/evolve` and `/evolve status` only
read and report. `/evolve upgrade` proposes a specific swap and waits — no Gene

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
| **Executes** | `/evolve run-agent` runs an Agent's Genes, inside the WASM sandbox. This Skill cannot disable that sandbox. Each run appends a line to `~/.rotifer/run-logs/<gene>.jsonl` and updates a fitness file beside the Agent — both local, neither transmitted. |
| **Writes** | Genes into `genes/` (`/evolve upgrade`) and Agent definitions into `.rotifer/agents/` (`/evolve create-agent`) — both are project files, written under the project root, not into your home directory. That root defaults to the directory you are in and is an argument the install tool accepts, so it is whichever project the call names; these commands name the current one, and `rotifer.json`'s `genes_dir` can rename `genes/`. Plus a run log at `~/.rotifer/run-logs/<gene>.jsonl` when you run an Agent, and an update-check cache at `~/.config/rotifer/update-check.json`. Nothing outside those four. |
| **Sends** | Gene and Arena queries to the public Rotifer API, and one version check per day to `registry.npmjs.org`. **When you are logged in, each MCP tool call is also logged to Rotifer Cloud** — the tool's name, the Gene it acted on, whether it succeeded, how long it took, and your Rotifer user id. **Logged out, no usage record is sent** — but installing a Gene bumps that Gene's public install counter either way, one request carrying the Gene id and no identity. `ROTIFER_TELEMETRY=0` stops all three. Argument values, file contents, environment variables and your local configuration are not sent. |
| **Credentials** | It does not read your environment variables or other tools' secrets. Public data needs no login. If you do log in, your Rotifer session token is written to `~/.rotifer/credentials.json` with `0600` permissions and sent only to the Rotifer API. Genes and Agents do not live there — they are project files. |

**Every replacement is confirmed by you.** `/evolve` and `/evolve status` only
read and report. `/evolve upgrade` proposes a specific swap and waits — no Gene

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

md
> `force: true` moves the replaced Gene into `<genes>/.snapshots/` before
> writing. Say so when you use it, and tell the user the two ways back:
> `rollback_gene` here, or `rotifer rollback <name>` in a terminal. One snapshot
> per Gene — the next overwrite of the same Gene supersedes it, and a rollback
> consumes it, so this undoes the last upgrade rather than a history.

## Discovery & Comparison

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

The skill documents and permits execution via an unpinned npx -y @rotifer/playground fallback, which fetches whatever version the npm registry serves at runtime. That creates a supply-chain risk: reviewed behavior can change without a repository change, and a compromised package, malicious publish, or dependency hijack could lead to execution of attacker-controlled code when run-agent is used.

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

md
- **Reads** installed Genes under `genes/`, and Agent definitions under `.rotifer/agents/` — both in the current project — to generate upgrade recommendations.
- Local configuration is **designed not to be transmitted** to any server. Comparison logic runs locally against data fetched from the public API. The only thing that leaves the machine beyond your queries is the usage record described under [Network requests](#network-requests) — tool name, Gene id, outcome, latency, user id — sent only while you are logged in, and nothing beyond it. You can verify both by inspecting the [source code](https://github.com/rotifer-protocol/rotifer-mcp-server).
- **Writes** are four things and nothing else:
  - Genes into `genes/` (`install_gene`), and the copy an overwrite replaces into `genes/.snapshots/`
  - Agent definitions into `.rotifer/agents/` (`create_agent`), and a fitness state file beside them when you run one
  - a run log at `~/.rotifer/run-logs/<gene>.jsonl` (`agent_run`) — one line per Gene execution, mode `0600`, rotated at 10 MB, never transmitted
  - the update-check cache above

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding

This second occurrence repeats the same unsafe pattern: an unpinned npx invocation for @rotifer/playground in the permission justification section. Even though the text warns about the risk, the behavior still enables execution of mutable remote code at runtime, which is dangerous in a skill that can execute agent genes and shell out to a CLI.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.