Skip to content

[Security Audit] customink/webmcp #2

@cink-continuous-integration

Description

Security Audit Report: customink/webmcp

Scan Date: 2026-03-22 06:07 UTC
Repository: https://github.com/customink/webmcp
Branch: main
Scan Type: Current State
Tool Version: gitleaks 8.18.0


Executive Summary

Severity Count
HIGH 0
MEDIUM 4
LOW 1
Total 5

The security audit of customink/webmcp revealed no exposed credentials or secrets in the repository. However, four MEDIUM severity issues were identified related to Cross-Site Scripting (XSS) vulnerability, insecure API key storage, overly broad Chrome extension permissions, and missing security controls in the build configuration. The repository contains a WebMCP demo and Chrome extension for testing web-native AI agent interactions. While no immediate credential exposure exists, the identified vulnerabilities could allow attackers to execute arbitrary code or access sensitive API keys if the extension is compromised or installed by users with malicious intent.


HIGH Severity Findings

No HIGH severity findings were identified.


MEDIUM Severity Findings

1. Cross-Site Scripting (XSS) Vulnerability in Extension Sidebar

Attribute Value
File `model-context-tool-inspector/sidebar.js:61`
Type XSS via innerHTML with unsanitized URL
Standard SEC-004 (Input Validation & Sanitization)
Rule manual-xss-check

Evidence:
```javascript
row.innerHTML = `No tools registered yet in ${url || tab.url}`;
```

Remediation:

  1. Immediate: Use `textContent` instead of `innerHTML` for displaying URLs, or sanitize the URL using an escapeHtml function before injection
  2. Implement: Add HTML escaping function similar to the one used in webmcp-demo.html (lines 1768-1773)
  3. Test: Validate that malicious URLs containing `<script>` tags or event handlers cannot execute code

2. Insecure API Key Storage in Browser localStorage

Attribute Value
File `model-context-tool-inspector/sidebar.js:150-152`
Type Sensitive data in unencrypted storage
Standard SEC-001 (Secrets Management)
Rule manual-config-check

Evidence:
```javascript
if (env?.apiKey) localStorage.apiKey ??= env.apiKey;
localStorage.model ??= env?.model || 'gemini-2.5-flash';
genAI = localStorage.apiKey ? new GoogleGenAI({ apiKey: localStorage.apiKey }) : undefined;
```

Remediation:

  1. Immediate: Document in README.md that API keys stored in localStorage are not encrypted and may be accessible to other extensions or malicious scripts
  2. Consider: Use Chrome's `chrome.storage.local` API instead, which provides some isolation from web page scripts
  3. Long-term: Implement Chrome Identity API for OAuth-based authentication instead of storing raw API keys
  4. Add warning: Display a security notice when users input their API key about the storage implications

3. Overly Broad Chrome Extension Permissions

Attribute Value
File `model-context-tool-inspector/manifest.json:7-8,16-22`
Type Excessive permissions scope
Standard SEC-003 (Least Privilege Access)
Rule manual-config-check

Evidence:
```json
"host_permissions": ["<all_urls>"],
"permissions": ["sidePanel", "activeTab", "scripting"],
"content_scripts": [{
"matches": ["<all_urls>"],
"runAt": "document_start",
"js": ["content.js"]
}]
```

Remediation:

  1. Review: Assess if `<all_urls>` is truly necessary for the extension's functionality - consider restricting to specific domains if possible
  2. Document: Add clear permission justification in README.md explaining why broad access is required for WebMCP tool inspection
  3. User Notice: Include privacy policy or permission explanation in the extension description
  4. Consider: Implement optional permissions that activate only when user explicitly tests tools on specific sites

4. Missing .gitignore Entry for Sensitive Configuration File

Attribute Value
File `.gitignore` (missing entry), `model-context-tool-inspector/sidebar.js:142`
Type Risk of credential exposure
Standard SEC-001 (Secrets Management)
Rule manual-config-check

