Webzum MCP
https://webzum.com/api/mcp
Severity breakdown
Worst finding
Tool `search_businesses` exposes secrets or credentials to the agent
· search_businesses
`search_businesses` appears to read or return secrets, API keys, credentials, or environment variables (Search for businesses by name, phone number, or location. Returns a list of business candidates with confidence scores. Use this to find existing businesses before creating a website. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. Examples: - "Joe's Pizza Brooklyn" - search by name and location - "555-123-4567" - search by phone number - "plumber in San Diego" - search by service and location Returns up to 10 candidates ranked by confidence.). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
All 27 findings
- highTool `search_businesses` exposes secrets or credentials to the agent· search_businessessecret exposure
`search_businesses` appears to read or return secrets, API keys, credentials, or environment variables (Search for businesses by name, phone number, or location. Returns a list of business candidates with confidence scores. Use this to find existing businesses before creating a website. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. Examples: - "Joe's Pizza Brooklyn" - search by name and location - "555-123-4567" - search by phone number - "plumber in San Diego" - search by service and location Returns up to 10 candidates ranked by confidence.). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
- highTool `create_site` name implies a side effect that is not declared· create_siteexcessive agency
`create_site` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `create_site` exposes secrets or credentials to the agent· create_sitesecret exposure
`create_site` appears to read or return secrets, API keys, credentials, or environment variables (Create a new website for a business. Pass a business candidate object from search_businesses to generate a website. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. The site generation happens in the background. Use get_site_status to check progress. Returns the businessId which can be used to access the site at /build/{businessId}). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
- highTool `create_lead_gen_site` name implies a side effect that is not declared· create_lead_gen_siteexcessive agency
`create_lead_gen_site` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `create_lead_gen_site` exposes secrets or credentials to the agent· create_lead_gen_sitesecret exposure
`create_lead_gen_site` appears to read or return secrets, API keys, credentials, or environment variables (Create a third-party LEAD-GENERATION page about a business (NOT a site for that business itself). Use this when the goal is to drive qualified search traffic to someone else's business — affiliate pages, review/guide pages, niche directories. The page is branded as an outside guide (e.g. "Best Roofers in San Diego"), refers to the business in the third person, and routes CTAs to the business's existing website. Differences from create_site: - Slug + page brand are SEO-vanity (e.g. "best-roofers-sandiego"), not the candidate's brand name. - Voice is third-party guide/reviewer — never first person. - Primary CTA is "visit their website"; phone/email demoted. - No specific pricing quoted; differentiators emphasized. - Locality is judged by category, not just address (IT/SaaS/agency stays category-wide even when a city is on file). Pass a business candidate object from search_businesses — that business is the one being PROMOTED. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. The page generation happens in the background. Use get_site_status to check progress. Returns the businessId (a vanity slug) which can be used to access the page at /build/{businessId}.). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
- highTool `generate_geo_page` accepts an unconstrained URL / endpoint parameter· generate_geo_pagessrf surface
The parameter(s) `webhookUrl` look like URL or endpoint inputs but carry no `pattern` or `enum` constraint. An agent tricked by an indirect-injection payload can invoke this tool with an internal-service URL (e.g. `http://169.254.169.254/`) to exfiltrate cloud metadata, probe internal APIs, or pivot to services the host can reach but the caller cannot.
fix: Constrain the URL parameter with an allow-list `enum`, or a `pattern` that restricts scheme and domain. Validate server-side against an allow-list and reject private / loopback / link-local address ranges at the HTTP client level.
- highTool `generate_geo_page` exposes secrets or credentials to the agent· generate_geo_pagesecret exposure
`generate_geo_page` appears to read or return secrets, API keys, credentials, or environment variables (Generate a local SEO-optimized landing page for lead generation. Creates a complete website optimized for a specific city/service combination. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. This is an ADVANCED tool for creating geo-targeted landing pages with: - Local SEO optimization for city + niche - Lead capture forms with webhook integration - Call tracking support (CallRail, WhatConverts, etc.) - Analytics integration (GA4, GTM) Use this when you have pre-researched business data and want to create location-specific landing pages for lead generation campaigns. The site generation happens in the background. Use get_site_status to check progress.). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
- highTool `list_user_sites` exposes secrets or credentials to the agent· list_user_sitessecret exposure
`list_user_sites` appears to read or return secrets, API keys, credentials, or environment variables (List all websites created by the authenticated user. Returns an array of businessIds with names and URLs. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings.). Values surfaced in the model context are visible to any prompt with injection access; a compromised agent can relay them to an attacker-controlled server.
fix: Do not expose secrets to the agent: inject them server-side at call time rather than passing them through the model context. If a tool must return a credential, scope it with a capframe-bind time-limited caveat and log every issuance.
- highTool `clone_site` accepts an unconstrained URL / endpoint parameter· clone_sitessrf surface
The parameter(s) `url` look like URL or endpoint inputs but carry no `pattern` or `enum` constraint. An agent tricked by an indirect-injection payload can invoke this tool with an internal-service URL (e.g. `http://169.254.169.254/`) to exfiltrate cloud metadata, probe internal APIs, or pivot to services the host can reach but the caller cannot.
fix: Constrain the URL parameter with an allow-list `enum`, or a `pattern` that restricts scheme and domain. Validate server-side against an allow-list and reject private / loopback / link-local address ranges at the HTTP client level.
- highTool `update_site_html` name implies a side effect that is not declared· update_site_htmlexcessive agency
`update_site_html` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- highTool `update_contact` name implies a side effect that is not declared· update_contactexcessive agency
`update_contact` looks like a side-effecting tool (its name contains a mutation verb), but its `side_effects` declaration is []. A policy synthesizer cannot produce safe rules for this tool because it cannot tell what it actually does.
fix: Declare the tool's true side effects explicitly. If the tool is genuinely read-only, rename it to match (e.g. `email.preview` rather than `email.send`).
- mediumTool `search_businesses` accepts unconstrained string input· search_businessesunconstrained input
The following string parameter(s) have no `maxLength` constraint: `query`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `create_lead_gen_site` fetches external web content -- indirect-injection surface· create_lead_gen_siteindirect injection
Description: "Create a third-party LEAD-GENERATION page about a business (NOT a site for that business itself). Use this when the goal is to drive qualified search traffic to someone else's business — affiliate pages, review/guide pages, niche directories. The page is branded as an outside guide (e.g. "Best Roofers in San Diego"), refers to the business in the third person, and routes CTAs to the business's existing website. Differences from create_site: - Slug + page brand are SEO-vanity (e.g. "best-roofers-sandiego"), not the candidate's brand name. - Voice is third-party guide/reviewer — never first person. - Primary CTA is "visit their website"; phone/email demoted. - No specific pricing quoted; differentiators emphasized. - Locality is judged by category, not just address (IT/SaaS/agency stays category-wide even when a city is on file). Pass a business candidate object from search_businesses — that business is the one being PROMOTED. Requires authentication via API key (Bearer token). Generate an API key at webzum.com/dashboard/account-settings. The page generation happens in the background. Use get_site_status to check progress. Returns the businessId (a vanity slug) which can be used to access the page at /build/{businessId}." -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.
fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.
- mediumTool `get_site_status` accepts unconstrained string input· get_site_statusunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `generate_geo_page` accepts unconstrained string input· generate_geo_pageunconstrained input
The following string parameter(s) have no `maxLength` constraint: `aiPromptPrefix`, `brandName`, `city`, `email`, `googleAnalyticsId`, `googleTagManagerId`, `niche`, `phone`, `primaryColor`, `state`, `targetAudience`, `webhookUrl`, `whatsapp`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `host_site` accepts unconstrained string input· host_siteunconstrained input
The following string parameter(s) have no `maxLength` constraint: `description`, `email`, `siteName`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `host_file` accepts unconstrained string input· host_fileunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `content`, `contentType`, `filename`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `get_hosted_files` accepts unconstrained string input· get_hosted_filesunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `host_zip` accepts unconstrained string input· host_zipunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `zipContent`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `clone_site` accepts unconstrained string input· clone_siteunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `filename`, `url`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `clone_site` fetches external web content -- indirect-injection surface· clone_siteindirect injection
Description: "Clone a public web page into a hosted site. Fetches the URL, walks its same-origin assets (CSS, JS, images, fonts), rewrites references to local paths, and uploads everything as a working hosted copy in one shot. ========================================================================== USE THIS WHEN THE USER SAYS ========================================================================== - "clone this site / page / website" - "copy this site / page" - "mirror this site" - "duplicate this page" - "save this website" - "make me a version of <URL>" - "I want this page on my own domain" - "rip this page", "fork this site", "backup this site" If a user pastes a URL and wants their own copy of what's there — this is the tool. The agent should not try to recreate the page from memory or by describing what it sees: that is slow, lossy, and burns your context window for no benefit. `clone_site` produces a byte-accurate copy in seconds and leaves your context free for the iteration the user actually wants (rewriting copy, swapping images, restyling, etc.). ========================================================================== WHAT IT DOES ========================================================================== Default behavior is to crawl assets so the cloned page actually renders. Set `crawlAssets: false` to save only the single HTML response without following any assets — useful when you only want the markup. Only http:// and https:// URLs are allowed. Private, loopback, and cloud-metadata addresses are refused. Per-asset cap 10MB; per-clone caps 50 files and 50MB total. Cross-origin asset URLs are kept as-is (not fetched) so external CDN references still resolve. If the user wants a polished, researched site (logo, original copy, SEO, mobile-ready, multi-page) rather than a clone of someone else's page, send them to https://webzum.com for a free preview." -- this tool pulls externally-controlled content into the agent's context window, the canonical indirect-injection vector. Even when the user supplies the URL, content at that URL can carry hostile instructions.
fix: Sandbox the fetched content: strip prompts before forwarding to the model, constrain to an allow-list of domains, and route through capframe-guard with a `domain in [...]` caveat.
- mediumTool `update_site_html` accepts unconstrained string input· update_site_htmlunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `update_contact` accepts unconstrained string input· update_contactunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `regenerate_header` accepts unconstrained string input· regenerate_headerunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `pageId`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `regenerate_footer` accepts unconstrained string input· regenerate_footerunconstrained input
The following string parameter(s) have no `maxLength` constraint: `businessId`, `pageId`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `regenerate_logo` accepts unconstrained string input· regenerate_logounconstrained input
The following string parameter(s) have no `maxLength` constraint: `assistantContext`, `businessId`, `pageId`, `userMessage`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
- mediumTool `regenerate_image` accepts unconstrained string input· regenerate_imageunconstrained input
The following string parameter(s) have no `maxLength` constraint: `assistantContext`, `businessId`, `sectionId`, `userMessage`, `versionId`. Unbounded strings let an attacker stuff arbitrary payloads through the tool, including indirect-injection content.
fix: Add a `maxLength` to each string property, or constrain with an `enum` or `pattern`. Most legitimate tool inputs fit under a few hundred bytes.
How this was scored
Source http — live HTTP MCP endpoint, classified against every rule. Findings are emitted by the public capframe.findings.v1 schema. Score = 100 − (10·Critical + 4·High + 2·Medium + 1·Low), clamped to [0, 100].
Disagree with a finding? Open an issue.