Back to skill

Security audit

market-beats

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed remote wrapper for a finance-news service, but it handles API secrets and remote output in ways users should review carefully before installing.

Install only if you trust the Prana service and understand that your messages, thread IDs, request IDs, and API key are sent to the configured endpoint. Avoid using a custom base URL unless you control it and it is HTTPS; prefer environment-provided credentials, set PRANA_SKILL_SKIP_WRITE_API_KEY=1 to avoid writing secrets to disk, and keep config/api_key.txt out of source control. Treat remote responses as untrusted service output rather than local verified news data.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
skill.yaml:14
Finding

Untrusted Remote Responses Are Mandated for Direct Pass-Through

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/prana_skill_client.py:415
Finding

API Credentials and User Messages Can Be Sent to an Arbitrary Base URL

Content
View full analysis
dict[str, str]: return { "Content-Type": "application/json", "x-api-key": f"{public_key}:{secret_key}", } ``` ```python url = base_url.rstrip("/") + "/api/claw/agent-run" body = { "skill_key": skill_key, "question": content, "thread_id": thread_id or "", "request_id": request_id, } data = json.dumps(body, ensure_ascii=False).encode("utf-8") req = urllib.request.Request( url, data=data, method="POST", headers=_headers_x_api_key(public_key, secret_key), ) ``` ```python parser.add_argument( "--base-url", "-b", default=DEFAULT_PRANA_BASE, help="Prana API root URL", ) ``` The Node.js runner implements the same flow: ```javascript function headersXApiKey(publicKey, secretKey) { return { 'Content-Type': 'application/json', 'x-api-key': `${publicKey}:${secretKey}`, }; } ``` ```javascript const url = `${baseUrl.replace(/\/+$/, '')}/api/claw/agent-run`; const opts = { method: 'POST', headers: headersXApiKey(publicKey, secretKey), body: JSON.stringify(body), signal: AbortSignal.timeout(HTTP_TIMEOUT_MS), }; ``` ### Technical Analysis The caller can set `--base-url` without any hostname allowlist, HTTPS requirement, port restriction, or explicit approval when the origin changes. The selected base URL is then used for authenticated requests carrying: - The complete `public_key:secret_key` credential in `x-api-key` - The user's message in the `question` field - The thread identifier - The request identifier - The internal remote skill identifier Consequently, an unsafe wrapp ...[truncated 1476 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/prana_skill_client.py:228
Finding

Fetched Secret Keys Are Persisted in Plaintext with Default Filesystem Permissions

Content
View full analysis
None: CONFIG_DIR.mkdir(parents=True, exist_ok=True) lines = [ "# Auto-saved by prana_skill_client after GET /api/v1/api-keys; do not commit to public repos.", f"{public_key}:{secret_key}", "", ] API_KEY_FILE.write_text("\n".join(lines), encoding="utf-8") ``` ```python if fetched: pub, sec = fetched if not _skip_write_fetched_api_key(): try: _persist_fetched_api_key_txt(pub, sec) except OSError as e: print(f"Warning: unable to write config/api_key.txt: {e}", file=sys.stderr) return pub, sec ``` Equivalent Node.js code: ```javascript function persistFetchedApiKeyTxt(publicKey, secretKey) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); const lines = [ '# Auto-saved by prana_skill_client after GET /api/v1/api-keys; do not commit to public repos.', `${publicKey}:${secretKey}`, '', ]; fs.writeFileSync(API_KEY_FILE, lines.join('\n'), 'utf8'); } ``` ### Technical Analysis When no credential is configured, the runners automatically fetch a public and secret key. Persistence is enabled by default unless the user sets `PRANA_SKILL_SKIP_WRITE_API_KEY`. The secret is written directly into the project directory without an explicit restrictive mode, atomic creation, ownership verification, or symbolic-link protection. Effective permissions depend on the process umask and existing file state. The file may therefore be readable by other local users or processes. Project directories are also commonly copied, archived, indexed, synchronized, or committed to source control. The warning comment does ...[truncated 1098 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
package.json:1
Finding

Dependency Installation Is Not Reproducibly Locked

