Back to skill

Security audit

Mcp Server

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real ChatbotX MCP integration, but its remote server defaults and token handling could expose or misuse a workspace token.

Review carefully before installing, especially for remote SSE use. Prefer stdio/local-only operation, bind any server to localhost, avoid placing workspace tokens in URLs, use least-privilege and short-lived tokens if available, and do not expose the MCP port publicly until authentication, session binding, origin validation, and resource limits are addressed.

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 (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/server/sse-server.ts:61
Finding

Unauthenticated remote clients inherit the server workspace token

Content
View full analysis
string) => { const token = getApiTokenFromRequest(req) || env.CHATBOTX_API_KEY return () => token } ``` ```ts // src/server/sse-server.ts:241-261 export const runSseServer = async ( createMcpServer: (options?: CreateMcpServerOptions) => McpServer, ): Promise => { const httpServer = createServer(async (req, res) => { enableCors(res) const url = new URL(req.url ?? "", "http://localhost") if (url.pathname === env.CHATBOTX_MCP_SSE_PATH) { await handleSseRequest(req, res, createMcpServer) return } if (url.pathname === env.CHATBOTX_MCP_MESSAGES_PATH) { await handleMessagesRequest(req, res, createMcpServer) return } if (url.pathname === "/") { writePlainText(res, 200, "MCP SSE server is running") return } writePlainText(res, 404, "Not Found") }) await new Promise((resolve) => { httpServer.listen(env.CHATBOTX_MCP_PORT, env.CHATBOTX_MCP_HOST, resolve) }) ``` ### Technical Analysis The default transport is `both`, so starting the application also starts its network-accessible SSE server. The default host is `0.0.0.0`, exposing that server on every available network interface. The appl ...[truncated 1750 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/openapi-loader.ts:123
Finding

Remote OpenAPI metadata can redirect the workspace bearer token to an attacker-controlled origin

