TweetSave MCP
https://mcp.tweetsave.org/mcp
Severity breakdown
Worst finding
Tool `tweetsave_get_tweet` accepts unconstrained string input
· tweetsave_get_tweet
The following string parameter(s) have no `maxLength` constraint: `response_format`, `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.
All 8 findings
- mediumTool `tweetsave_get_tweet` accepts unconstrained string input· tweetsave_get_tweetunconstrained input
The following string parameter(s) have no `maxLength` constraint: `response_format`, `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 `tweetsave_get_tweet` fetches external web content -- indirect-injection surface· tweetsave_get_tweetindirect injection
Description: "Fetch a single tweet with all its content including text, media (photos, videos, GIFs), polls, and engagement metrics. This tool retrieves tweet data from Twitter/X using the FxTwitter API. It returns the tweet content, author info, media URLs, and engagement stats. Args: - url (string): Tweet URL or tweet ID - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Tweet data including: - Author info (name, username, avatar) - Tweet text - Media URLs (photos, videos) - Engagement (likes, retweets, replies, views) - Poll data (if applicable) - Quote tweet (if applicable) Examples: - "Get tweet from https://x.com/elonmusk/status/123456" - "Fetch this tweet: 123456789" Note: Does not fetch replies. Use tweetsave_to_blog for a complete blog post with formatting." -- 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 `tweetsave_get_thread` accepts unconstrained string input· tweetsave_get_threadunconstrained input
The following string parameter(s) have no `maxLength` constraint: `response_format`, `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 `tweetsave_get_thread` fetches external web content -- indirect-injection surface· tweetsave_get_threadindirect injection
Description: "Fetch a tweet thread (multiple connected tweets by the same author). Note: Current implementation fetches the main tweet. Full thread crawling requires additional API access. Args: - url (string): URL or ID of any tweet in the thread - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Array of tweets in the thread with all content and media. Examples: - "Get the full thread from this tweet: https://x.com/user/status/123"" -- 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 `tweetsave_to_blog` accepts unconstrained string input· tweetsave_to_blogunconstrained input
The following string parameter(s) have no `maxLength` constraint: `response_format`, `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 `tweetsave_batch` accepts unconstrained string input· tweetsave_batchunconstrained input
The following string parameter(s) have no `maxLength` constraint: `response_format`. 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 `tweetsave_batch` fetches external web content -- indirect-injection surface· tweetsave_batchindirect injection
Description: "Fetch multiple tweets at once (max 10). Useful for: - Collecting tweets from a list - Building a feed from multiple sources - Comparing multiple tweets Args: - urls (string[]): Array of tweet URLs or IDs (max 10) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Array of tweets or a combined feed in markdown format. Examples: - "Fetch these tweets: [url1, url2, url3]"" -- 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 `tweetsave_extract_media` accepts unconstrained string input· tweetsave_extract_mediaunconstrained input
The following string parameter(s) have no `maxLength` constraint: `media_type`, `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.
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.