Content
View full analysis
=18.0.0" } } ``` The package contains no audited lockfile, while the documentation directs users to run: ```bash npm install ``` ### Technical Analysis The caret range permits npm to resolve later compatible versions of `yaml`, and no lockfile fixes the complete dependency graph and integrity hashes. Therefore, installing the same reviewed Skill at different times may produce different code. There is no evidence that the declared `yaml` package is malicious. The confirmed issue is the non-reproducible and insufficiently constrained installation process, which increases exposure to a future compromised release, registry compromise, or unexpected transitive dependency change. Running `npm install` may also execute lifecycle scripts from resolved packages unless separately disabled. This expands the effective code executed beyond the files included in the audited Skill package. ### Attack Path 1. A user follows the Skill documentation and runs `npm install`. 2. npm resolves the latest package version allowed by `^2.6.1` rather than a version fixed by the audited artifact. 3. A future compromised or unexpectedly changed allowed version is downloaded. 4. Package installation logic or imported dependency code executes in the user's environment. 5. The dependency runs with the permissions of the user invoking the Skill. ### Impact Assessment A compromised dependency can potentially read files accessible to the invoking user, access environment vari ...[truncated 238 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to provide a finance-news crawler/streaming UI, but the documented flow is actually a CLI thin client that forwards prompts to a remote Prana/Claw service, reads local config, handles API keys, and polls job status. That discrepancy can conceal the true trust boundary and cause operators to expose credentials or sensitive prompts to an unexpected third-party execution service.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to provide a finance-news crawler/streaming UI, but the documented flow is actually a CLI thin client that forwards prompts to a remote Prana/Claw service, reads local config, handles API keys, and polls job status. That discrepancy can conceal the true trust boundary and cause operators to expose credentials or sensitive prompts to an unexpected third-party execution service.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 8)May include surrounding context.

md
- **Node.js 18+**:先在包根目录执行 **`npm install`**,再执行 `node scripts/prana_skill_client.js -m "…" [-t thread_id] [-b base_url]`

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file is not a local finance-news crawler/viewer at all; it is a thin wrapper that forwards arbitrary user input and embedded skill identifiers to a remote backend for execution. This creates a strong capability/description mismatch, preventing users and reviewers from understanding what code actually runs and expanding the trust boundary to an external service that may perform unintended actions with supplied credentials and prompts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly documents that API credentials may be automatically fetched and written to config/api_key.txt, but the warning about credential sensitivity appears later and is easy to miss relative to the behavior description. This creates a real risk of accidental secret persistence on disk, exposure via backups or shared workspaces, and later leakage through source control or local compromise.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding

