Back to skill

Security audit

Rydberg Agent Node

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned for deploying a blockchain agent node, but it handles credentials and remote code in ways that warrant careful review before installation.

Install only if you are comfortable running a hot local blockchain node from ProbeChain release artifacts. Use a dedicated low-value testnet account and machine profile where possible, do not reuse passwords, treat ~/rydberg-agent/password.txt and the keystore as sensitive, and review the generated start-bg.sh before running it. The skill should ideally pin immutable releases, validate bootnode data, avoid persistent plaintext passwords, and use short-lived unlocks.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:159
Finding
Unvalidated Remote Bootnode Data Is Injected into an Executable Shell Script<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 159-198 **Vulnerability Type**: Command and script injection through untrusted remote configuration **Risk Level**: High ### Vulnerable Code ```bash # Fetch official bootnode pinned to release tag (immutable reference) REPO="ProbeChain/Rydberg-Mainnet" RELEASE_TAG=$(curl -sSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | head -1 | cut -d'"' -f4) ENODE=$(curl -sSL "https://raw.githubusercontent.com/${REPO}/${RELEASE_TAG}/bootnodes.txt" | head -1) cat > ~/rydberg-agent/start-bg.sh << 'SCRIPT' #!/usr/bin/env bash cd ~/rydberg-agent ./gprobe \ --datadir ./data \ --networkid 8004 \ --port 30398 \ --http --http.addr 127.0.0.1 --http.port 8549 \ --http.api "probe,net,web3,pob,txpool" \ --http.corsdomain "http://localhost:*" \ --consensus pob \ --miner.probebase ADDR_PLACEHOLDER \ --password ./password.txt \ --ipcpath ~/rydberg-agent/gprobe.ipc \ --bootnodes "ENODE_PLACEHOLDER" \ --verbosity 3 > node.log 2>&1 & ./gprobe attach ~/rydberg-agent/gprobe.ipc --exec "admin.addPeer('ENODE_PLACEHOLDER')" 2>/dev/null SCRIPT sed -i.bak "s|ADDR_PLACEHOLDER|$ADDR|g; s|ENODE_PLACEHOLDER|$ENODE|g" ~/rydberg-agent/start-bg.sh rm -f ~/rydberg-agent/start-bg.sh.bak chmod +x ~/rydberg-agent/start-bg.sh ``` ### Technical Analysis The first line of the remotely hosted `bootnodes.txt` file is assigned to `ENODE` and substituted directly into an executable shell script using `sed`. The value is not validated against the expected enode URI syntax and is not escaped for either of the contexts in which it is embedded: 1. A double-quoted shell argument to `--bootnodes`. 2. A quoted JavaScript expression supplied to the local IPC console. Although the URL uses HTTPS and references a release tag, the tag and repository remain under upstream control. A release tag is not necessarily an immutable commit. If the repository, maintainer account, tag, or retrieved file ...[truncated 1518 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `ENODE` against the complete expected enode URI grammar before using it. Reject whitespace, newlines, control characters, quotes, shell metacharacters, and unexpected URI parameters. 2. Do not generate executable source code through textual placeholder replacement. 3. Pass validated values as arguments or environment variables using shell arrays and strict quoting. 4. If replacement is unavoidable, escape all characters meaningful to both `sed` and the destination context. 5. Pin `bootnodes.txt` to an audited immutable commit hash rather than a mutable release tag. 6. Verify the file against a digest embedded in the reviewed Skill or a signature validated with an independently trusted public key. 7. Enable strict shell behavior such as `set -euo pipefail` and make failed or empty downloads abort deployment. 8. Use `curl --fail --show-error --location` and reject unexpected response content. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
SKILL.md:94
Finding
Mutable Remote Executable Code Is Built or Installed Without Independent Trust Verification<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 94-140 **Vulnerability Type**: Remote payload retrieval and supply-chain compromise **Risk Level**: Medium ### Vulnerable Code ```bash REPO="ProbeChain/Rydberg-Mainnet" # Fetch latest release metadata from the official ProbeChain GitHub organization RELEASE_JSON=$(curl -sSL "https://api.github.com/repos/${REPO}/releases/latest") RELEASE_TAG=$(echo "$RELEASE_JSON" | grep '"tag_name"' | head -1 | cut -d'"' -f4) if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then RELEASE_URL=$(echo "$RELEASE_JSON" | grep "browser_download_url.*darwin.*arm64.*tar.gz" | head -1 | cut -d'"' -f4) CHECKSUM_URL=$(echo "$RELEASE_JSON" | grep "browser_download_url.*SHA256SUMS" | head -1 | cut -d'"' -f4) curl -sSL "$RELEASE_URL" -o gprobe-darwin-arm64.tar.gz if [ -z "$CHECKSUM_URL" ]; then echo "ERROR: No SHA256SUMS found in release. Cannot verify binary integrity. Aborting." rm -f gprobe-darwin-arm64.tar.gz exit 1 fi curl -sSL "$CHECKSUM_URL" -o SHA256SUMS SIG_URL=$(echo "$RELEASE_JSON" | grep "browser_download_url.*SHA256SUMS.asc" | head -1 | cut -d'"' -f4) PUBKEY_URL=$(echo "$RELEASE_JSON" | grep "browser_download_url.*probechain-gpg-public.asc" | head -1 | cut -d'"' -f4) if command -v gpg &>/dev/null && [ -n "$SIG_URL" ] && [ -n "$PUBKEY_URL" ]; then curl -sSL "$PUBKEY_URL" -o probechain-gpg-public.asc curl -sSL "$SIG_URL" -o SHA256SUMS.asc gpg --import probechain-gpg-public.asc 2>/dev/null gpg --verify SHA256SUMS.asc SHA256SUMS 2>/dev/null || { echo "ERROR: GPG signature verification failed" rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS* exit 1 } rm -f probechain-gpg-public.asc SHA256SUMS.asc fi shasum -a 256 --check --ignore-missing SHA256SUMS || { echo "ERROR: checksum verification failed" rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS ...[truncated 3085 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the source to a reviewed immutable commit hash rather than discovering the latest release dynamically. 2. Embed the expected binary and source-artifact SHA-256 digests in the reviewed Skill. 3. Require cryptographic signature verification; abort when GPG or the signature is unavailable. 4. Pin and verify an independently obtained signing-key fingerprint. Do not trust a public key downloaded alongside the artifact it authenticates. 5. Verify the checked-out commit after cloning, and reject any mismatch. 6. Apply equivalent digest or signature verification to `genesis.json` and `bootnodes.txt`. 7. Use `curl --fail --show-error --location` and validate that all parsed URLs use the expected HTTPS host. 8. Consider publishing reproducible-build information so prebuilt binaries can be compared against binaries built from the pinned source. 9. Review and pin Go module dependencies used by the source build. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:85
Finding
Plaintext Wallet Password Is Retained and Exposed in Process Arguments While the Account Is Unlocked Indefinitely<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 85-187 **Vulnerability Type**: Insecure credential handling and excessive account-unlock duration **Risk Level**: High ### Vulnerable Code ```bash # Securely save password (restricted permissions, never echoed to terminal) read -sp "Enter node password (min 6 chars): " NODE_PWD && echo (umask 077; printf '%s' "$NODE_PWD" > password.txt) unset NODE_PWD ``` ```bash # Create account ./gprobe --datadir ./data account new --password password.txt ``` ```bash ./gprobe \ --datadir ./data \ --networkid 8004 \ --port 30398 \ --http --http.addr 127.0.0.1 --http.port 8549 \ --http.api "probe,net,web3,pob,txpool" \ --http.corsdomain "http://localhost:*" \ --consensus pob \ --miner.probebase ADDR_PLACEHOLDER \ --password ./password.txt \ --ipcpath ~/rydberg-agent/gprobe.ipc \ --bootnodes "ENODE_PLACEHOLDER" \ --verbosity 3 > node.log 2>&1 & ``` ```bash # Unlock account via local IPC (not exposed over HTTP) ./gprobe attach ~/rydberg-agent/gprobe.ipc --exec \ "personal.unlockAccount('ADDR_PLACEHOLDER', '$(cat password.txt)', 0)" 2>/dev/null ``` ### Technical Analysis The Skill stores the account password in plaintext at `~/rydberg-agent/password.txt` and does not remove it after account creation or startup. The use of `umask 077` appropriately restricts the file at creation, but it does not protect the credential from processes running as the same user, later permission changes, user-level malware, backups, or accidental disclosure. The command substitution `$(cat password.txt)` inserts the secret directly into the argument passed to `gprobe attach`. Depending on operating-system process inspection controls and timing, command-line arguments may be observable through process listings or process metadata. The account is unlocked using duration `0`, which conventionally represents an indefinite unlock. This exceeds the minimum privilege necessary for a one-time registration ...[truncated 1717 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Avoid permanently storing a reusable plaintext password. 2. Use an operating-system credential store, protected external signer, hardware wallet, or node-supported secure secret mechanism. 3. If a password file is unavoidable, use a short-lived securely created file descriptor or temporary file, enforce mode `0600`, and securely remove it immediately after use. 4. Never interpolate secrets into command-line arguments. Supply the password through a protected standard-input channel, inherited file descriptor, or supported secret API. 5. Replace indefinite unlock duration `0` with the shortest practical timeout. 6. Unlock only for the exact operation requiring signing and explicitly lock the account afterward. 7. Explicitly restrict permissions on the installation directory, data directory, keystore, and IPC socket. 8. Verify the ownership and permissions of an existing installation before reading credentials or connecting to IPC. 9. Consider a dedicated, minimally privileged operating-system account for the node. 10. Warn users that the generated account is a hot wallet and should not hold unrelated or high-value funds. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (16)

