Back to skill

Security audit

solana-stream-light

Security checks for vulnerabilities and agentic risk

Overview

This is a documentation-style Solana data-streaming skill with no hidden secret handling or persistence, though users should treat its unpinned install command and example code carefully.

Before installing, verify the repository and preferably pin the installer version and source commit. Run installation from a restricted project environment without unnecessary wallet keys or API credentials present. If you copy the Rust examples into production, add length checks and avoid `unwrap()` on network-supplied account data.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:90
Finding
Unpinned Package and Repository Execution Through npx<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:90` **Vulnerability Type**: Supply-chain exposure through mutable dependencies **Risk Level**: Medium ### Vulnerable Code ```markdown - **Install source.** `npx skills add Lightprotocol/skills` installs from the public GitHub repository ([Lightprotocol/skills](https://github.com/Lightprotocol/skills)). Verify the source before running. ``` ### Technical Analysis The documented installation command invokes `npx` without pinning the `skills` package to a reviewed version. Depending on the local npm configuration and cache, `npx` can retrieve and execute the latest available version of that package. The GitHub skill source is also specified without a commit hash or immutable release identifier. Consequently, the package executing the installation and the repository content being installed can both change after this Skill has been reviewed. The instruction to verify the source is advisory and does not provide an enforceable integrity check. This behavior is not required at runtime for the declared account-streaming functionality. Installation is a separate operation and should use immutable, verified artifacts. ### Attack Path 1. An attacker compromises the npm package, its maintainer account, the referenced GitHub repository, or another relevant supply-chain component. 2. The attacker publishes a malicious package version or modifies the repository content. 3. A user follows the documented unpinned `npx skills add Lightprotocol/skills` command. 4. `npx` retrieves and executes the mutable installer package. 5. The installer downloads or installs the attacker-controlled repository content. 6. Malicious code executes with the permissions of the user running the command. ### Impact Assessment Successful exploitation could execute arbitrary code under the installing user's account. The resulting access could include reading or modifying files available to that user, accessing environment variabl ...[truncated 332 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the `skills` npm package to a reviewed, exact version rather than relying on the latest version: ```bash npx --yes skills@EXACT_VERSION add Lightprotocol/skills ``` 2. Pin the GitHub dependency to an immutable commit hash or cryptographically signed release. 3. Publish and verify SHA-256 checksums or signatures for installed artifacts. 4. Use a lockfile and a trusted package registry with integrity metadata. 5. Prefer installing the tool explicitly and reviewing it before execution rather than allowing `npx` to download and execute it implicitly. 6. Run installation in a restricted environment without wallet keys, API credentials, or unnecessary filesystem permissions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/token-accounts.md:101
Finding
Unchecked Parsing of Network-Supplied Account Data Can Terminate the Streaming Process<![CDATA[ ## Vulnerability Details **File Locations**: - `references/token-accounts.md:15` - `references/token-accounts.md:101-102` - `references/mint-accounts.md:83` - `references/pdas.md:141` - `references/shared.md:126` **Vulnerability Type**: Panic-prone parsing of untrusted network records **Risk Level**: Medium ### Vulnerable Code From `references/token-accounts.md:15`: ```rust let parsed: &PodAccount = pod_from_bytes(&data[..165])?; ``` From `references/token-accounts.md:101-102`: ```rust let pubkey: [u8; 32] = account.pubkey.as_slice().try_into().unwrap(); let parsed: &PodAccount = pod_from_bytes(&account.data[..165])?; ``` From `references/mint-accounts.md:83`: ```rust let pubkey: [u8; 32] = account_info.pubkey.as_slice().try_into().unwrap(); ``` From `references/pdas.md:141`: ```rust let pubkey: [u8; 32] = account.pubkey.as_slice().try_into().unwrap(); ``` From `references/shared.md:126`: ```rust let pubkey: [u8; 32] = account.pubkey.as_slice().try_into().unwrap(); ``` ### Technical Analysis The examples parse records received through a remote gRPC stream. They assume that account data is at least 165 bytes and that every public key is exactly 32 bytes. Rust range indexing such as `data[..165]` panics when the input contains fewer than 165 bytes. Similarly, converting a slice of an unexpected length to `[u8; 32]` returns an error, and calling `unwrap()` converts that recoverable error into a panic. Although subscription filters should normally constrain the received records, network-originated and deserialized data must still be treated as untrusted. Filters, provider behavior, protocol versions, malformed upstream records, or implementation defects can violate these assumptions. If the application uses the examples directly and is configured to abort or does not isolate stream-processing panics, a single malformed update can terminate the indexing pipeline. ### Attack Path 1. An attacker or compromised upstream component causes an a ...[truncated 1274 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate all network-supplied lengths and propagate recoverable errors instead of panicking. For account data: ```rust let base_data = account .data .get(..165) .ok_or_else(|| anyhow::anyhow!( "invalid token account length: expected at least 165 bytes, got {}", account.data.len() ))?; let parsed: &PodAccount = pod_from_bytes(base_data)?; ``` For public keys: ```rust let pubkey: [u8; 32] = account .pubkey .as_slice() .try_into() .map_err(|_| anyhow::anyhow!( "invalid public key length: expected 32 bytes, got {}", account.pubkey.len() ))?; ``` Additional hardening should include: 1. Log malformed records without including API credentials or other secrets. 2. Skip invalid updates while keeping the stream-processing loop alive. 3. Add metrics and alerts for malformed record counts. 4. Apply bounded retries and reconnect logic for failed streams. 5. Supervise spawned tasks so a panic in one handler cannot silently stop the pipeline. 6. Add tests for zero-length, undersized, oversized, and otherwise malformed account fields. 7. Avoid `unwrap()` and unchecked slicing for all externally supplied protobuf fields. ]]>
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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding
The skill recommends installing via `npx skills add Lightprotocol/skills` without pinning a specific version, commit, or release artifact. That creates a supply-chain risk because users may execute whatever package/version `npx` resolves at runtime, including a compromised or newly published variant, and the skill context explicitly encourages fetching code from a public repository.

Static analysis

No suspicious patterns detected.