The skill exposes or implies code capabilities including environment access, file operations, and network access, but declares no explicit tool scope or permission boundaries. In a skill that is presented as a simple financial news feed, this lack of least-privilege disclosure makes it harder for integrators to assess what the client may access and increases the risk of unintended credential, file, or network use.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation presents the skill as a real-time financial news product, but the integration instructions require direct use of generic /api/claw/agent-run and /api/claw/agent-result proxy endpoints. In context, that makes the skill more dangerous because it is not a verifiable news-fetching implementation but a wrapper around remote agent execution, which changes the data exposure and execution-risk profile.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The markdown instructs users to send sensitive credentials in the x-api-key header as public_key:secret_key to an external API but gives no warning about handling, storage, rotation, or exposure risks. In a skill already misaligned with its claimed function, this increases the chance that users disclose reusable secrets to a third-party service without informed consent.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file documents storing and automatically retrieving Prana Claw API credentials in a skill whose declared purpose is real-time financial news crawling and display. This mismatch is a strong indicator of hidden or unnecessary credential-handling behavior, and auto-fetching/writing secrets to disk expands the attack surface by persisting sensitive tokens where they may be exfiltrated or accidentally committed.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The comments explicitly describe a client that requests API keys and writes them back to disk by default. Automatically materializing credentials into a local file is dangerous because it can leave secrets in plaintext, increase the chance of accidental source control inclusion, and create an opaque secret-handling path unrelated to the advertised news-monitoring use case.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code path fetches API credentials from a remote endpoint and includes a helper to persist them locally, which is functionality unrelated to a market-news display skill and materially expands the trust boundary. A client that can autonomously acquire and store secrets creates unnecessary credential exposure risk, especially if the endpoint is reachable without prior authentication or if the local filesystem is shared, backed up, or later committed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Fetched credentials are written to config/api_key.txt automatically, without an interactive warning or opt-in in the normal execution path. Persisting secrets to disk increases the chance of accidental disclosure through source control, backups, permissive file permissions, local compromise, or other users on the same machine.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The client automatically attempts to retrieve API keys from /api/v1/api-keys and then caches them, effectively turning the skill into a secret bootstrapper. For a finance-news skill, this is especially suspicious because the feature is not needed for core functionality and could be abused to obtain reusable credentials for broader platform access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The client sends the composed content, including the user's message and skill invocation parameters, to the remote /api/claw/agent-run endpoint. While network use is part of a client wrapper's purpose, this code path lacks a visible user-facing notice, log, or prompt indicating that user-provided content will be transmitted to an external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module docstring is written as user-facing skill description text entirely in Chinese and describes how the skill should be used, without indicating any language choice or opt-in. Under the policy, forcing a specific language or locale without user choice is a natural-language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The client can automatically fetch API credentials from a remote endpoint and then persist them to config/api_key.txt on disk. For a news-monitoring skill this is unnecessary and risky because it silently expands privilege acquisition, stores secrets locally, and could expose reusable credentials through filesystem access, packaging mistakes, or accidental commits.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This manifest describes a general-purpose real-time financial news crawling and display capability, but provides no specific activation phrases, scope limits, or negative examples indicating when the skill should or should not be invoked. In manifest files, this lack of trigger specificity can lead to unintended invocation from loosely related finance-news requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest uses locale-specific policy fields and instructions in Chinese for runtime behavior and post-payment handling, without any indication that users may choose another language or locale. Per the policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest explicitly instructs the system to pass upstream API responses directly to the end user without rewriting or summarization. In a network-enabled skill that proxies external endpoints, this can expose sensitive, unsafe, or attacker-controlled content verbatim, including tokens, internal errors, untrusted markup, or prompt-injection-style instructions returned by upstream services.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest embeds paid-skill order verification against an external commerce API that is not necessary for a real-time financial news crawler/display skill. This expands the trust boundary, introduces credential-handling requirements, and creates a risk of unnecessary outbound data flows or misuse of user/API secrets if the commerce integration is triggered or abused.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

L14-L18 引入了一个访问 https://claw-uat.ebonex.io/api/order/skills 的购买记录查询流程,并要求使用 API 凭证鉴权。对于一个以实时财经新闻抓取与展示为目的的技能,这属于额外的账户/订单管理能力,不是其核心功能的直接实现。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file's user-facing guidance is entirely written in Chinese, which imposes a specific language on users without any opt-in or alternative locale. The policy explicitly calls for flagging language or locale constraints when the skill does not offer a user choice or document a justified regional limitation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a caret range (^2.6.1), which allows installation of newer 2.x releases that are not cryptographically or operationally fixed by this manifest. That weakens build reproducibility and can unexpectedly pull in a vulnerable or breaking release through the supply chain, even though the package itself is not obviously malicious.

Content

Scanner excerpt · package.json (reported line 7)May include surrounding context.

json
"type": "module",
  "description": "Prana encapsulated skill — install deps for the Node runner: npm install",
  "dependencies": {
    "yaml": "^2.6.1"
  },
  "engines": {
    "node": ">=18.0.0"

Unverifiable Dependency: yaml has 2 known advisory(ies) (CVE-2026-33532 (yaml is vulnerable to Stack Overflow via deeply nested YAML collections); CVE-2023-2251 (Uncaught Exception in yaml)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

The manifest references yaml without pinning an exact vetted version, while known advisories exist for some yaml releases, including denial-of-service style crashes from malformed or deeply nested YAML input. Because the installed version cannot be verified from this file alone, there is residual risk that an affected release could be resolved at install time.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/prana_skill_client.js:26

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/prana_skill_client.py:502