Credential Access

High
Category
Privilege Escalation
Content
# Securely save password (restricted permissions, never echoed to terminal)
read -sp "Enter node password (min 6 chars): " NODE_PWD && echo
(umask 077; printf '%s' "$NODE_PWD" > password.txt)
unset NODE_PWD

# Detect OS and download binary
Confidence
98% confidence
Finding
The skill stores the node password in plaintext on disk as password.txt, creating a durable local secret that can be read by malware, backups, other processes running as the user, or accidental disclosure. Even with umask 077, plaintext-at-rest credentials materially increase credential theft risk.

Chaining Abuse

High
Category
Tool Misuse
Content
curl -sSL "$PUBKEY_URL" -o probechain-gpg-public.asc
        curl -sSL "$SIG_URL" -o SHA256SUMS.asc
        gpg --import probechain-gpg-public.asc 2>/dev/null
        gpg --verify SHA256SUMS.asc SHA256SUMS 2>/dev/null || { echo "ERROR: GPG signature verification failed"; rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS*; exit 1; }
        echo "GPG signature verified (ProbeChain <dev@probechain.org>)"
        rm -f probechain-gpg-public.asc SHA256SUMS.asc
    fi
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
curl -sSL "$PUBKEY_URL" -o probechain-gpg-public.asc
        curl -sSL "$SIG_URL" -o SHA256SUMS.asc
        gpg --import probechain-gpg-public.asc 2>/dev/null
        gpg --verify SHA256SUMS.asc SHA256SUMS 2>/dev/null || { echo "ERROR: GPG signature verification failed"; rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS*; exit 1; }
        echo "GPG signature verified (ProbeChain <dev@probechain.org>)"
        rm -f probechain-gpg-public.asc SHA256SUMS.asc
    fi
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
fi
    shasum -a 256 --check --ignore-missing SHA256SUMS || { echo "ERROR: checksum verification failed"; rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS; exit 1; }
    rm -f SHA256SUMS
    tar xzf gprobe-darwin-arm64.tar.gz && rm -f gprobe-darwin-arm64.tar.gz
    chmod +x gprobe
