Back to skill

Security audit

ShipStatic

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its ShipStatic deployment purpose, but it needs review because realistic workflows can expose credentials or upload unintended local files.

Install only if you trust the package and understand that it can upload local files, use ShipStatic credentials, and modify deployments, domains, and tokens. Avoid running it in untrusted repositories while ShipStatic credentials are in the environment, inspect deployment directories for symlinks before upload, and protect or avoid plaintext ~/.shiprc credentials.

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
src/node/core/config.ts:109
Finding

Project-Controlled API Endpoint Can Receive Environment-Sourced Credentials

Content
View full analysis
); const fetchOptions: RequestInit = { ...options, ...[truncated 2752 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/node/core/node-files.ts:20
Finding

Recursive Deployment Follows Symbolic Links Outside the Selected Root

Content
View full analysis
= new Set()): string[] { const results: string[] = []; // Resolve the real path to detect symlink cycles const realPath = fs.realpathSync(dirPath); if (visited.has(realPath)) { // Already visited this directory (symlink cycle) - skip to prevent infinite loop return results; } visited.add(realPath); const entries = fs.readdirSync(dirPath); for (const entry of entries) { const fullPath = path.join(dirPath, entry); const stats = fs.statSync(fullPath); if (stats.isDirectory()) { const subFiles = findAllFilePaths(fullPath, visited); results.push(...subFiles); } else if (stats.isFile()) { results.push(fullPath); } } return results; } ``` ```ts const absolutePaths = paths.flatMap(p => { const absPath = path.resolve(p); try { const stats = fs.statSync(absPath); return stats.isDirectory() ? findAllFilePaths(absPath) : [absPath]; } catch (error) { throw ShipError.file(`Path does not exist: ${p}`, p); } }); ``` ```ts const stats = fs.statSync(filePath); // Skip empty files — R2 cannot store zero-byte objects if (stats.size === 0) { continue; } // Filename and extension validation (shared with browser) validateDeployFile(deployPath, filePath); // Validate file sizes if (stats.size > platformLimits.maxFileSize) { throw ShipError.business(`File ${filePath} is too large. Maximum allowed size is ${platformLimits.maxFileSize / (1024 * 1024)}MB.`); } const content = fs.readFileSync(filePath); const { md5 } = await calculateMD5(content); results.push({ path: deployPath, content, size: content.length, md5, }); ``` ### Technical Analysis `fs.statSync()` follows symbolic links ...[truncated 2088 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
examples/node/index.js:6
Finding

Credential-Shaped API Key Hardcoded in Executable Example

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/node/cli/config.ts:67
Finding

Persistent API Key Written Without Explicit Restrictive Permissions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (161)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · CLAUDE.md (reported line 266)May include surrounding context.

md
| `deployments.list()` | `GET /deployments` | Paginated |
| `deployments.get()` | `GET /deployments/:id` | |
| `deployments.set()` | `PATCH /deployments/:id` | Labels only |
| `deployments.remove()` | `DELETE /deployments/:id` | Returns 202 (async) |
| `domains.set()` | `PUT /domains/:name` | Upsert — create, repoint, or label |
| `domains.list()` | `GET /domains` | |
| `domains.get()` | `GET /domains/:name` | |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · CLAUDE.md (reported line 275)May include surrounding context.

md
| `domains.dns()` | `GET /domains/:name/dns` | DNS provider information |
| `domains.records()` | `GET /domains/:name/records` | Required DNS records |
| `domains.share()` | `GET /domains/:name/share` | Shareable setup hash |
| `domains.remove()` | `DELETE /domains/:name` | |
| `tokens.create()` | `POST /tokens` | Returns 201 |
| `tokens.list()` | `GET /tokens` | |
| `tokens.remove()` | `DELETE /tokens/:token` | Returns 202 (async) |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · CLAUDE.md (reported line 278)May include surrounding context.

md
| `domains.remove()` | `DELETE /domains/:name` | |
| `tokens.create()` | `POST /tokens` | Returns 201 |
| `tokens.list()` | `GET /tokens` | |
| `tokens.remove()` | `DELETE /tokens/:token` | Returns 202 (async) |
| `account.get()` | `GET /account` | |
| `ping()` | `GET /ping` | Returns boolean |
| `getConfig()` | `GET /config` | Cached after init |

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The core behavior generally matches the declared purpose: it deploys static files/directories to ShipStatic. However, the code includes a hardcoded API key, which is a significant undeclared capability because it grants authenticated access to a specific ShipStatic account/resource. That access is materially more sensitive than a generic deployment example and is not reflected in the declared permissions. Aside from that, the deployment/upload behavior itself is consistent with the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill is for interacting with ShipStatic to deploy and manage static hosting resources. However, the supplied code chunk is just a standard React front-end bootstrap file created by Create React App: it imports React modules, renders the App component, and calls reportWebVitals. It does not communicate with shipstatic.com, perform hosting actions, upload files, manage deployments, or configure domains. This is a material mismatch in primary purpose and capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is about static site hosting and deployment operations on ShipStatic. The supplied code instead measures web performance metrics in a React app and forwards them to a callback. It does not interact with ShipStatic, perform deployments, upload files, manage domains, or publish static assets. This is a materially different primary purpose, so it is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

There is a clear mismatch between the declared purpose and the actual code. The description claims ShipStatic deployment and hosting capabilities, but the code shown is merely a frontend testing setup file that adds jest-dom matchers. It does not interact with shipstatic.com, perform hosting-related actions, or implement any deployment workflow.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description focuses on static hosting and deployment functionality via ShipStatic, but the supplied code chunk does not deploy websites, upload files to shipstatic.com, manage domains, or publish static assets. Instead, it performs local shell integration tasks by copying completion files and editing shell startup files. This is a materially different primary purpose and involves filesystem access to user configuration files that is unrelated to the declared hosting/deployment behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose describes a user-facing static hosting/deployment capability for shipstatic.com, but the supplied code chunk does not perform any hosting, deployment, file upload, domain management, or publishing actions. Instead, it provides a low-level SDK utility for detecting whether code is running in Node.js or a browser, plus a testing override. 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
94% confidence
Finding

The declared purpose describes a broad end-user skill for static hosting on ShipStatic. However, the supplied code does not perform hosting, deployment, publishing, domain setup, or deployment management. It is a narrow internal utility for validating and filtering file paths before upload or deployment, including rejecting junk files and unbuilt project markers. While this may support a hosting workflow, it does not itself implement the declared skill behavior. Therefore, the description materially overstates and misrepresents what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared purpose describes a user-facing static hosting and deployment capability for ShipStatic. However, the code shown does not deploy websites, upload to shipstatic.com, manage domains, or perform hosting operations. Instead, it is a low-level helper that calculates MD5 checksums in browser and Node environments, including reading file chunks or file streams. This is materially different from the declared primary purpose. While such a utility could support uploads internally, the chunk itself exposes checksum/file-processing behavior rather than the declared hosting/deployment behavior, so this 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 ShipStatic deployment/hosting skill, but the provided code is a small shared utility module for path string processing. While such helpers could support a deployment tool internally, this chunk by itself does not implement or expose the claimed capabilities, access any hosting service, or interact with shipstatic.com. Therefore the actual behavior in this code chunk is materially different from the declared purpose, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill supports ShipStatic-based static hosting operations, but the actual code shown does not implement any hosting, deployment, file management, domain configuration, or external service interaction. It is a simple utility for pluralizing text. This is a materially different primary purpose, so the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a production-facing ShipStatic hosting/deployment skill, but the supplied code is strictly test infrastructure. Its functions support creating temporary test environments, writing configuration fixtures, switching the current working directory, and cleaning up temporary directories. These are materially different from deploying websites or managing ShipStatic resources. While local file handling could be a supporting detail in a broader deployment tool, this chunk alone shows no ShipStatic-specific behavior and instead exposes unrelated test utilities, so the description does not accurately represent this code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose centers on ShipStatic hosting operations, but the actual code is only client-side demo-site behavior and test instrumentation. While such a file could be part of a hosted site, this code chunk itself does not implement or invoke any static hosting, deployment, upload, or domain-management capability. Its primary purpose is unrelated UI interactivity and CLI/demo validation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This code chunk’s primary purpose is unrelated to static hosting operations. It is a Vitest test file focused on cross-platform environment behavior in a library, including mocked browser APIs, runtime guards, config isolation, and Ship class environment validation. While the name 'Ship' appears, the code does not actually perform website deployment, file upload to shipstatic.com, domain management, or deployment management. Therefore the declared description does not accurately represent the behavior of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is a production skill for ShipStatic hosting operations such as deploying sites, uploading files, and managing domains. The supplied code does not implement or invoke static hosting, deployment, file upload, domain management, or publishing to shipstatic.com. Instead, it contains automated tests for internal event-system reliability in a Ship client, centered on request/response events and ping calls with mocked fetch responses. This is a materially different purpose, so the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose centers on static hosting via ShipStatic and operational actions like deploying websites, uploading files, managing deployments, and configuring domains. The actual code chunk is only a test file demonstrating an SDK event emitter interface around API calls. It mocks fetch, attaches request/response/error handlers, calls ship.ping(), and validates observability and listener management. These behaviors are unrelated to the declared primary purpose and do not show any hosting or deployment functionality. While this may be supporting infrastructure for a broader SDK, this code chunk itself materially differs from the described skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk does relate to ShipStatic deployment/upload functionality, which partially matches the declared purpose. However, it also exercises token management capabilities that are not mentioned in the description. Additionally, the chunk is specifically a test suite for the browser SDK rather than code implementing static hosting, deployment management, or domain setup itself. The biggest material mismatch is the undeclared token-management capability; domain setup is declared but not evidenced here. Overall, the description does not accurately represent the full behavior present in this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The code chunk does not implement or invoke static website hosting, deployment, file upload to shipstatic.com, domain setup, or deployment management. Its primary purpose is testing CLI configuration resolution logic on the local filesystem. While config loading could be a supporting part of a hosting tool, this chunk itself is materially different from the declared skill purpose and exposes undeclared filesystem/config-testing behavior rather than hosting capabilities.

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 · examples/vanilla/package.json (reported line 6)May include surrounding context.

json
"version": "1.0.0",
  "scripts": {
    "start": "serve .",
    "clean": "rm -f ./ship.js",
    "copy": "pnpm run clean && cp ../../dist/browser.js ./ship.js"
  },
  "devDependencies": {

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

setHeaders() allows arbitrary global headers on every request, and the comment explicitly mentions admin impersonation as a use case. In a deployment SDK, this can let callers inject privileged or identity-altering headers to bypass normal authorization boundaries, especially if upstream services trust such headers.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · tests/mocks/api.ts (reported line 189)May include surrounding context.

ts
return HttpResponse.json(newDeployment, { status: 201 });
  }),

  // DELETE /deployments/:id
  http.delete('*/deployments/:id', ({ params }) => {
    const deployment = mockDeployments.find(d => d.deployment === params.id);
    if (!deployment) {

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · tests/mocks/api.ts (reported line 271)May include surrounding context.

ts
return HttpResponse.json(domainResult, { status: 201 });
  }),

  // DELETE /domains/:name
  http.delete('*/domains/:name', ({ params }) => {
    const domain = mockDomains.find(d => d.domain === params.name);
    if (!domain) {

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 · tests/node/core/node-files.test.ts (reported line 1456)May include surrounding context.

ts
const result = await processFilesForNode(['./dist']);

      // index.html should be kept, .DS_Store and .env should be filtered
      expect(result).toHaveLength(1);
      expect(result[0].path).toBe('index.html');
    });

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/mocks/cli.js:25

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/node/cli/completion.test.ts:8

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/node/cli/helpers.ts:66

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
examples/auth-lifecycle-example.ts:80

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
examples/node/index.js:7

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/node/core/config.ts:122

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/shared/core/config.ts:28

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/browser/browser.test.ts:55

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/e2e/smoke.e2e.test.ts:238

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/integration/authentication-flow.test.ts:244

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/mixed-core/browser-sdk.test.ts:48

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/mixed-core/client.test.ts:42

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/mixed-core/config-directory-traversal.test.ts:161

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/mixed-core/node-sdk.test.ts:57

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/mocks/cli.js:31

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/node/cli/cli-api.test.ts:22

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/node/cli/config.test.ts:12

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/node/cli/helpers.ts:54

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/node/node.test.ts:46

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/shared/auth-lifecycle.test.ts:202

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/shared/base-ship.test.ts:55