Back to skill

Security audit

stratos-storage

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it combines network file transfer and node setup with under-scoped triggers, risky download file handling, and limited warnings around wallet secrets, open ports, and staking funds.

Review before installing. Use it only for explicit Stratos upload or download requests, avoid uploading sensitive files, choose download destinations in a private trusted directory, protect wallet mnemonics and passwords outside chats or source-controlled files, restrict node service ports with a firewall, and verify network, wallet, amount, and fees before staking STOS.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download.sh:21
Finding

Symlink and TOCTOU-Based Arbitrary File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/download.sh, lines 21–36 and 43–45
Vulnerability Type: Symlink following and time-of-check/time-of-use race
Risk Level: Medium

Vulnerable Code

bash
# Check if output file already exists
if [ -e "$OUTPUT_PATH" ]; then
    echo "ERROR: Output path already exists: $OUTPUT_PATH"
    echo "Please choose a different output path or confirm overwrite."
    exit 1
fi

# Ensure output directory exists
OUTPUT_DIR=$(dirname "$OUTPUT_PATH")
if [ ! -d "$OUTPUT_DIR" ]; then
    mkdir -p "$OUTPUT_DIR"
    echo "Created output directory: $OUTPUT_DIR"
fi

echo "Downloading: $FILE_HASH"
echo "Destination: $OUTPUT_PATH"

# Try SPFS HTTP API first
try_spfs_download() {
    local http_code
    http_code=$(curl -s -w "%{http_code}" -X POST \
        "${SPFS_GATEWAY}/api/v0/get?arg=${FILE_HASH}" \
        -o "$OUTPUT_PATH" 2>/dev/null)

Technical Analysis

The script checks whether the destination exists and later asks curl to open that path. These are separate filesystem operations, creating a time-of-check/time-of-use race.

The check also uses test -e, which ordinarily returns false for a dangling symbolic link. Consequently, a dangling symlink can pass the existence check. When curl -o subsequently opens the destination, it follows the symbolic link and writes the downloaded content to its target.

Even when no symlink exists during the check, an attacker with write access to the destination directory can replace the checked path with a symbolic link before curl opens it. Quoting "$OUTPUT_PATH" prevents shell word splitting and command injection, but it does not prevent symbolic-link traversal or the race.

Attack Path

  1. A victim invokes the download script with an output path located in a directory writable by an attacker.
  2. The attacker creates a dangling symbolic link at the requested output path that points to another file writable by the victim or Agent. Alternatively, the attacker ...[truncated 1096 chars]
Remediation
View remediation

Remediation Suggestions

  1. Reject symbolic-link destinations explicitly with [ -L "$OUTPUT_PATH" ], while recognizing that this check alone does not eliminate the race.
  2. Restrict downloads to a trusted directory that is not writable by other users.
  3. Create a temporary file securely in the destination directory using mktemp, with restrictive permissions and a trusted fixed directory.
  4. Download into the secure temporary file rather than directly into the final path.
  5. Validate the completed download, including the HTTP status and expected content integrity where such metadata is available.
  6. Install the temporary file at the destination using an atomic no-clobber operation. Ensure that the operation fails if the destination already exists and does not follow symbolic links.
  7. Clean up the temporary file through a shell trap on normal exit and signals.
  8. Validate that the destination directory itself is not a symlink and remains within the approved download root after canonicalization.
  9. If implementation portability permits, use a helper that opens the final destination with operating-system flags equivalent to O_CREAT | O_EXCL | O_NOFOLLOW.

A safer workflow is:

bash
OUTPUT_DIR=$(dirname -- "$OUTPUT_PATH")

if [ -L "$OUTPUT_PATH" ] || [ -e "$OUTPUT_PATH" ]; then
    echo "ERROR: Output path already exists or is a symbolic link: $OUTPUT_PATH"
    exit 1
fi

TEMP_FILE=$(mktemp "${OUTPUT_DIR}/.stratos-download.XXXXXX")
trap 'rm -f -- "$TEMP_FILE"' EXIT HUP INT TERM

http_code=$(curl -sS -w "%{http_code}" -X POST \
    "${SPFS_GATEWAY}/api/v0/get?arg=${FILE_HASH}" \
    -o "$TEMP_FILE")

if [ "$http_code" != "200" ] || [ ! -s "$TEMP_FILE" ]; then
    echo "ERROR: Download failed"
    exit 1
fi

# Use a platform-appropriate atomic no-clobber installation mechanism here.

The final installation step must preserve the no-overwrite guarantee atomically; merely repeating an existence check before mv is insufficient.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description claims both upload and download support for Stratos SDS. However, the provided script is exclusively an upload utility (upload.sh). It accepts a local file path, checks that the file exists, attempts an HTTP multipart upload to /api/v0/add, and if that fails, falls back to ppd terminal put. There is no logic for downloading, retrieving by CID/hash, reading remote content, or writing downloaded data locally. The Stratos-related resource usage is consistent with the declared domain, but the implemented capability is only a subset of the declared purpose, making the description inaccurate for this code chunk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes shell scripts (bash .../upload.sh and bash .../download.sh) but does not declare any tool scope such as permissions or allowed-tools. That creates an authorization gap where a runtime may permit broader shell execution than users or policy expect, increasing the chance of unintended command execution or abuse through this skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger guidance includes broad keyword mentions like "Stratos," "SDS," "SPFS," or "decentralized storage upload/download," which can cause the skill to activate on vague or incidental references. In a skill that performs file transfer via shell scripts, unintended invocation raises the risk of surprising data exfiltration, unwanted downloads, or user confusion about which action is being taken.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The setup flow requires handling a wallet password, P2P key password, and especially a 24-word mnemonic, but the guidance only says to back it up and does not warn against storing it in plaintext, screenshots, shell history, chat logs, or source-controlled files. Because the mnemonic and credentials control wallet recovery and node identity, insecure handling could result in theft of funds, node takeover, or permanent account compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The guide explicitly tells operators to expose port 18081 to the internet and documents several additional service ports, but it does not provide security guidance on limiting exposure, binding admin interfaces to localhost, using firewalls, or enabling TLS where available. In infrastructure setup documentation, this omission can lead users to unintentionally expose RPC, monitoring, REST, or web management surfaces, increasing the attack surface of the node.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documentation describes wallet and P2P password fields in the configuration without warning that storing secrets in plaintext config files is highly sensitive. Users may leave long-lived credentials readable on disk, exposing wallets or node identity material to other local users, backups, logs, or accidental commits.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The guide lists several service and API ports and states that the main communication port must be opened externally, but it does not clearly distinguish which ports should remain restricted to localhost or trusted networks. In a node-setup context, readers may overexpose RPC, monitoring, SPFS, REST, or web management interfaces, increasing the attack surface and enabling unauthorized access, information disclosure, or abuse of administrative endpoints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation instructions tell users to execute a staking transaction with a specific amount of STOS, but they do not clearly warn that this is a real on-chain action involving funds and that mistakes may be irreversible or costly. In a setup guide for a storage node, less experienced operators may follow commands blindly and lock funds, pay fees, or stake on the wrong environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The filename and document content indicate an English-only setup guide, with no indication that users can choose another language or locale. Under SQP-3, forcing a specific language without opt-in can be a natural-language policy violation unless clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.