Back to skill

Security audit

Snapbyte Digest API

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated Snapbyte digest purpose, but its helper script can send the user's API key to an undocumented, arbitrary base URL if an environment variable is set.

Review this skill before installing. Only use it if you trust Snapbyte with the digest requests and API key, avoid setting SNAPBYTE_BASE_URL unless you fully control the endpoint, and prefer pinned/provenance-checked CLI installation where possible. Treat the optional cron example as persistent automation that will keep using the configured key on a schedule.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/snapbyte_digest.py:12
Finding
Bearer API Credential Can Be Redirected to an Arbitrary Host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/snapbyte_digest.py:12-31` **Vulnerability Type**: Unvalidated credential destination **Risk Level**: High ### Vulnerable Code ```python BASE_URL = os.environ.get("SNAPBYTE_BASE_URL", "https://api.snapbyte.dev") def build_url(path: str, query: dict[str, Any] | None = None) -> str: base = BASE_URL.rstrip("/") if not query: return f"{base}{path}" filtered = {k: v for k, v in query.items() if v is not None} return f"{base}{path}?{urllib.parse.urlencode(filtered)}" def api_request(path: str, query: dict[str, Any] | None = None) -> Any: api_key = os.environ.get("SNAPBYTE_API_KEY") if not api_key: print("Missing SNAPBYTE_API_KEY", file=sys.stderr) sys.exit(2) request = urllib.request.Request(build_url(path, query), method="GET") request.add_header("Authorization", f"Bearer {api_key}") request.add_header("Accept", "application/json") try: with urllib.request.urlopen(request, timeout=20) as response: ``` ### Technical Analysis The Skill documentation declares `https://api.snapbyte.dev` as the API origin, but the implementation permits the origin to be replaced through the `SNAPBYTE_BASE_URL` environment variable. The code does not validate the resulting URL's scheme, hostname, port, or embedded user information before attaching the bearer credential. Consequently, any process, configuration layer, launcher, or attacker that can influence this environment variable can cause the helper to send `SNAPBYTE_API_KEY` to an unintended server. The override also accepts plaintext HTTP, which can expose the credential through network interception. Sending the bearer token to the genuine Snapbyte endpoint is necessary for the declared functionality. Allowing that token to be sent to arbitrary origins exceeds the minimum privileges required. ### Attack Path 1. An attacker gains the ability to influence the Skill process environment or i ...[truncated 1228 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `SNAPBYTE_BASE_URL` override if alternate origins are not required. 2. If an override is operationally necessary, parse the destination with `urllib.parse.urlsplit()` and enforce all of the following before constructing a request: - The scheme must be exactly `https`. - The normalized hostname must be exactly `api.snapbyte.dev`. - User information must not be present. - The port must be absent or explicitly approved. 3. Refuse to attach `SNAPBYTE_API_KEY` when the destination does not match the trusted origin. 4. If development endpoints are needed, require a separate explicit development mode and a separate non-production credential. 5. Avoid following redirects that cross origins while carrying the authorization header, or explicitly verify the final destination. 6. Add tests proving that HTTP URLs, deceptive subdomains, userinfo URLs, unexpected ports, and non-Snapbyte hosts are rejected. 7. Document any supported endpoint override and its security constraints in `SKILL.md`. ]]>

T08 · Insecure Dependencies

Warning
Location
references/quickstart.md:5
Finding
Quickstart Installs an Unpinned Global npm Package<![CDATA[ ## Vulnerability Details **File Location**: `references/quickstart.md:5-7` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash npm i -g clawhub ``` ### Technical Analysis The quickstart directs users to install the latest version of the `clawhub` npm package globally. No exact version, package integrity value, or reviewed release is specified. As a result, the installed code can change after this Skill has been audited. npm installation can execute package lifecycle scripts. A compromised maintainer account, registry entry, or future malicious release could therefore execute code during installation. The global installation option increases the affected scope by modifying shared tooling rather than using a project-local dependency. The package is relevant to installing the Skill, but fetching an unrestricted future version globally is not the least-risk method of satisfying that requirement. ### Attack Path 1. The upstream npm package, maintainer account, publication token, or release process is compromised. 2. A malicious version is published under the expected package name or selected by the package's default distribution tag. 3. A user follows the quickstart and runs `npm i -g clawhub`. 4. npm resolves the unpinned current version and downloads it. 5. Any included lifecycle scripts run with the privileges of the invoking user. 6. The malicious package can access data and modify files available to that user, subject to operating-system permissions. ### Impact Assessment A compromised dependency could execute arbitrary code with the privileges of the user running npm. Potential effects include reading user-accessible credentials, changing global Node.js tooling, modifying files, or establishing additional persistence. The exact impact depends on the user's permissions and npm configuration. This finding does not establish that the current `clawhub` package is malicious; th ...[truncated 124 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the command to an exact, reviewed package version rather than relying on the latest distribution tag. 2. Document the expected npm registry and verified publisher. 3. Provide an integrity hash, signed-release verification procedure, or other provenance check where supported. 4. Prefer a project-local or otherwise scoped installation over a global installation when practical. 5. Review package lifecycle scripts before recommending installation. 6. Update the pinned version only after reviewing and testing the new release. 7. Consider documenting a method that prevents lifecycle scripts during initial verification, where compatible with the package's installation requirements. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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 (4)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
python3 scripts/snapbyte_digest.py items --digest-id dst_abc123 --page 1 --limit 10
```

## Output rules

- Prefer formatted markdown output from script by default.
- If user asks for raw payload, pass `--raw`.
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill requires environment access to `SNAPBYTE_API_KEY` and performs network operations against an external API, but it does not declare an explicit tool scope such as `permissions` or `allowed-tools`. That omission weakens least-privilege controls and makes it easier for an agent runtime to grant broader-than-necessary capabilities when handling secrets and outbound requests.

External Transmission

Medium
Category
Data Exfiltration
Content
---
name: snapbyte-digest-api
description: Fetch personalized developer news digests from Snapbyte External API with API-key auth. Use for Hacker News digest, Reddit digest, Lobsters digest, and DEV.to digest workflows.
homepage: https://api.snapbyte.dev/docs
metadata: {"openclaw":{"emoji":"📰","requires":{"bins":["python3","curl"],"env":["SNAPBYTE_API_KEY"]},"primaryEnv":"SNAPBYTE_API_KEY"}}
---
Confidence
76% confidence
Finding
This skill is explicitly designed to send user-scoped digest requests and an API bearer token to an external service at `api.snapbyte.dev`, which constitutes intentional data transmission outside the local environment. In context this is expected behavior, but it still creates a real trust boundary: user data, request parameters, and authentication material are exposed to a third-party API and should be treated as sensitive.

Intent-Code Divergence

Low
Confidence
95% confidence
Finding
The text says to set the Snapbyte API key using `SNAPBYTE_API_KEY`, which implies an environment/config variable of that exact name, but the immediately following JSON example instead uses an `apiKey` field under the skill entry. This is an active documentation contradiction about the intended configuration method, which can mislead users about how the skill is actually meant to be configured.

Static analysis

No suspicious patterns detected.