Evidence:
```javascript
// sidebar.js line 142 - attempts to load .env.json
const envModulePromise = import('./.env.json', { with: { type: 'json' } });

// .gitignore does not include .env.json
```

Remediation:

  1. Immediate: Add `.env.json` and `model-context-tool-inspector/.env.json` to `.gitignore`
  2. Create: Add `.env.json.example` template file with placeholder values to guide users
  3. Document: Update README.md with instructions for creating local `.env.json` for API key configuration
  4. Prevent: Consider implementing pre-commit hooks to scan for accidentally committed credential files

LOW Severity Findings

1. Postinstall Script Removes node_modules Directory

Attribute Value
File `model-context-tool-inspector/package.json:3`
Type Unusual build pattern
Standard N/A (Development workflow issue)
Rule manual-config-check

Evidence:
```json
"scripts": {
"postinstall": "npx esbuild ./node_modules/@google/genai/dist/web/index.mjs --bundle --format=esm --outfile=js-genai.js && rm -rf node_modules"
}
```

Remediation:

  1. Document: Add clear comment in package.json and README.md explaining why node_modules is removed after bundling
  2. Consider: This pattern may confuse developers who expect node_modules to persist - consider using `npm ci --production` or similar instead
  3. Advisory: While not a direct security issue, unexpected file deletions in build scripts can mask supply chain attacks or create confusion during security audits

Manual Analysis Observations

  • Good Practice: The demo HTML files (`webmcp-demo.html` and `webmcp-demo-customink.html`) implement proper HTML escaping through the `escapeHtml()` function, preventing XSS in those contexts
  • No Hardcoded Credentials: Automated and manual scans found no hardcoded passwords, API keys, database connection strings, or private keys in the repository
  • No Sensitive Files: No `.env`, `.pem`, `.key`, or SSH private key files were found in the repository
  • No Weak Cryptography: No usage of weak hashing algorithms (MD5, SHA1) was detected
  • No Code Injection Patterns: No `eval()` or `exec()` statements were found in the JavaScript code
  • Experimental Technology: The repository uses WebMCP, an experimental W3C proposal (Microsoft + Google, 2025) - as noted in the README, this is for demonstration/research purposes and should not be used in production yet
  • Copyright Headers: All source files include proper copyright attribution to Google LLC with Apache 2.0 license headers

Recommendations

Immediate Actions

  1. Fix XSS Vulnerability: Replace `innerHTML` with `textContent` in `sidebar.js:61`, or implement HTML escaping before rendering URLs
  2. Update .gitignore: Add `.env.json` and `model-context-tool-inspector/.env.json` to prevent accidental commits of API keys
  3. Document Security Risks: Add a security notice in README.md about:
    • API keys stored in localStorage are not encrypted
    • Chrome extension has broad permissions by design
    • Users should be cautious about which sites they use the extension on

Short-term Improvements

  1. Create .env.json Template: Add `.env.json.example` file with placeholder values to guide users
  2. Implement Pre-commit Hooks: Use `gitleaks` or similar tools as pre-commit hooks to prevent credential commits
  3. Enhance API Key Storage: Consider migrating from `localStorage` to `chrome.storage.local` for better isolation
  4. Add CSP Headers: If serving these demos from a web server, implement Content Security Policy headers
  5. Security Audit CI/CD: Integrate gitleaks into GitHub Actions workflow to scan every commit

Long-term Security Posture

  1. Adopt Secrets Management: For production extensions, implement OAuth-based authentication instead of raw API key storage
  2. Principle of Least Privilege: Review and scope down extension permissions once WebMCP API stabilizes and specific use cases are defined
  3. Security Documentation: Create SECURITY.md with vulnerability reporting process and security best practices for contributors
  4. Regular Audits: Schedule periodic security reviews, especially as WebMCP specification evolves
  5. Input Validation Framework: Establish consistent patterns for sanitizing all user-controlled input across the codebase

Appendix: Tools Used

  • gitleaks 8.18.0: Automated secret detection
  • Manual analysis: Pattern matching and configuration review

Report generated by sec-github-audit skill

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions