Back to skill

Security audit

Slv Rpc

Security checks for vulnerabilities and agentic risk

Overview

This skill is for legitimate Solana RPC node operations, but it directs agents to run high-impact Ansible playbooks from a mutable local template directory outside the reviewed package.

Install only if you understand that this skill can guide an agent to make real infrastructure changes. Before running any playbook, verify the exact ~/.slv/template version, source, ownership, and contents; prefer pinned or checksummed playbooks, run Ansible check mode first, and manually review any disk formatting, ledger cleanup, sudo package installation, or curl-to-shell installer steps.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/setup.sh:87
Finding
Unverified Remote Installer Piped Directly to a Shell<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:87-92` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Medium ### Vulnerable Code ```bash if command -v solana-keygen &>/dev/null; then info "solana-cli found ($(solana-keygen --version 2>/dev/null | head -1))" else warn "solana-cli not found (optional — only needed for local key generation)" echo " → Install: sh -c \"\$(curl -sSfL https://release.anza.xyz/stable/install)\"" fi ``` ### Technical Analysis The setup script recommends downloading the response from a mutable `stable` URL and passing it directly to `sh`. The retrieved content is not pinned to a reviewed release and is not authenticated with a publisher signature or expected checksum. The command is printed rather than executed automatically, so exploitation requires the user to follow the displayed installation instruction. Nevertheless, it forms part of the Skill's intended setup flow and creates a remote code-execution channel whose effective payload can change after the Skill has been audited. TLS protects transport under normal circumstances but does not protect against compromise of the distribution service, its deployment pipeline, DNS or certificate trust infrastructure, or the upstream publisher account. ### Attack Path 1. The user runs `scripts/setup.sh` on a system without `solana-keygen`. 2. The script displays the `curl | sh` installation command as its recommended remediation. 3. The remote `stable/install` endpoint or its delivery infrastructure is compromised, or begins serving an unsafe installer. 4. The user copies and executes the displayed command. 5. The remote response is interpreted immediately by the local shell without review or integrity validation. 6. The payload executes with all permissions held by that user. ### Impact Assessment Successful exploitation permits arbitrary command execution under the invoking user's account. The payload could access user ...[truncated 396 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the mutable `stable` installer with an explicitly pinned release. 2. Download the artifact to a local file instead of piping it directly to a shell. 3. Verify a publisher-signed release signature or a checksum obtained through an independently authenticated channel. 4. Display the resolved version and verification result before execution. 5. Allow the user to inspect the downloaded installer before running it. 6. Prefer a trusted package repository or reproducible package manager installation when available. A hardened flow should follow this pattern: ```bash curl --fail --location --output installer.sh "<pinned-release-url>" echo "<expected-sha256> installer.sh" | sha256sum --check - less installer.sh sh installer.sh ``` The checksum must be updated through a controlled review process rather than retrieved from the same mutable endpoint as the installer. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
AGENT.md:175
Finding
Agent Executes Mutable Playbooks Outside the Audited Skill Package<![CDATA[ ## Vulnerability Details **File Location**: `AGENT.md:175-188` **Vulnerability Type**: Tool hijacking through unaudited executable template selection **Risk Level**: High ### Vulnerable Code ```bash All playbooks are stored in `~/.slv/template/{version}/ansible/`. To find the latest version directory: ```bash TEMPLATE_DIR=$(ls -d ~/.slv/template/*/ | sort -V | tail -1) ``` Example (mainnet RPC): ```bash TEMPLATE_DIR=$(ls -d ~/.slv/template/*/ | sort -V | tail -1) ansible-playbook -i ~/.slv/inventory.mainnet.rpcs.yml \ ${TEMPLATE_DIR}ansible/mainnet-rpc/init.yml --limit <identity_pubkey> ``` Do NOT use the skill's own `ansible/` directory for execution. Those files are reference copies. The runtime playbooks live in `~/.slv/template/`. ``` ### Technical Analysis The Agent is instructed to execute playbooks from whichever directory under `~/.slv/template/` sorts as the latest version. The selected directory is not pinned to a reviewed version, and the workflow does not validate its ownership, permissions, checksum, signed manifest, or provenance. The executable playbooks are not included in the audited project. As a result, the security-sensitive behavior ultimately performed by Ansible cannot be established from this package. Selecting executable content solely by its directory name also creates a tool-spoofing opportunity: a malicious or compromised process able to write to that location can create a higher-version directory containing attacker-controlled playbooks. The instruction explicitly prohibits using the package's reference playbooks and redirects execution to this mutable external location, widening the trust boundary beyond the reviewed Skill. ### Attack Path 1. An attacker, compromised updater, or malicious local process obtains write access to `~/.slv/template/`, or compromises the mechanism that populates it. 2. The attacker creates a directory with a version name that sorts after legitimate versions, such as `~/.slv/template ...[truncated 1326 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Include the executable playbooks in the reviewed Skill package, or bind runtime execution to an immutable, explicitly selected release. 2. Do not discover executable content using `ls | sort -V | tail -1`. 3. Record the approved template version in trusted configuration and require an exact directory match. 4. Verify every runtime template against a signed manifest or pinned cryptographic checksums before invoking Ansible. 5. Reject template directories or files that are writable by group or other users. 6. Validate that the directory is owned by the expected account and is not a symbolic link to an untrusted location. 7. Present the exact playbook path, release identity, and integrity result to the user before confirmation. 8. Maintain the existing requirement for user confirmation and use `--check` where feasible, while recognizing that dry-run mode is not a substitute for provenance validation. 9. Align `README.md`, `SKILL.md`, and `AGENT.md` so they identify one authoritative and auditable source of playbooks. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/setup.sh:33
Finding
Unpinned Installation of Ansible from the Active Python Package Index<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:33-36` **Vulnerability Type**: Insecure dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash if command -v pip3 &>/dev/null; then pip3 install --user ansible-core elif command -v pip &>/dev/null; then pip install --user ansible-core ``` ### Technical Analysis The setup script installs `ansible-core` without an exact version constraint, lock file, expected package hashes, isolated environment, or explicit trusted index. The actual version and dependency graph therefore depend on the package index and resolver state at installation time. The project documentation states a requirement of Ansible 2.15 or later, but the setup path neither pins a reviewed compatible release nor verifies the installed version after installation. It also inherits any user-level pip configuration, including alternate indexes and extra indexes. A compromised or incorrectly configured index could therefore supply unexpected package content. Although `ansible-core` is named correctly and there is no evidence of deliberate typosquatting, installing mutable dependency versions without integrity constraints exposes the setup process to upstream and package-index supply-chain compromise. ### Attack Path 1. The user runs `scripts/setup.sh` without `ansible-playbook` already installed. 2. The script discovers `pip3` or `pip`. 3. The active pip configuration points to a compromised, malicious, or otherwise untrusted package source, or the legitimate upstream release chain is compromised. 4. Pip resolves an unreviewed `ansible-core` release and its transitive dependencies. 5. Malicious installation/build behavior executes where applicable, or compromised Ansible code is installed into the user's environment. 6. The installed tooling is later trusted to process inventories and execute privileged deployment playbooks. ### Impact Assessment A compromised package or dependency could execute cod ...[truncated 519 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `ansible-core` to a reviewed exact version rather than installing the latest available release. 2. Install dependencies from a lock file containing cryptographic hashes, for example with pip's `--require-hashes`. 3. Use a dedicated virtual environment instead of modifying the general user environment. 4. Specify and enforce an approved package index; avoid uncontrolled `extra-index-url` settings. 5. Verify the installed Ansible version and fail if it differs from the approved version. 6. Review and pin transitive dependencies as part of the same lock file. 7. Prefer operating-system packages only when the repository and exact version meet the project's support and integrity requirements. Example hardened invocation: ```bash python3 -m venv ~/.local/share/slv-rpc/venv ~/.local/share/slv-rpc/venv/bin/python -m pip install \ --require-hashes \ --only-binary=:all: \ -r requirements.lock ``` The lock file should be maintained through a controlled dependency-update and security-review process. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (13)

