Back to skill

Security audit

Skill Discovery Monitor

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent discovery-and-notification service, but it ships a live-looking payment API key and exposes subscription/payment operations without adequate access control.

Review carefully before installing or deploying. Rotate the exposed SkillPay key, replace it with an operator-provided secret, add authentication and signed payment callback verification, avoid exposing this server publicly until subscription endpoints are protected, and document how contact and payment data are stored and used.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
skill.json:15
Finding
Hard-Coded SkillPay API Credential Distributed with the Project<![CDATA[ ## Vulnerability Details **File Location**: `skill.json:15`; duplicate credential in `README.md:103-106` **Vulnerability Type**: Hard-coded secret exposure **Risk Level**: High ### Vulnerable Code `skill.json:15`: ```json "apiKey": "sk_e390b52cb259fc4f4aa1489547a48375d72876acdee75de57101d9e0e833fcb7", ``` `README.md:103-106`: ```env # SkillPay API Key (Required) SKILLPAY_API_KEY=sk_e390b52cb259fc4f4aa1489547a48375d72876acdee75de57101d9e0e833fcb7 ``` The credential is subsequently used as a bearer token in `src/payment.js:26-29`: ```javascript headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' } ``` ### Technical Analysis A SkillPay API key is committed directly to both machine-readable metadata and public-facing documentation. Anyone who downloads, clones, installs, or otherwise obtains the project receives the same credential. Unlike a placeholder, the value has the format of an actual secret and the documentation instructs users to assign it to `SKILLPAY_API_KEY`. The application then transmits that value as a bearer credential to the SkillPay API. Bearer credentials provide access to any party possessing the token, without proving the identity of the original owner. If the credential remains valid, source-code removal alone is insufficient because copies may persist in package archives, repository history, caches, logs, and forks. ### Attack Path 1. An attacker downloads the Skill package or reads its repository. 2. The attacker extracts the `sk_e390...fcb7` value from `skill.json` or `README.md`. 3. The attacker uses the key as a bearer credential when sending requests to supported SkillPay endpoints. 4. Requests are attributed to the credential owner rather than the attacker. 5. Depending on the provider-side permissions assigned to the key, the attacker may generate unauthorized usage, manipulate payment-related operations, consume quotas, or interfere with analytics. ### Impact Assessment I ...[truncated 612 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke the exposed SkillPay API key immediately and issue a replacement. 2. Investigate provider logs for unauthorized activity performed with the exposed key. 3. Remove the credential from `skill.json`, `README.md`, package archives, release artifacts, and repository history. 4. Replace documentation values with an unmistakable placeholder: ```env SKILLPAY_API_KEY=your_skillpay_api_key ``` 5. Inject the real secret only at deployment time through a secret manager or protected environment variable. 6. Give the replacement key only the minimum provider-side permissions required for payment verification and usage logging. 7. Use separate keys for development, testing, and production. 8. Add automated secret scanning to CI and pre-commit checks. 9. Fail startup securely when payment-dependent functionality is enabled without a valid runtime credential; do not ship a shared fallback key. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/index.js:203
Finding
Unsigned Payment Callback Allows Unpaid Subscription Activation<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:203-216` **Vulnerability Type**: Missing authentication and integrity verification on payment callback **Risk Level**: High ### Vulnerable Code ```javascript // Payment callback this.app.post('/payment/callback', async (req, res) => { try { const { userId, paymentId, status } = req.body; if (status === 'completed') { const subscription = this.subscriptions.get(userId); if (subscription && subscription.paymentId === paymentId) { subscription.status = 'active'; this.subscriptions.set(userId, subscription); } } res.json({ success: true }); } catch (error) { console.error('Payment callback error:', error); res.status(500).json({ error: error.message }); } }); ``` The payment identifier needed for the attack is returned by the subscription endpoint: ```javascript res.json({ success: true, message: 'Subscription created, please complete payment', payment: paymentRequest }); ``` ### Technical Analysis The callback trusts three attacker-controlled JSON properties: `userId`, `paymentId`, and `status`. It does not verify: - A payment-provider signature or HMAC. - A shared callback secret. - The source or authenticated identity of the sender. - The payment status through an independent server-to-server provider request. - The amount, currency, recipient account, or transaction uniqueness. - Whether the callback has already been processed. Possession of a matching `paymentId` is treated as sufficient proof of payment. However, `/subscribe` returns that identifier to the caller before payment is completed. The caller can therefore create a pending subscription and immediately forge its completion callback. ### Attack Path 1. The attacker sends a request to `POST /subscribe` with an attacker-selected `userId` and notification destination. 2. The application creates a pending subscription and returns its `paymentId`. 3. The attac ...[truncated 1074 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require and verify the payment provider's documented callback signature over the raw HTTP request body. 2. Store the callback signing secret in a protected runtime secret store. 3. Reject callbacks with missing, invalid, or expired signatures before parsing their status. 4. Independently query SkillPay using the server-side API after receiving a callback and verify: - Payment ID. - Final payment status. - Expected user or internal subscription ID. - Amount and currency. - Recipient account. 5. Use a server-generated, non-enumerable internal subscription identifier rather than trusting a caller-selected `userId`. 6. Make callback processing idempotent and record processed event IDs to prevent replay. 7. Permit only valid state transitions such as `pending` to `active`. 8. Return generic failure responses and log rejected callback attempts without logging secrets. 9. Add tests proving that unsigned, replayed, mismatched, underpaid, and fabricated callbacks cannot activate subscriptions. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/index.js:177
Finding
Subscription Records Can Be Read or Deleted Without Authentication<![CDATA[ ## Vulnerability Details **File Location**: `src/index.js:177-200` **Vulnerability Type**: Broken object-level authorization **Risk Level**: High ### Vulnerable Code ```javascript // Unsubscribe this.app.post('/unsubscribe', async (req, res) => { try { const { userId } = req.body; if (!userId) { return res.status(400).json({ error: 'Missing userId' }); } this.subscriptions.delete(userId); res.json({ success: true, message: 'Subscription cancelled' }); } catch (error) { console.error('Unsubscribe endpoint error:', error); res.status(500).json({ error: error.message }); } }); // Get subscription status this.app.get('/subscription/:userId', (req, res) => { const { userId } = req.params; const subscription = this.subscriptions.get(userId); if (!subscription) { return res.status(404).json({ error: 'Subscription not found' }); } res.json({ success: true, subscription }); }); ``` Subscription records contain channel destinations and payment information: ```javascript this.subscriptions.set(userId, { channels, preferences: { categories: preferences.categories || ['all'], platforms: preferences.platforms || ['clawhub', 'github', 'npm'], limit: preferences.limit || 5, schedule: preferences.schedule || process.env.SCHEDULE || '0 10 * * *' }, status: 'pending', paymentId: paymentRequest.paymentId, createdAt: new Date().toISOString() }); ``` ### Technical Analysis Both endpoints treat knowledge of a `userId` as authorization. There is no authenticated session, API token, ownership check, or separate cancellation secret. The status endpoint returns the complete subscription object rather than a minimal public status. Depending on the configured channels, this may disclose email addresses, Telegram chat IDs, preferences, status, creation timestamps, and payment IDs. The unsubscribe endpoint deletes the selected record regardless of who submitted the request. Its response als ...[truncated 1447 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for all subscription management endpoints. 2. Bind each subscription to the authenticated principal and enforce ownership on every read, update, and deletion. 3. Do not accept an arbitrary `userId` as proof of identity. 4. Use opaque, cryptographically random internal subscription IDs. 5. Return only the minimum required status fields; do not expose payment IDs or complete channel configuration. 6. For one-click unsubscribe links, use a dedicated, random, single-purpose cancellation token with expiration and rotation support. 7. Apply rate limiting and monitoring to subscription lookup and deletion endpoints. 8. Use consistent responses where appropriate to reduce identifier enumeration. 9. Add authorization tests covering cross-user reads and deletions. 10. Protect stored channel identifiers as personal data and define an appropriate retention policy. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/notifiers/email.js:98
Finding
External Registry Metadata Is Embedded into HTML, Markdown, and Mermaid Without Escaping<![CDATA[ ## Vulnerability Details **File Location**: `src/notifiers/email.js:98-108`; related sinks in `src/notifiers/telegram.js:57-75` and `src/utils/flowchart.js:27-76` **Vulnerability Type**: Output injection through untrusted external metadata **Risk Level**: Medium ### Vulnerable Code `src/notifiers/email.js:98-108`: ```javascript repos.slice(0, 10).forEach((repo, index) => { html += ` <div class="repo"> <div class="repo-title"> ${index + 1}. <a href="${repo.url}" target="_blank">${repo.fullName}</a> </div> <div class="repo-desc">${repo.description || 'No description provided.'}</div> <div class="repo-stats"> <div class="stat">⭐ <span class="stat-value">${repo.stars.toLocaleString()}</span> stars</div> <div class="stat">🍴 <span class="stat-value">${repo.forks.toLocaleString()}</span> forks</div> ${repo.todayStars > 0 ? `<div class="stat">📈 <span class="stat-value">+${repo.todayStars}</span> today</div>` : ''} ${repo.language ? `<div class="stat">💻 <span class="stat-value">${repo.language}</span></div>` : ''} </div> </div> `; }); ``` `src/notifiers/telegram.js:57-75`: ```javascript repos.slice(0, 10).forEach((repo, index) => { message += `*${index + 1}. ${repo.fullName}*\n`; message += ` ⭐ ${repo.stars.toLocaleString()} stars`; if (repo.todayStars > 0) { message += ` (+${repo.todayStars} today)`; } message += `\n`; message += ` 🍴 ${repo.forks.toLocaleString()} forks\n`; if (repo.language) { message += ` 💻 ${repo.language}\n`; } if (repo.description) { const desc = repo.description.length > 100 ? repo.description.substring(0, 100) + '...' : repo.description; message += ` 📝 ${desc}\n`; } message += ` 🔗 [View on GitHub](${repo.url})\n\n`; }); ``` `src/utils/flowchart.js:45-56`: ```javascript static generateDeveloperToolFlow(skill) { return `graph TD A[Start] --> B[Install ${skill.name}] B --> C[Initi ...[truncated 2819 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every field returned by Clawhub, GitHub, and npm as untrusted. 2. HTML-escape text nodes and attribute-escape URL values before constructing email HTML. 3. Validate all links with a URL parser and permit only expected schemes such as `https:`. 4. Escape Telegram Markdown using the rules for the selected parse mode, or send plain text when rich formatting is unnecessary. 5. Sanitize Mermaid labels by removing or escaping brackets, braces, pipes, quotes, line breaks, and syntax delimiters. 6. Configure downstream Mermaid rendering with the strictest available security mode and disable unsafe HTML. 7. Normalize scraper output into a single validated schema before passing records to notifiers. 8. Correct the `fullName`, `forks`, `todayStars`, and `language` schema mismatch so sanitization is consistently applied to values that are actually rendered. 9. Impose reasonable maximum lengths on names, descriptions, tags, and URLs. 10. Add tests using malicious payloads in every external field, including HTML tags, quoted attributes, Markdown links, Mermaid directives, and non-HTTPS URLs. 11. Consider using a well-maintained templating or encoding library rather than manually concatenating active-format strings. ]]>
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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (46)

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The README appears to expose a concrete SkillPay API key value in the example .env configuration rather than a clearly fake placeholder. Publishing what looks like a real secret can enable unauthorized use of the payment integration, billing abuse, account compromise, or downstream fraud if the credential is valid.

Known Vulnerable Dependency: undici==6.21.3 — 13 advisory(ies): CVE-2026-1525 (Undici has an HTTP Request/Response Smuggling issue); CVE-2026-6733 (undici vulnerable to HTTP response queue poisoning via keep-alive socket reuse); CVE-2026-1527 (Undici has CRLF Injection in undici via `upgrade` option) +10 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
The lockfile pins undici 6.21.3, and the supplied advisories include request/response smuggling, response queue poisoning, and CRLF injection issues. In a skill that appears to make outbound HTTP requests and interact with external services, a vulnerable HTTP client can enable SSRF-adjacent abuse, request confusion, or header injection if untrusted inputs ever influence requests.

Known Vulnerable Dependency: axios==1.13.6 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
axios 1.13.6 is reported with multiple high-severity advisories, including SSRF-related proxy bypass and prototype-pollution-linked attack chains. Because this skill-discovery monitor likely fetches remote content, a vulnerable HTTP library is especially relevant and could expose internal services, credentials, or response integrity if attacker-controlled URLs or proxy settings are involved.

Known Vulnerable Dependency: brace-expansion==5.0.4 — 5 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-45149 (brace-expansion: Large numeric range defeats documented `max` DoS protection) +2 more

High
Category
Supply Chain
Confidence
88% confidence
Finding
brace-expansion 5.0.4 is associated with multiple DoS issues involving pathological expansion inputs. It appears only as a development dependency path here, so exploitation is less likely in production, but it can still affect development tooling or CI if untrusted patterns are processed.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
90% confidence
Finding
form-data 4.0.5 is flagged for CRLF injection via multipart field names and filenames. If the application constructs multipart requests from untrusted values, an attacker may be able to manipulate downstream HTTP message structure or inject unintended headers/content.

Known Vulnerable Dependency: lodash==4.17.23 — 2 advisory(ies): CVE-2025-13465 (lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and ); CVE-2021-23337 (lodash vulnerable to Code Injection via `_.template` imports key names)

High
Category
Supply Chain
Confidence
87% confidence
Finding
lodash 4.17.23 is associated with prototype pollution and template-related code injection advisories. The actual exploitability depends on whether vulnerable lodash APIs such as _.unset or _.template are used with attacker-controlled data, which cannot be confirmed from the lockfile alone, but the dependency is genuinely vulnerable.

Known Vulnerable Dependency: lodash-es==4.17.23 — 2 advisory(ies): CVE-2025-13465 (lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and ); CVE-2021-23337 (lodash vulnerable to Code Injection via `_.template` imports key names)

High
Category
Supply Chain
Confidence
87% confidence
Finding
lodash-es 4.17.23 carries the same pollution and template-related risks as lodash. As a transitive library used by mermaid-related packages, the impact depends on reachable code paths, but the presence of a known-vulnerable version is still a valid dependency risk.

Known Vulnerable Dependency: nodemailer==6.10.1 — 12 advisory(ies): CVE-2026-82661 (Nodemailer: CRLF injection in Nodemailer List-* header comments allows arbitrary); GHSA-2x7j-588g-ccc2; GHSA-8m3c-c648-2xjj +9 more

High
Category
Supply Chain
Confidence
94% confidence
Finding
nodemailer 6.10.1 is flagged for multiple high-severity issues including CRLF/header injection. In a monitoring skill that may send alert emails, this is operationally relevant because attacker-influenced email fields could permit header injection, spoofing, or message manipulation.

Known Vulnerable Dependency: path-to-regexp==0.1.12 — 1 advisory(ies): GHSA-37ch-88jc-xwx2

High
Category
Supply Chain
Confidence
91% confidence
Finding
path-to-regexp 0.1.12 is a genuinely outdated vulnerable dependency in the express routing stack. If exposed routes rely on attacker-controlled paths, vulnerable path parsing can contribute to denial of service or route-matching issues, making it relevant for any internet-facing express service.

Known Vulnerable Dependency: picomatch==2.3.1 — 2 advisory(ies): GHSA-3v7f-55p6-f55p; GHSA-c2c7-rcm5-vvqj

High
Category
Supply Chain
Confidence
82% confidence
Finding
picomatch 2.3.1 is reported with high-severity advisories and is present via development tooling. Because it is likely only used by nodemon/chokidar in development, this is less dangerous for deployed runtime but can still affect developer machines or CI if fed malicious glob patterns.

Known Vulnerable Dependency: qs==6.14.2 — 3 advisory(ies): GHSA-4mjr-xmp4-gh2g; GHSA-q8mj-m7cp-5q26; GHSA-x5fp-wj9c-mxmx

High
Category
Supply Chain
Confidence
92% confidence
Finding
qs 6.14.2 is flagged with multiple high-severity advisories and is used by express/body-parser for query/body parsing. In a service exposing HTTP endpoints, parser bugs can enable prototype pollution, denial of service, or unexpected object-shape manipulation from crafted requests.

Known Vulnerable Dependency: undici==7.22.0 — 16 advisory(ies): GHSA-2mjp-6q6p-2qxm; GHSA-35p6-xmwp-9g52; GHSA-4992-7rv2-5pvq +13 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
undici 7.22.0 is also present and reported with numerous advisories. Since this package underpins network operations for cheerio and possibly other consumers, multiple vulnerable HTTP client versions in one project expand the attack surface for malicious remote content, redirect abuse, smuggling, or header manipulation.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The manifest contains a hard-coded API key directly in skill.json, which exposes a secret to anyone who can access the package or repository. This is especially suspicious because the skill is described as a discovery/monitoring tool, and embedding a live credential in static metadata is unnecessary and enables credential theft, unauthorized API usage, billing abuse, or pivoting into connected services.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Get top AI skills
curl "http://localhost:3000/discover?category=ai&limit=5"

# Get all trending skills
curl "http://localhost:3000/discover?limit=20"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The markdown shows a subscription API that sends a user ID, Telegram chat ID, and preference data, but it does not include any warning about privacy, data handling, or notification side effects. For markdown files, user-facing descriptions should warn when behavior could affect user data or privacy.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill exposes notification and subscription flows that collect contact identifiers such as Telegram chat IDs and email addresses, but the documentation provides no privacy notice, retention policy, consent language, or description of how that data is stored and used. This creates privacy and compliance risk because operators may collect personally identifiable information and trigger outbound messaging without clear user disclosure or safeguards.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The configuration section lists sensitive secrets including API keys, bot tokens, webhook URLs, and SMTP credentials without any warning about secure storage, rotation, least-privilege use, or avoiding disclosure in source control and logs. In practice, this omission can lead to secret leakage, unauthorized messaging, account compromise, or abuse of integrated services if users handle the credentials insecurely.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Line L013 states "Full English documentation," and later L089 reinforces "All code in English - Comments, docs, everything!" This is a natural-language locale policy constraint presented as a requirement or project property, with no opt-in or justification for restricting language usage.

External Transmission

Medium
Category
Data Exfiltration
Content
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  # Discover AI skills
  curl "http://localhost:3000/discover?category=ai&limit=5"

  # Get Clawhub skills only
  curl "http://localhost:3000/platform/clawhub"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Vague Triggers

Medium
Confidence
83% confidence
Finding
The manifest describes broad discovery, monitoring, and notification capabilities across multiple platforms without clear activation boundaries, scope limitations, or exclusions. Overly generic scope increases the chance the skill is invoked in unintended contexts, potentially leading to excessive data collection, spammy outbound notifications, or actions that users did not explicitly authorize.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The /notify route takes user-supplied channel details and then transmits discovered skill data to Telegram, Discord, and email. While the code performs the action intentionally, this file does not provide a confirmation prompt or explicit user-facing disclosure at the point where external notifications are sent, which is relevant for network transmissions affecting user data and privacy.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
The subscription endpoint persists user channel configuration and preferences, and the scheduled task later uses those settings to send reports to external services. Although the behavior appears functional, this file lacks an explicit warning or disclosure that user-provided contact endpoints and report contents will be stored and used for recurring outbound notifications.

External Transmission

Medium
Category
Data Exfiltration
Content
class SkillPayment {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseURL = 'https://api.skillpay.me/v1';
    this.pricePerCall = 0.001; // USDT
  }
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The code transmits userId, transactionId, payment amount, and currency to an external payment service without any visible consent flow, notice, or data-minimization controls in this module. In a skill context, silent transmission of user-linked payment data to a third party can create privacy and compliance risks, especially if users are unaware their identifiers are being shared externally.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This payment creation flow sends userId and payment metadata to an external processor with no visible user-facing notice or consent mechanism in the code. Because this initiates third-party billing-related processing, the lack of transparency is more dangerous in a skill environment where users may not expect their identifiers to be shared off-platform.

Static analysis

No suspicious patterns detected.