Content
View full analysis
{ if (cachedTools !== null) { return cachedTools } const specUrl = `${env.CHATBOTX_API_URL}/public-spec.json` const response = await fetch(specUrl, { headers: { Accept: "application/json" }, }) if (!response.ok) { throw new Error( `Failed to fetch OpenAPI spec from ${specUrl}: ${response.status} ${response.statusText}`, ) } const spec = (await response.json()) as OpenAPISpec const baseUrl = spec.servers?.[0]?.url ?? env.CHATBOTX_API_URL const tools: DynamicTool[] = [] ``` ```ts // src/openapi-loader.ts:158-168 tools.push({ name: toSnakeCase(operation.operationId), description: operation.summary ?? operation.description ?? operation.operationId, inputSchema: schema, baseUrl, pathTemplate, method: httpMethod.toUpperCase(), pathParamNames, bodyParamNames, queryParamNames, }) ``` ```ts // src/server/create-mcp-server.ts:69-80 const url = `${tool.baseUrl}${path}${buildQueryString(queryArgs)}` const sendBody = !NO_BODY_METHODS.has(tool.method) && tool.bodyParamNames.length > 0 try { const response = await fetch(url, { method: tool.method, headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: sendBody ? JSON.stringify(body) : undefined, }) ``` ### Technical Analysis The remotely fetched OpenAPI document controls `spec.servers[0].url`. That value is copied into every dynamic tool as `baseUrl`. When a tool is invoked, the application unconditionally adds the workspace API key as an `Authorization: Bearer` header to the resulting URL. There is no vali ...[truncated 1825 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/server/sse-server.ts:42
Finding

Workspace bearer tokens are accepted and recommended in URL query strings

Content
View full analysis
{ const url = new URL(req.url ?? "", "http://localhost") const urlToken = ( url.searchParams.get("workspace_token") ?? url.searchParams.get("token") )?.trim() if (urlToken) { return urlToken } ``` ```md ChatGPT.com connects via SSE. The server must be publicly reachable. Because ChatGPT does not support custom request headers, pass the workspace token directly in the URL: 1. Start the server with `CHATBOTX_MCP_TRANSPORT=sse` (or `both`). 2. In ChatGPT Settings → Connectors → Add custom connector, set the URL: ``` https://your-mcp-server.com/sse?workspace_token= ``` When using this URL in a shell command, always quote it to prevent `?` being interpreted as a glob: ```bash claude mcp add chatbotx -t sse -s user "https://your-mcp-server.com/sse?workspace_token=" ``` ``` ```md ## Token resolution order | Transport | Priority | |-----------|----------| | SSE / Streamable HTTP | `?workspace_token=` or `?token=` query param → `x-workspace-token` / `x-chatbo-token` header → `CHATBOTX_API_KEY` env | | stdio | `CHATBOTX_API_KEY` env | ``` ### Technical Analysis The server treats `workspace_token` and `token` query parameters as workspace bearer credentials. The documentation explicitly recommends this approach for a publicly reachable server. URLs are routinely retained outside the application's security boundary. Full request targets can appear in reverse-proxy and web-server access logs, load-balancer logs, observability systems, connector configuration, shell history, browser history, support capt ...[truncated 1212 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/server/sse-server.ts:136
Finding

MCP sessions are authorized solely through possession of a session identifier

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/server/sse-server.ts:72
Finding

Unbounded request buffering and session allocation enable remote denial of service

Content
View full analysis
() const legacySseSessions = new Map() ``` ```ts // src/server/sse-server.ts:72-89 const parseRequestBody = async (req: IncomingMessage): Promise => { const chunks: Buffer[] = [] for await (const chunk of req) { chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk) } if (chunks.length === 0) { return } const rawBody = Buffer.concat(chunks).toString("utf8").trim() if (rawBody.length === 0) { return } return JSON.parse(rawBody) as unknown } ``` ```ts // src/server/sse-server.ts:187-207 if (!isInitializeRequest(parsedBody)) { writePlainText( res, 400, "Missing sessionId. First request must be initialize.", ) return } const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: (initializedSessionId) => { sseSessions.set(initializedSessionId, { server, transport }) }, }) const server = createMcpServer({ getApiKey: makeGetApiKey(req) }) transport.onclose = () => { const activeSessionId = transport.sessionId if (activeSessionId) { sseSessions.delete(activeSessionId) } } ``` ### Technical Analysis `parseRequestBody` collects every incoming chunk and only concatenates and parses the data after the client finishes sending it. No maximum body length, read deadline, or content-length validation is enforced. The global session maps also have no maximum size, per-client quota, creation rate limit, or periodic idle-session cleanup. Session creation is possible without prior authentication under the audited behavior. These weaknesses can be combined: an a ...[truncated 1283 chars]
Remediation
View remediation
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (48)

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · README.md (reported line 95)May include surrounding context.

md
| `unblock_contact` | Unblock a contact |
| `list_contact_messages` | List messages for contact |
| `get_contact_message` | Get a message by ID for a contact |
| `send_message` | Send message to contact |
| `send_contact_flow` | Send flow to contact |
| `trigger_auto_reply` | Trigger auto reply for contact |

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The connector setup tells users to embed the workspace token directly in the public connector URL. That is plaintext secret handling in a location broadly visible to client software, browsers, telemetry, and infrastructure, making credential theft substantially easier.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 270)May include surrounding context.

Copy .env.example to .env and fill in the values:

bash
cp .env.example .env

| Variable | Description | Default | Required |

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a full-featured multi-channel chat marketing platform. The supplied code chunk does not implement or support that functionality; it is only a trivial unit/smoke test confirming the Vitest runner works. This is a materially different primary purpose from the declared description, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a multi-channel chat marketing platform with contact, conversation, flow, broadcast, and sequence management. The supplied code chunk does not show any of that business functionality; it only launches a Node.js process for an mcp-server application with host/port environment variables. While an entrypoint script can be a supporting implementation detail, the specific target being an MCP server is not clearly represented by the declared purpose. Based on this code alone, the behavior is materially different from the described platform functionality, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding

The declared description presents a full chat marketing platform with contact, conversation, flow, broadcast, and sequence management across many channels. The supplied code chunk does not implement or directly expose those platform features; instead, it initializes configuration, loads an OpenAPI spec, and launches a server using stdio and/or SSE transports. That is a materially different primary purpose for this chunk. While this may be supporting infrastructure for the broader product, based on the provided code alone the behavior is an MCP server bootstrapper, which is not accurately represented by the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad chat marketing platform for multi-channel customer engagement management. The supplied code chunk instead specifically implements backend infrastructure for an MCP Server-Sent Events/streamable HTTP transport layer. While this could be a supporting component inside a larger platform, the behavior shown is not representative of the declared product purpose and exposes a distinct capability: an MCP protocol server with session handling and API token intake. There are no visible features for managing contacts, conversations, broadcasts, sequences, or channel integrations in this code chunk. Therefore, this code does not accurately match the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a multi-channel chat marketing platform focused on contact management, conversations, flows, broadcasts, and sequences. The supplied code chunk does not implement any of those application-level capabilities. Instead, it is a small infrastructure utility that creates an MCP server and connects it via stdio transport. This is a materially different purpose from the declared product description, and no chat-platform-specific behavior is evident in this code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code chunk is a developer test script, not code implementing chat marketing platform features like managing contacts, conversations, broadcasts, or multichannel messaging workflows. It imports environment configuration, loads an OpenAPI spec, and logs tool metadata. That behavior is materially different from the declared product description, so this chunk does not accurately represent the stated purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code chunk does not implement or expose any of the platform capabilities described in the declared purpose. It is only a development configuration file for the Vitest test runner, specifying how tests should be discovered and executed. While such a file could be part of the broader project, this chunk’s actual purpose is materially different from the declared skill description, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

bash
chatbotx --refresh-spec <command>
# or
rm ~/.chatbotX/openapi-cache.json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 302)May include surrounding context.