else
    # All other platforms: build from source using pinned release tag
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
fi
    shasum -a 256 --check --ignore-missing SHA256SUMS || { echo "ERROR: checksum verification failed"; rm -f gprobe-darwin-arm64.tar.gz SHA256SUMS; exit 1; }
    rm -f SHA256SUMS
    tar xzf gprobe-darwin-arm64.tar.gz && rm -f gprobe-darwin-arm64.tar.gz
    chmod +x gprobe
else
    # All other platforms: build from source using pinned release tag
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
curl -sSL "https://raw.githubusercontent.com/${REPO}/${RELEASE_TAG}/genesis.json" -o genesis.json

# Create account
./gprobe --datadir ./data account new --password password.txt

# Initialize genesis
./gprobe --datadir ./data init genesis.json
Confidence
97% confidence
Finding
Using a plaintext password file for account creation reinforces insecure secret handling and leaves credential material available on disk beyond the initial setup phase. In a deployment skill that also starts long-lived services, this creates ongoing credential exposure.

Credential Access

High
Category
Privilege Escalation
Content
--http.corsdomain "http://localhost:*" \
  --consensus pob \
  --miner.probebase ADDR_PLACEHOLDER \
  --password ./password.txt \
  --ipcpath ~/rydberg-agent/gprobe.ipc \
  --bootnodes "ENODE_PLACEHOLDER" \
  --verbosity 3 > node.log 2>&1 &
