Back to skill

Security audit

Basecamp CLI

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Basecamp CLI/MCP integration, but it gives an AI client broad authority to change, delete, and route live Basecamp data without enough guardrails.

Install only if you are comfortable giving an AI assistant write-capable access to your Basecamp account. Prefer a dedicated OAuth app/account with minimal practical permissions, confirm project and object IDs before mutating actions, avoid letting the assistant create or test webhooks unless you trust the destination, and update dependencies plus harden pagination URL validation before production or shared-team use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
src/lib/api.ts:23
Finding
Untrusted Pagination URL Can Trigger Authenticated Requests to an Unapproved Origin<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/api.ts:23-47` and `src/lib/api.ts:105-110` **Vulnerability Type**: Unvalidated cross-origin pagination URL **Risk Level**: Medium ### Vulnerable Code ```ts function parseNextLink(linkHeader: string | undefined): string | null { if (!linkHeader) return null; const match = linkHeader.match(/<([^>]+)>;\s*rel="next"/); return match ? match[1] : null; } /** * Fetch all pages of a paginated API endpoint and aggregate results * Handles RFC5988 Link header pagination automatically */ async function fetchAllPages<T>( client: Got, url: string, options?: Options ): Promise<T[]> { const allResults: T[] = []; let nextUrl: string | null = url; while (nextUrl) { const response = await client.get(nextUrl, { ...options, responseType: 'json' }); const items = response.body as T[]; allResults.push(...items); const linkHeader = response.headers.link as string | undefined; nextUrl = parseNextLink(linkHeader); } return allResults; } ``` The client used by this function is configured with an OAuth bearer token: ```ts return got.extend({ prefixUrl: `https://3.basecampapi.com/${accountId}/`, headers: { 'Authorization': `Bearer ${accessToken}`, 'User-Agent': USER_AGENT, 'Content-Type': 'application/json' }, ``` ### Technical Analysis The pagination implementation extracts the next-page URL directly from the server-provided HTTP `Link` header and passes it to the authenticated HTTP client without validating its scheme, hostname, port, or origin. An absolute URL such as `https://attacker.example/next` can therefore cause the application to make an unintended outbound request. Because the `Got` client is configured globally with the Basecamp OAuth bearer token, this design also creates a credential-forwarding risk. Whether the authorization header is retained on a cross-origin absolute request depends on the HTTP client's precise header-handling beha ...[truncated 2350 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse each pagination target with the standard `URL` API and resolve relative links against the fixed Basecamp API origin. 2. Require the URL protocol to be exactly `https:`. 3. Require the URL origin to be exactly `https://3.basecampapi.com`; reject alternate hostnames, ports, embedded credentials, and non-HTTPS schemes. 4. Verify that the account path remains within the selected Basecamp account, for example by requiring the pathname to begin with `/${accountId}/`. 5. Avoid using an absolute untrusted URL with a client that has a default authorization header. Prefer extracting and validating the relative path before issuing the next request. 6. Add tests covering malicious pagination links, including: - Cross-origin HTTPS URLs - HTTP URLs - URLs with alternate ports - URLs containing user-information components - Protocol-relative URLs - Redirects from an approved URL to an unapproved origin 7. Configure redirect handling so authorization headers cannot be forwarded to another origin, and reject cross-origin redirects explicitly. Example hardening approach: ```ts const BASECAMP_ORIGIN = 'https://3.basecampapi.com'; function validateNextLink( linkHeader: string | undefined, accountId: number ): string | null { if (!linkHeader) return null; const match = linkHeader.match(/<([^>]+)>;\s*rel="next"/); if (!match) return null; const parsed = new URL(match[1], `${BASECAMP_ORIGIN}/${accountId}/`); if (parsed.protocol !== 'https:' || parsed.origin !== BASECAMP_ORIGIN) { throw new Error('Rejected cross-origin pagination URL'); } if (!parsed.pathname.startsWith(`/${accountId}/`)) { throw new Error('Rejected pagination URL outside the selected account'); } return `${parsed.pathname}${parsed.search}`; } ``` The validated relative path should then be passed to the Basecamp client, ensuring that the bearer token is only used for the intended API origin. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose describes an end-user Basecamp CLI/MCP server for project-management interactions with Basecamp 4. The supplied code does not implement Basecamp access or MCP tools; it is a maintenance/release script for developers. Its primary purpose is software release automation using bun, npm, git, and GitHub CLI, including pushing to GitHub and publishing to npm. Those capabilities are materially different from the declared Basecamp functionality, so this chunk is a clear description/behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description describes a functional Basecamp 4 CLI/MCP integration with many tools for interacting with Basecamp resources. The actual code chunk does not implement any Basecamp access, MCP tools, CLI commands, API calls, or project management actions. Instead, it only configures the Vitest test runner and coverage settings. This is materially different from the declared purpose, so the description does not accurately represent this code chunk.

Known Vulnerable Dependency: @hono/node-server==1.19.9 — 3 advisory(ies): CVE-2026-39406 (@hono/node-server: Middleware bypass via repeated slashes in serveStatic); GHSA-frvp-7c67-39w9 (Node.js Adapter for Hono: Path traversal in `serve-static` on Windows via encode); CVE-2026-29087 (@hono/node-server has authorization bypass for protected static paths via encode)

High
Category
Supply Chain
Confidence
92% confidence
Finding
The lockfile pins @hono/node-server 1.19.9, and the reported advisories affect static file serving and path normalization/authorization behavior. In a CLI/MCP server package, a vulnerable embedded HTTP server can expose protected files or bypass middleware if the package enables HTTP transport or serves local assets, so this is a real supply-chain risk even if not always reachable in every deployment.

Known Vulnerable Dependency: @modelcontextprotocol/sdk==1.25.3 — 1 advisory(ies): CVE-2026-25536 (@modelcontextprotocol/sdk has cross-client data leak via shared server/transport)

High
Category
Supply Chain
Confidence
97% confidence
Finding
The project directly depends on @modelcontextprotocol/sdk 1.25.3, and the cited advisory describes cross-client data leakage via shared server/transport. Because this skill is explicitly an MCP server with many tools for project-management data, any cross-session isolation flaw could leak Basecamp data between users or clients, making the context especially sensitive.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
83% confidence
Finding
fast-uri is present as a transitive dependency of ajv, and the advisory set includes host confusion and SSRF-related URI parsing flaws. In an MCP server/CLI that likely processes URLs, callbacks, or remote endpoints as part of auth or transport setup, parser inconsistencies can become security relevant if attacker-controlled URIs are validated or normalized with affected code paths.

Known Vulnerable Dependency: hono==4.11.7 — 16 advisory(ies): CVE-2026-56762 (Hono missing validation of cookie name on write path in setCookie()); CVE-2026-47676 (Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro); CVE-2026-47675 (Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie) +13 more

High
Category
Supply Chain
Confidence
88% confidence
Finding
hono 4.11.7 is present and carries multiple security advisories affecting cookie handling, routing, and path processing. Since this skill includes an MCP server and transitively uses Hono through the MCP SDK stack, flaws in request routing or cookie generation can materially affect authentication, authorization, and request isolation if the HTTP transport is enabled.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

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.

Known Vulnerable Dependency: picomatch==4.0.3 — 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.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +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.

Missing User Warnings

High
Confidence
97% confidence
Finding
Creating a webhook causes future Basecamp event data to be delivered to an external payload URL, which can expose sensitive project activity outside Basecamp. In an AI/MCP context, this is more dangerous because an automated agent may configure persistent exfiltration without the user fully realizing the network and data-sharing implications.

Missing User Warnings

High
Confidence
95% confidence
Finding
Testing a webhook intentionally triggers an outbound request to the configured external endpoint, creating network side effects that may leak metadata or activate downstream systems. In an agent setting, this can be abused as an SSRF-like outbound action primitive or to signal attacker-controlled infrastructure without clear user awareness.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The function name suggests deletion of a todo, but it actually calls a generic recording-trash endpoint using only the provided ID. That mismatch can cause an agent or caller to trash an unintended resource type if IDs are confused, leading to destructive actions beyond the apparent scope of the function.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The function is presented as deleting a todo list but simply trashes a generic recording by ID. This type confusion can lead callers to destroy the wrong object when relying on the function name and signature, which is especially risky in automation where IDs may be passed across tool boundaries.

Credential Access

High
Category
Privilege Escalation
Content
/**
 * Generate a machine-specific encryption key
 * This provides better security than plain text while not requiring external dependencies
 * Note: For maximum security, consider using system keychain (macOS Keychain, Windows Credential Manager)
 */
function getEncryptionKey(): Buffer {
  const machineId = `${os.hostname()}-${os.userInfo().username}-basecamp-cli-tokens`;
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
/**
 * Generate a machine-specific encryption key
 * This provides better security than plain text while not requiring external dependencies
 * Note: For maximum security, consider using system keychain (macOS Keychain, Windows Credential Manager)
 */
function getEncryptionKey(): Buffer {
  const machineId = `${os.hostname()}-${os.userInfo().username}-basecamp-cli-tokens`;
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This markdown file advertises commands and MCP tools that create, update, archive, delete, trash, move, subscribe, unsubscribe, and send content in a real Basecamp account, but it does not include a clear warning that these operations modify live user/project data. Because the file is the primary skill description and includes AI-assistant integration, users should be explicitly warned before using commands that can irreversibly affect workspace content.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill exposes capabilities that require environment variable access and network communication, but it does not declare any explicit tool scope or allowed-tools restrictions. In an MCP/agent context, missing scope declarations can lead to over-broad access and make it harder for users or host platforms to understand and constrain what the skill may do with secrets and remote endpoints.

Session Persistence

Medium
Category
Rogue Agent
Content
## Authentication Setup

1. Create an OAuth app at https://launchpad.37signals.com/integrations
   - Set redirect URI to `http://localhost:9292/callback`
2. Configure credentials:
```bash
Confidence
67% confidence
Finding
The authentication instructions rely on persistent client credentials in environment variables and an OAuth login flow using a localhost callback, which introduces session and secret-handling risk if tokens or credentials are stored insecurely on a shared system. While localhost OAuth callbacks are common, the skill documentation does not describe token storage protections, logout/revocation behavior, or precautions for multi-user environments.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill advertises numerous destructive operations such as delete, archive, trash, move, and update actions against live Basecamp resources without any warning, confirmation guidance, or clear distinction between safe read-only and mutating tools. In an AI-driven workflow, that increases the chance of accidental data loss or unauthorized modification when a model selects tools autonomously.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The manifest describes a CLI/MCP server for interacting with Basecamp 4 projects, todos, messages, schedules, cards, documents, and campfires. This script instead pushes code to GitHub, publishes to npm, and creates GitHub releases, which are software release-management capabilities unrelated to Basecamp project interaction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This validation script performs real state-changing actions against a live Basecamp account, including creating and completing a todo, but it does not prominently warn that running it will modify production data. In an AI-agent skill context, test scripts that mutate third-party SaaS state are riskier because they may be invoked with insufficient operator awareness, causing unintended data changes in a real workspace.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The manifest describes a CLI/MCP skill for interacting with Basecamp resources, but this file imports child_process and later executes arbitrary shell command strings to drive validation. Spawning subprocesses and using shell pipelines is a broader host-execution capability than the stated project-management purpose itself requires.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The manifest describes interacting with Basecamp projects, todos, messages, schedules, kanban cards, documents, and campfires, but this file also exposes CRUD and test operations for project webhooks. Webhook endpoint management introduces outbound integration/control capabilities beyond the enumerated resource types in the manifest description, making it an unjustified capability relative to the stated purpose.

External Transmission

Medium
Category
Data Exfiltration
Content
it('should accept HTTPS URLs', () => {
      const validUrls = [
        'https://example.com/webhook',
        'https://api.example.com/v1/webhooks',
        'https://webhook.example.com:8443/endpoint'
      ];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
it('should reject HTTP URLs', () => {
      const invalidUrls = [
        'http://example.com/webhook',
        'http://api.example.com/v1/webhooks'
      ];

      invalidUrls.forEach(url => {
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/validate.ts:46

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/__tests__/example.test.ts:48

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/__tests__/config.test.ts:16

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/__tests__/mocks/handlers.ts:392

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/__tests__/setup.ts:26

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/lib/auth.ts:182

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/lib/config.ts:131