md
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.cjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.mjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · docker/Dockerfile (reported line 23)May include surrounding context.

dockerfile
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

json
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.cjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.mjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.cjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · dist/index.mjs (reported line 2)May include surrounding context.

js
#!/usr/bin/env node
import{createRequire as e}from"node:module";import t from"crypto";import{randomUUID as n}from"node:crypto";import{createServer as r}from"node:http";import{Http2ServerRequest as i,constants as a}from"http2";import{Readable as o}from"stream";import s from"node:process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)),_=e(import.meta.url),v=m(((e,t)=>{let n=_(`fs`),r=_(`path`),i=_(`os`),a=_(`crypto`),o=[`◈ encrypted .env [www.dotenvx.com]`,`◈ secrets for agents [www.dotenvx.com]`,`⌁ auth for agents [www.vestauth.com]`,`⌘ custom filepath { path: '/custom/path/.env' }`,`⌘ enable debugging { debug: true }`,`⌘ override existing { override: true }`,`⌘ suppress logs { quiet: true }`,`⌘ multiple files { path: ['.env.local', '.env'] }`];function s(){return o[Math.floor(Math.random()*o.length)]}function c(e){return typeof e==`string`?![`false`,`0`,`no`,`off`,``].includes(e.toLowerCase()):!!e}function l(){return process.stdout.isTTY}function u(e){return l()?`\x1b[2m${e}\x1b[0m`:e}let d=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;function f(e){let t={},n=e.toString();n=n.replace(/\r\n?/gm,`
`);let r;for(;(r=d.exec(n))!=null;){let e=r[1],n=r[2]||``;n=n.trim();let i=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/gm,`$2`),i===`"`&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,`\r`)),t[e]=n}return t}function p(e){e||={};let t=ee(e);e.path=t;let n=x.configDotenv(e);if(!n.parsed){let e=Error(
...[truncated 27 chars]

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The README explicitly instructs users to place a long-lived workspace token in the SSE URL query string for ChatGPT.com. Query-string secrets are routinely exposed through browser history, logs, proxy/CDN access logs, analytics, screenshots, and copy/paste reuse, so this creates a real credential disclosure risk for a token that grants workspace API access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation normalizes token-in-URL usage without any warning about leakage channels or operational safeguards. Even if driven by platform limitations, omitting warnings increases the chance that users will expose secrets in logs, shell history, tickets, and shared configuration.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The follow-up example encourages reusing the full token-bearing URL in shell commands, which further spreads the secret into shell history, process listings in some environments, copied docs, and team chat. Repetition of the full secret-bearing URL increases both accidental disclosure and persistence of leaked credentials.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill requests sensitive capabilities through environment variables and network access but does not declare any explicit tool scope such as allowed tools or permissions. In an agent setting, that weakens least-privilege controls and makes it easier for the skill to invoke broader capabilities than a reviewer may expect, especially given it handles API tokens and can perform remote actions against a ChatbotX instance.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The authentication section instructs users to disable TLS verification via CHATBOTX_ALLOW_SELF_SIGNED_CERT=true without a strong warning, while also demonstrating use of workspace tokens. Disabling certificate validation enables man-in-the-middle interception of API traffic and theft or replay of workspace tokens, which is especially dangerous because those tokens authorize broad account operations.

Content

No source excerpt is available for this finding.