Back to skill

Security audit

Helpscout

Security checks for vulnerabilities and agentic risk

Overview

This Help Scout skill uses the expected Help Scout API, but its documented permissions and implemented controls do not line up clearly for customer conversation access and replies.

Review this skill before installing. Use a Help Scout app with the narrowest possible permissions, assume the configured inbox list is not a hard security boundary, and do not rely on the documented sendReply examples until the code and documentation are reconciled. Update dependencies and add explicit allowlist checks before using it with real customer data.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/fetchConversations.js:4
Finding

Mailbox Filter Bypass Causes Account-Wide Conversation Retrieval

Content
View full analysis
fetchConversations(inboxId, options)) ); return results; } ``` `scripts/fetchConversations.js:4-31`: ```javascript async function fetchConversations({ inboxId = null, status = null, folderId = null, assignedTo = null, customerId = null, number = null, modifiedSince = null, sortField = null, sortOrder = null, tag = null, query = null, page = null}) { const token = await getToken(); const parameters = new URLSearchParams({ mailbox: inboxId, status: status, folderId: folderId, assignedTo: assignedTo, customerId: customerId, number: number, modifiedSince: modifiedSince, sortField: sortField, sortOrder: sortOrder, tag: tag, query: query, page: page }); // Filter out null parameters for (const [key, value] of parameters.entries()) { if (value === null) { parameters.delete(key); } } ``` ### Technical Analysis `fetchAllInboxes` calls `fetchConversations` with two positional arguments: ```javascript fetchConversations(inboxId, options) ``` However, `fetchConversations` accepts only one object argument and destructures its properties. The numeric or string inbox ID supplied as the firs ...[truncated 2412 chars]
Remediation
View remediation
fetchConversations({ ...options, inboxId }) ) ); } ``` 2. Reject requests that omit the mailbox identifier rather than silently issuing an unrestricted query: ```javascript async function fetchConversations(options = {}) { const { inboxId } = options; if (inboxId === null || inboxId === undefined || inboxId === '') { throw new Error('A valid inboxId is required'); } // Continue constructing the request. } ``` 3. Enforce the configured allowlist inside `fetchConversations`, not only in `fetchAllInboxes`. This prevents direct callers from requesting arbitrary mailboxes: ```javascript const { inboxIds } = getCredentials(); if (!inboxIds.map(String).includes(String(inboxId))) { throw new Error('The requested inbox is not configured for this Skill'); } ``` 4. Normalize and validate `INBOX_IDS` and `inboxId` types before comparison. Reject malformed, empty, or unexpected values. 5. Update every documented example to use the object-based API: ```javascript await fetchConversations({ inboxId: 321755, status: 'closed', sortField: 'modifiedAt', sortOrder: 'desc', page: 1 }); ``` 6. Add tests that inspect the outgoing request and verify: - The `mailbox` parameter is always present. - The mailbox value belongs to `INBOX_IDS`. - User-supplied filters are preserved. - Missing or unauthorized inbox IDs cause a local error. - `fetchAllInboxes()` does not issue an unrestricted request. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The supplied code does not implement any Help Scout conversation fetching or replying behavior. Instead, it only configures the test runner. This is a materially different purpose from the declared functionality, so the description is not accurately represented by this code chunk. No undeclared sensitive capability is present, but the actual code is unrelated to the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The implemented behavior matches the 'fetch' portion of the description: it retrieves Help Scout conversations from the v2 conversations endpoint using optional filters. However, the declared description also states 'reply to Helpscout conversations,' and this code chunk contains no functionality to post replies, modify conversations, or call any reply endpoint. This is a material description-to-behavior mismatch because part of the stated primary capability is absent from the supplied code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

There is a partial mismatch between the declared description and the actual code. The declared purpose is to fetch and reply to HelpScout conversations. In this code chunk, the exported behavior is createNote, which posts internal notes to conversations; that is a distinct capability from replying and is not mentioned in the description. The chunk also includes a sendReply implementation that can send customer-visible replies, but it is intentionally not exported, so the active exposed behavior here is note creation. The helper also fetches conversation data to derive a customer ID, which aligns with 'fetch' as a supporting detail. Overall, the main mismatch is that the code performs undeclared note creation and does not primarily expose reply functionality in this chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared purpose centers on interacting with Help Scout conversations, specifically fetching and replying to them. However, the supplied code only concerns authentication token retrieval for the Help Scout API. While token fetching could be a supporting detail for a conversation-handling skill, this code chunk itself does not implement or demonstrate conversation retrieval or replying behavior. That makes the observed behavior materially different from the declared purpose for this chunk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==1.1.12 — 4 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-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==3.1.2 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: browserslist==4.28.1 — 2 advisory(ies): CVE-2026-73088 (Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.); CVE-2026-73089 (Browserslist: Unbounded memory growth (no cache eviction) via distinct query res)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==3.14.2 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==2.3.1 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill documentation declares a network-capable integration with Help Scout and requires API credentials, but the manifest does not define any explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where a runtime may permit broader network access than reviewers or operators expect, increasing the chance of overprivileged execution.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
### 1. Retrieve Helpscout API Key & App Secret
1. Go to your Helpscout account.
2. Navigate to **Manage > Apps**.
3. Create or open your app to retrieve the following details:
   - **API Key**
   - **App Secret**

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code retrieves an access token and sends a remote API request to Help Scout, potentially transmitting user-provided search/filter values such as customerId, assignedTo, tag, and query. Although comments describe the function's purpose, there is no user-facing confirmation, warning, or disclosure about the outbound network access or data sent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetchConversations.js (reported line 40)May include surrounding context.

js
async function getToken() {
  const { apiKey, appSecret } = getCredentials();

  const response = await fetch('https://api.helpscout.net/v2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/getToken.js (reported line 8)May include surrounding context.

js
async function getToken() {
  const { apiKey, appSecret } = getCredentials();

  const response = await fetch('https://api.helpscout.net/v2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/sendReply.js (reported line 42)May include surrounding context.

js
async function getToken() {
  const { apiKey, appSecret } = getCredentials();

  const response = await fetch('https://api.helpscout.net/v2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · tests/token.test.js (reported line 36)May include surrounding context.

js
async function getToken() {
  const { apiKey, appSecret } = getCredentials();

  const response = await fetch('https://api.helpscout.net/v2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/getToken.js (reported line 8)May include surrounding context.

js
async function getToken() {
  const { apiKey, appSecret } = getCredentials();

  const response = await fetch('https://api.helpscout.net/v2/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file contains fully functional code to send customer-visible replies even though the documentation explicitly states the skill is not allowed to do so. Although the function is not currently exported, retaining live unauthorized reply logic creates a latent capability that could be exposed by a small future change, monkey-patching, or internal reuse, undermining intended security boundaries.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This outbound request transmits customer-visible reply content to HelpScout through a hidden-but-functional sendReply path that contradicts the stated restriction that the skill must not send replies. In this context, the danger is not the external transmission itself but that it enables an unauthorized action against end users if the dormant function becomes reachable.

Content

Scanner excerpt · scripts/sendReply.js (reported line 120)May include surrounding context.

js
payload.user = userId;
  }

  const response = await fetch(`https://api.helpscout.net/v2/conversations/${conversationId}/reply`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,

Known Vulnerable Dependency: @babel/core==7.29.0 — 1 advisory(ies): CVE-2026-49356 (@babel/core: Arbitrary File Read via sourceMappingURL Comment)

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: baseline-browser-mapping==2.9.19 — 1 advisory(ies): CVE-2026-45819 (baseline-browser-mapping process termination on invalid input causes denial of s)

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: fflate==0.8.2 — 1 advisory(ies): CVE-2026-45820 (fflate unzipSync can enter an infinite loop when parsing malformed ZIP64 archive)

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

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

json
"test": "jest"
  },
  "devDependencies": {
    "clawdhub": "^0.3.0",
    "jest": "^29.0.0",
    "nock": "^13.0.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

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

json
},
  "devDependencies": {
    "clawdhub": "^0.3.0",
    "jest": "^29.0.0",
    "nock": "^13.0.0"
  },
  "dependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

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

json
"devDependencies": {
    "clawdhub": "^0.3.0",
    "jest": "^29.0.0",
    "nock": "^13.0.0"
  },
  "dependencies": {
    "node-fetch": "^2.6.8",

Static analysis

No suspicious patterns detected.