Credential Access

High
Category
Privilege Escalation
Content
rpc-1:
      ansible_host: "<server-ip>"
      ansible_user: "solv"
      ansible_ssh_private_key_file: "~/.ssh/id_rsa"

  vars:
    # --- RPC Type ---
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
rpc-1:
      ansible_host: "<server-ip>"
      ansible_user: "solv"
      ansible_ssh_private_key_file: "~/.ssh/id_rsa"

  vars:
    # --- RPC Type ---
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
rpc-1:
      ansible_host: "<server-ip>"
      ansible_user: "solv"
      ansible_ssh_private_key_file: "~/.ssh/id_rsa"

  vars:
    # --- RPC Type ---
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Chaining Abuse

High
Category
Tool Misuse
Content
brew install ansible
  elif [[ "$OS" == "linux" ]]; then
    if command -v apt-get &>/dev/null; then
      sudo apt-get update && sudo apt-get install -y ansible-core
    elif command -v dnf &>/dev/null; then
      sudo dnf install -y ansible-core
    else
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Credential Access

High
Category
Privilege Escalation
Content
warn "SSH agent running but no keys loaded"
    echo "  → Run: ssh-add ~/.ssh/id_rsa (or your key path)"
  fi
elif [[ -f "$HOME/.ssh/id_rsa" ]] || [[ -f "$HOME/.ssh/id_ed25519" ]]; then
  info "SSH keys found (agent not running — Ansible will use key files directly)"