Confidence
98% confidence
Finding
Passing --password ./password.txt to the node startup path means the long-running service depends on a plaintext password file remaining on disk. This turns a one-time secret into persistent standing access for local attackers to unlock and control the account.

Credential Access

High
Category
Privilege Escalation
Content
./gprobe attach ~/rydberg-agent/gprobe.ipc --exec "admin.addPeer('ENODE_PLACEHOLDER')" 2>/dev/null

# Unlock account via local IPC (not exposed over HTTP)
./gprobe attach ~/rydberg-agent/gprobe.ipc --exec "personal.unlockAccount('ADDR_PLACEHOLDER', '$(cat password.txt)', 0)" 2>/dev/null

# Start mining via IPC
./gprobe attach ~/rydberg-agent/gprobe.ipc --exec "miner.start(1)" 2>/dev/null
Confidence
99% confidence
Finding
The script interpolates $(cat password.txt) directly into an IPC command that unlocks the account indefinitely with duration 0. This exposes the password to script contents and process/runtime artifacts and creates a permanently unlocked account, significantly increasing the blast radius of any local compromise.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SCRIPT

sed -i.bak "s|ADDR_PLACEHOLDER|$ADDR|g; s|ENODE_PLACEHOLDER|$ENODE|g" ~/rydberg-agent/start-bg.sh
rm -f ~/rydberg-agent/start-bg.sh.bak
chmod +x ~/rydberg-agent/start-bg.sh
```
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger phrase "deploy rydberg validator" materially misrepresents what the skill does, because the skill explicitly deploys an Agent node and performs installation, registration, and background execution. This can cause unintended activation for users seeking different behavior and increases the chance the agent will run invasive system actions under an ambiguous request.

External Transmission

Medium
Category
Data Exfiltration
Content
- network:outbound
  - system:exec
requirements:
  - curl
  - tar
  - shasum
  - git (source build only)
Confidence
88% confidence
Finding
The declared permissions include outbound network access and system command execution, which are high-risk capabilities in a skill that downloads software and launches a node. In context, these capabilities are expected for deployment, but they still expand the attack surface and warrant strong guardrails and explicit consent.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill does not prominently disclose upfront that it will execute shell commands, write secrets and binaries to disk, fetch remote content, and launch a background node process. That omission weakens informed consent and makes potentially risky behavior easier to trigger without the user understanding the consequences.

External Transmission

Medium
Category
Data Exfiltration
Content
REPO="ProbeChain/Rydberg-Mainnet"

# Fetch latest release metadata from the official ProbeChain GitHub organization
RELEASE_JSON=$(curl -sSL "https://api.github.com/repos/${REPO}/releases/latest")
RELEASE_TAG=$(echo "$RELEASE_JSON" | grep '"tag_name"' | head -1 | cut -d'"' -f4)

if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then
Confidence
91% confidence
Finding
The skill fetches release metadata from GitHub at runtime and then uses that data to select code to download or source to build. Because trust is rooted in a live network response and source tags rather than a pinned artifact digest or independently trusted key, a compromised upstream, release process, or repo could supply malicious code for execution.

External Transmission

Medium
Category
Data Exfiltration
Content
# Fetch official bootnode pinned to release tag (immutable reference)
REPO="ProbeChain/Rydberg-Mainnet"
RELEASE_TAG=$(curl -sSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | head -1 | cut -d'"' -f4)
ENODE=$(curl -sSL "https://raw.githubusercontent.com/${REPO}/${RELEASE_TAG}/bootnodes.txt" | head -1)

cat > ~/rydberg-agent/start-bg.sh << 'SCRIPT'
Confidence
89% confidence
Finding
The start script fetches the latest release tag again at runtime to obtain bootnode data, creating mutable remote dependency after installation. This allows network-supplied configuration to influence peer connectivity and node behavior without strong authenticity guarantees beyond GitHub transport.

Vague Triggers

Low
Confidence
84% confidence
Finding
The trigger set lacks boundaries for when the skill should not activate, despite the skill performing privileged operations like executing shell commands, downloading code, and starting a persistent service. Broad activation criteria increase the risk of accidental invocation and unintended system modification.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The instruction "Always reply in the user's language (Chinese if Chinese)" sets a language behavior rule rather than offering a user choice. While mild, it still hardcodes locale handling instead of explicitly asking or allowing opt-in when language preference is ambiguous.

Static analysis

No suspicious patterns detected.