-
Notifications
You must be signed in to change notification settings - Fork 0
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:
- Immediate: Use `textContent` instead of `innerHTML` for displaying URLs, or sanitize the URL using an escapeHtml function before injection
- Implement: Add HTML escaping function similar to the one used in webmcp-demo.html (lines 1768-1773)
- 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:
- Immediate: Document in README.md that API keys stored in localStorage are not encrypted and may be accessible to other extensions or malicious scripts
- Consider: Use Chrome's `chrome.storage.local` API instead, which provides some isolation from web page scripts
- Long-term: Implement Chrome Identity API for OAuth-based authentication instead of storing raw API keys
- 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:
- Review: Assess if `<all_urls>` is truly necessary for the extension's functionality - consider restricting to specific domains if possible
- Document: Add clear permission justification in README.md explaining why broad access is required for WebMCP tool inspection
- User Notice: Include privacy policy or permission explanation in the extension description
- 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:
- Immediate: Add `.env.json` and `model-context-tool-inspector/.env.json` to `.gitignore`
- Create: Add `.env.json.example` template file with placeholder values to guide users
- Document: Update README.md with instructions for creating local `.env.json` for API key configuration
- 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:
- Document: Add clear comment in package.json and README.md explaining why node_modules is removed after bundling
- Consider: This pattern may confuse developers who expect node_modules to persist - consider using `npm ci --production` or similar instead
- 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
- Fix XSS Vulnerability: Replace `innerHTML` with `textContent` in `sidebar.js:61`, or implement HTML escaping before rendering URLs
- Update .gitignore: Add `.env.json` and `model-context-tool-inspector/.env.json` to prevent accidental commits of API keys
- 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
- Create .env.json Template: Add `.env.json.example` file with placeholder values to guide users
- Implement Pre-commit Hooks: Use `gitleaks` or similar tools as pre-commit hooks to prevent credential commits
- Enhance API Key Storage: Consider migrating from `localStorage` to `chrome.storage.local` for better isolation
- Add CSP Headers: If serving these demos from a web server, implement Content Security Policy headers
- Security Audit CI/CD: Integrate gitleaks into GitHub Actions workflow to scan every commit
Long-term Security Posture
- Adopt Secrets Management: For production extensions, implement OAuth-based authentication instead of raw API key storage
- Principle of Least Privilege: Review and scope down extension permissions once WebMCP API stabilizes and specific use cases are defined
- Security Documentation: Create SECURITY.md with vulnerability reporting process and security best practices for contributors
- Regular Audits: Schedule periodic security reviews, especially as WebMCP specification evolves
- 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