else
  warn "No SSH keys found"
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
warn "SSH agent running but no keys loaded"
    echo "  → Run: ssh-add ~/.ssh/id_rsa (or your key path)"
  fi
elif [[ -f "$HOME/.ssh/id_rsa" ]] || [[ -f "$HOME/.ssh/id_ed25519" ]]; then
  info "SSH keys found (agent not running — Ansible will use key files directly)"
else
  warn "No SSH keys found"
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

External Transmission

Medium
Category
Data Exfiltration
Content
1. **Local RPC Response Check** (every 30 seconds):
   ```bash
   curl -s http://localhost:8899 -X POST -H "Content-Type: application/json" \
     -d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}'
   ```
   - No response → still loading ledger, retry
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
-d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' | jq -r '.result')

   # Local slot
   LOCAL_SLOT=$(curl -s http://localhost:8899 -X POST -H 'Content-Type: application/json' \
     -d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' | jq -r '.result')

   DIFF=$((NETWORK_SLOT - LOCAL_SLOT))
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill documents a cleanup command that removes ledger/snapshot files but does not warn that this is destructive and can permanently delete large amounts of node state. In an infrastructure automation context, operators may run mapped commands directly from the documentation, so omission of a data-loss warning increases the chance of accidental service disruption or forced resync.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill advertises playbooks for mounting and formatting disks without any safety warning, which is risky because formatting can irreversibly erase attached storage if the wrong device is targeted. Given this is server-deployment automation for RPC nodes, operators are likely to run these playbooks on real infrastructure, making accidental destructive execution more plausible.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The setup script automatically installs software and may invoke system package managers and privileged commands, but it does not clearly warn the user up front that it will modify the local system. In an agent-skill context, users may run setup helpers with elevated trust, so implicit package installation increases the risk of unintended local changes and supply-chain exposure.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
brew install ansible
  elif [[ "$OS" == "linux" ]]; then
    if command -v apt-get &>/dev/null; then
      sudo apt-get update && sudo apt-get install -y ansible-core
    elif command -v dnf &>/dev/null; then
      sudo dnf install -y ansible-core
    else
Confidence
92% confidence
Finding
The script invokes sudo to run apt-get update and install ansible-core, which causes privileged system modification. While common in installers, using sudo in a skill setup script is risky because it expands the blast radius if the script or package source is compromised and may surprise users expecting a non-privileged prerequisite check.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if command -v apt-get &>/dev/null; then
      sudo apt-get update && sudo apt-get install -y ansible-core
    elif command -v dnf &>/dev/null; then
      sudo dnf install -y ansible-core
    else
      error "Cannot auto-install ansible-core. Please install manually: pip3 install ansible-core"
      exit 1
Confidence
91% confidence
Finding
The script invokes sudo to install ansible-core via dnf, performing privileged package installation. In a setup script distributed as part of an agent skill, automatic root-level package management should be treated as sensitive because it modifies the host and relies on external package repositories.

Static analysis

Detected: suspicious.generated_source_template_injection

User-controlled placeholder is embedded directly into generated source code.

Critical
Code
suspicious.generated_source_template_injection
Location
AGENT.md:195