Ahrefs

Integrates with Ahrefs' SEO and marketing APIs to provide rank tracking, keyword research, batch analysis, search volume data, and competitor insights for search marketing intelligence workflows.

khadyapi-integrationTypeScript
0Tools
11Findings
95Stars
Mar 19, 2026Last Scanned
4 critical · 6 high · 1 low findings detected

Security Category Deep Dive

Prompt Injection
Prompt & context manipulation attacks
69
Maturity
14
Rules
5
Sub-Categories
1
Gaps
64%
Implemented
56
Tests
1
Stories
PI-DIRDirect Input Injection
100%3 rules
Injection via tool descriptions and parameter fields
GAP-001Prompt Injection Coverage GapMissing detection coverage for emerging prompt injection attack variants not addressed by current rules
PI-INDIndirect / Gateway Injection
100%4 rules
Hidden instructions via external content and tool responses
PI-CTXContext Manipulation
100%2 rules
Context window saturation and prior-approval exploitation
PI-ENCEncoding & Obfuscation
100%3 rules
Payload hiding via invisible chars, base64, schema fields
PI-TPLTemplate & Output Poisoning
100%2 rules
Injection via prompt templates and runtime tool output
Framework Coverage
OWASP MCP Top 1014/14
MITRE ATLAS14/14
CoSAI MCP2/14
OWASP Agentic Top 1012/14
Kill Chain Phases
0Initial Access
0Defense Evasion
0Execution
0Persistence

Findings11

4critical
6high
1low

Critical4

criticalQ13MCP Bridge Package Supply Chain AttackMCP10-supply-chainAML.T0054
Pattern "(?:mcp|fastmcp|langchain-mcp|llama-index-mcp)(?:>=|~=|==)?(?!\d)" matched in source_code: "Mcp" (at position 263)
MCP bridge packages (mcp-remote, mcp-proxy, @modelcontextprotocol/sdk, fastmcp) are high-value supply chain targets — CVE-2025-6514 (CVSS 9.6) in mcp-remote affected 437,000+ installs. Always pin exact versions (no ^ or ~ ranges). Use lockfiles (package-lock.json, pnpm-lock.yaml, uv.lock). Never run `npx mcp-remote` without version pinning. Verify package integrity with `npm audit` or `pip-audit` before deployment. Reference: CVE-2025-6514, OWASP ASI04.
criticalK14Agent Credential Propagation via Shared StateMCP05-privilege-escalationAML.T0054
Pattern "(process\.env|os\.environ|setenv|putenv).*(?:token|credential|api[_\s-]?key|secret|password)" matched in source_code: "process.env.API_KEY" (at position 582)
Never write credentials to shared agent state. Use credential vaults (HashiCorp Vault, AWS Secrets Manager) with per-agent scoped access. Implement OAuth token exchange (RFC 8693) for cross-agent authorization. Redact credentials from all agent outputs before writing to shared memory. Required by OWASP ASI03/ASI07 and MAESTRO L7.
criticalQ11Code Suggestion Poisoning via MCPMCP01-prompt-injectionAML.T0054.001
Pattern "(?:suggest|generate|complete|insert).*(?:code|function|class|import|require)" matched in source_code: "generate clicks on multiple results, while others might not end in any clicks at all. \ntype: integer nullable \n\n**clicks_per_search**: Clicks Per Search is the ratio of Clicks to Keyword Search volume. It shows how many different search results get clicked, on average, when people search for the target keyword in a given country. \ntype: number<float> nullable \n\n**cost_per_click**: Cost Per Click shows the average price that advertisers pay for each ad click in paid search results for a keyword. \ntype: integer nullable \n\n**country**: The country that a given keyword is being tracked in. A two-letter country code (ISO 3166-1 alpha-2). \ntype: string \nenum: `\"AD\"` .. `\"ZW\"` \n\n**country_prev**: The country that a given keyword is being tracked in on the comparison date. A two-letter country code" (at position 5935)
MCP tool outputs flowing into IDE code suggestion contexts must be sanitized. Implement output content policies that: (1) strip hidden Unicode characters (zero-width, RTL override, tag characters), (2) detect embedded instructions targeting AI code assistants, (3) validate code blocks against security patterns before they enter the suggestion pipeline, (4) never include shell commands in tool outputs without explicit [COMMAND] markers visible to the user. Reference: IDEsaster (Dec 2025), arXiv 2509.22040.
criticalC1Command InjectionMCP03-command-injectionAML.T0054
Pattern "`[^`]+`" matched in source_code: "`\"paid_top\"`" (at position 4847)
Replace exec()/execSync() with execFile() and pass arguments as an array, never as a string. Validate all inputs against an allowlist before use in any shell context. For subprocess.run, always pass a list and shell=False.

High6

highK13Unsanitized Tool OutputMCP02-tool-poisoningAML.T0054
Pattern "(?:fetch|axios|requests?\.get|http\.get).*(?:return|respond|result|body|text|data)(?!.*(?:sanitize|escape|encode|strip|validate|parse|extract))" matched in source_code: "fetched yet. \ntype: boolean \n\n**keyword_is_frozen**: Indicates whether a keyword has exceeded the tracked keywords limit on your plan. Such keywords are \"frozen\", meaning they do not have their rankings updated. \ntype: boolean \n\n**keyword_prev**: The keyword your target ranks for on the comparison date. \ntype: string \n\n**language**: The SERP language that a given keyword is being tracked for. \ntype: string \n\n**language_prev**: The SERP language on the comparison date. \ntype: string \n\n**location**: The location (country, state/province, or city) that a given keyword is being tracked in. \ntype: string \n\n**location_prev**: The location (country, state/province, or city) that a given keyword is being tracked in on the comparison date. \ntype: string \n\n**parent_topic**: Parent Topic determines if you can rank for your target keyword while targeting a more general topic on your page instead. To identify the Parent Topic, we take the #1 ranking page for your keyword and find the keyword responsible for sending the most traffic to that page. \ntype: string nullable \n\n**position**: The top position your target ranks for in the organic search results for a keyword. \ntype: integer nullable \n\n**position_diff**: The change in position between your selected dates. \ntype: integer nullable \n\n**position_prev**: The top position on the comparison date. \ntype: integer nullable \n\n**search_type_image**: Search type Image shows the percentage of searches for a keyword made for images, highlighting interest in visual content. \ntype: number<float> nullable \n\n**search_type_news**: Search type News shows the percentage of searches for a keyword made for news articles. \ntype: number<float> nullable \n\n**search_type_video**: Search type Video shows the percentage of searches for a keyword made for video, reflecting interest in video content. \ntype: number<float> nullable \n\n**search_type_web**: Search type Web shows the percentage of searches for a keyword made for general web content, indicating interest in a wide range of information. \ntype: number<float> nullable \n\n**serp_features**: The SERP features that appear in search results for a keyword. \ntype: array[string] \nenum: `\"paid_top\"` `\"paid_bottom\"` `\"paid_right\"` `\"paid_sitelink\"` `\"organic\"` `\"sitelink\"` `\"snippet\"` `\"image\"` `\"article\"` `\"knowledge_card\"` `\"knowledge_panel\"` `\"local_pack\"` `\"local_teaser\"` `\"news\"` `\"question\"` `\"review\"` `\"shopping\"` `\"tweet\"` `\"spelling\"` `\"video\"` `\"discussion\"` `\"ai_overview\"` `\"ai_overview_sitelink\"` `\"organic_shopping\"` `\"image_th\"` `\"video_th\"` `\"ai_overview_found\"` \n\n**serp_updated**: The date when we last checked search engine results for a keyword. \ntype: string<date-time> nullable \n\n**serp_updated_prev**: The date when we checked search engine results up to the comparison date. \ntype: string<date-time> nullable \n\n**tags**: A list of tags assigned to a given keyword. \ntype: array[string] \n\n**tags_prev**: A list of tags assigned to a given keyword on the comparison date. \ntype: array[string] \n\n**target_positions_count**: The number of target URLs ranking for a keyword. \ntype: integer \n\n**traffic**: An estimation of the number of monthly visits that a page gets from organic search over the latest month or over the latest known 12 months of data depending on the \"volume_mode\" parameter. \ntype: integer nullable \n\n**traffic_diff**: The change in traffic between your selected dates. \ntype: integer nullable \n\n**traffic_prev**: An estimation of the number of monthly visits that a page gets from organic search over the latest month or over the latest known 12 months of data depending on the \"volume_mode\" parameter. \ntype: integer nullable \n\n**url**: The top ranking URL in organic search results for a given keyword. \ntype: string<url> nullable \n\n**url_prev**: The top ranking URL in organic search results for a given keyword on the comparison date. \ntype: string<url> nullable \n\n**volume**: An estimation of the average monthly number of searches for a keyword over the latest month or over the latest known 12 months of data" (at position 7171)
Sanitize all external data before including in tool responses. Implement output encoding that neutralizes prompt injection patterns. Truncate excessively long content. Validate structure before passing database results. Apply the principle: treat all external data as untrusted, even in tool outputs. Required by CoSAI MCP-T4.
highQ12Cross-Jurisdiction Data Routing via MCPMCP04-data-exfiltrationT1020
Pattern "(?:region|jurisdiction|country|geo).*(?:route|proxy|forward|redirect|select|choose)" matched in source_code: "country. \ntype: number<float> nullable \n\n**cost_per_click**: Cost Per Click shows the average price that advertisers pay for each ad click in paid search results for a keyword. \ntype: integer nullable \n\n**country**: The country that a given keyword is being tracked in. A two-letter country code (ISO 3166-1 alpha-2). \ntype: string \nenum: `\"AD\"` .. `\"ZW\"` \n\n**country_prev**: The country that a given keyword is being tracked in on the comparison date. A two-letter country code (ISO 3166-1 alpha-2). \ntype: string \nenum: `\"AD\"` .. `\"ZW\"` \n\n**keyword**: The keyword your target ranks for. \ntype: string \n\n**keyword_difficulty**: An estimation of how hard it is to rank in the top 10 organic search results for a keyword on a 100-point scale. \ntype: integer nullable \n\n**keyword_has_data**: Will return `false` if the keyword is still processing and no SERP has been fetched yet. \ntype: boolean \n\n**keyword_is_frozen**: Indicates whether a keyword has exceeded the tracked keywords limit on your plan. Such keywords are \"frozen\", meaning they do not have their rankings updated. \ntype: boolean \n\n**keyword_prev**: The keyword your target ranks for on the comparison date. \ntype: string \n\n**language**: The SERP language that a given keyword is being tracked for. \ntype: string \n\n**language_prev**: The SERP language on the comparison date. \ntype: string \n\n**location**: The location (country, state/province, or city) that a given keyword is being tracked in. \ntype: string \n\n**location_prev**: The location (country, state/province, or city) that a given keyword is being tracked in on the comparison date. \ntype: string \n\n**parent_topic**: Parent Topic determines if you can rank for your target keyword while targeting a more general topic on your page instead. To identify the Parent Topic, we take the #1 ranking page for your keyword and find the keyword responsible for sending the most traffic to that page. \ntype: string nullable \n\n**position**: The top position your target ranks for in the organic search results for a keyword. \ntype: integer nullable \n\n**position_diff**: The change in position between your selected dates. \ntype: integer nullable \n\n**position_prev**: The top position on the comparison date. \ntype: integer nullable \n\n**search_type_image**: Search type Image shows the percentage of searches for a keyword made for images, highlighting interest in visual content. \ntype: number<float> nullable \n\n**search_type_news**: Search type News shows the percentage of searches for a keyword made for news articles. \ntype: number<float> nullable \n\n**search_type_video**: Search type Video shows the percentage of searches for a keyword made for video, reflecting interest in video content. \ntype: number<float> nullable \n\n**search_type_web**: Search type Web shows the percentage of searches for a keyword made for general web content, indicating interest in a wide range of information. \ntype: number<float> nullable \n\n**serp_features**: The SERP features that appear in search results for a keyword. \ntype: array[string] \nenum: `\"paid_top\"` `\"paid_bottom\"` `\"paid_right\"` `\"paid_sitelink\"` `\"organic\"` `\"sitelink\"` `\"snippet\"` `\"image\"` `\"article\"` `\"knowledge_card\"` `\"knowledge_panel\"` `\"local_pack\"` `\"local_teaser\"` `\"news\"` `\"question\"` `\"review\"` `\"shopping\"` `\"tweet\"` `\"spelling\"` `\"video\"` `\"discussion\"` `\"ai_overview\"` `\"ai_overview_sitelink\"` `\"organic_shopping\"` `\"image_th\"` `\"video_th\"` `\"ai_overview_found\"` \n\n**serp_updated**: The date when we last checked search engine results for a keyword. \ntype: string<date-time> nullable \n\n**serp_updated_prev**: The date when we checked search engine results up to the comparison date. \ntype: string<date-time> nullable \n\n**tags**: A list of tags assigned to a given keyword. \ntype: array[string] \n\n**tags_prev**: A list of tags assigned to a given keyword on the comparison date. \ntype: array[string] \n\n**target_positions_count**: The number of target URLs ranking for a keyword. \ntype: integer \n\n**traffic**: An estimation of the number of monthly visits that a page gets from organic search over the latest month or over the latest known 12 months of data depending on the \"volume_mode\" parameter. \ntype: integer nullable \n\n**traffic_diff**: The change in traffic between your select" (at position 6263)
MCP servers that handle personal or sensitive data must: (1) declare the geographic regions where data is processed in tool descriptions, (2) never route data to third-country backends without GDPR adequacy decisions or Standard Contractual Clauses, (3) log all cross-border data transfers with source/destination jurisdiction for audit, (4) implement data residency enforcement that rejects requests violating localization requirements. Reference: EU AI Act Art. 12, GDPR Art. 44-49.
highK16Unbounded Recursion / Missing Depth LimitsMCP07-insecure-configAML.T0054
Pattern "(invoke|call|execute)[_\s-]?(?:tool|agent|self)(?!.*(?:depth|level|limit|max[_\s-]?(?:depth|recursi|iter|call)|count))" matched in source_code: "CallTool" (at position 216)
Add explicit depth/recursion limits to all recursive operations. Use iterative approaches where possible. Set maximum depth for directory walking (max_depth=10), tree traversal (max_level=20), and agent re-invocation (max_calls=5). Implement circuit breakers that halt after N iterations. Required by EU AI Act Art. 15 (robustness) and OWASP ASI08.
highK18Cross-Trust-Boundary Data Flow in Tool ResponseMCP04-data-exfiltrationAML.T0054
Pattern "(?:readFile|read_file|query|select|getSecret|getCredential|getPassword).*(?:webhook|http|fetch|axios|post|send|email|slack|discord)" matched in source_code: "select` parameter).\n\n**best_position_has_thumbnail**: The top position has a thumbnail. \ntype: boolean nullable\n\n**best_position_has_thumbnail_previous**: The top position has a thumbnail on the comparison date. \ntype: boolean nullable\n\n**best_position_has_video_preview**: The top position has a video preview. \ntype: boolean nullable\n\n**best_position_has_video_preview_previous**: The top position has a video preview on the comparison date. \ntype: boolean nullable\n\n**best_position_kind**: The kind of the top position: organic, paid, or a SERP feature. \ntype: string nullable \nenum: `\"paid_top\"` `\"paid_bottom\"` `\"paid_right\"` `\"paid_sitelink\"` `\"organic\"` `\"sitelink\"` `\"snippet\"` `\"image\"` `\"article\"` `\"knowledge_card\"` `\"knowledge_panel\"` `\"local_pack\"` `\"local_teaser\"` `\"news\"` `\"question\"` `\"review\"` `\"shopping\"` `\"tweet\"` `\"spelling\"` `\"video\"` `\"discussion\"` `\"ai_overview\"` `\"ai_overview_sitelink\"` `\"organic_shopping\"`\n\n**best_position_kind_previous**: The kind of the top position on the comparison date. \ntype: string nullable \nenum: `\"paid_top\"` `\"paid_bottom\"` `\"paid_right\"` `\"paid_sitelink\"` `\"organic\"` `\"sitelink\"` `\"snippet\"` `\"image\"` `\"article\"` `\"knowledge_card\"` `\"knowledge_panel\"` `\"local_pack\"` `\"local_teaser\"` `\"news\"` `\"question\"` `\"review\"` `\"shopping\"` `\"tweet\"` `\"spelling\"` `\"video\"` `\"discussion\"` `\"ai_overview\"` `\"ai_overview_sitelink\"` `\"organic_shopping\"`\n\n**clicks**: Clicks metric refers to the average monthly number of clicks on the search results that people make while searching for the target keyword. Some searches generate clicks on multiple results, while others might not end in any clicks at all. \ntype: integer nullable\n\n**clicks_per_search**: Clicks Per Search is the ratio of Clicks to Keyword Search volume. It shows how many different search results get clicked, on average, when people search for the target keyword in a given country. \ntype: float nullable\n\n**cost_per_click**: Cost Per Click shows the average price that advertisers pay for each ad click in paid search results for a keyword. \ntype: integer nullable\n\n**country**: The country that a given keyword is being tracked in. A two-letter country code (ISO 3166-1 alpha-2). \ntype: string \nenum: `\"AD\"` .. `\"ZW\"`\n\n**country_prev**: The country that a given keyword is being tracked in on the comparison date. A two-letter country code (ISO 3166-1 alpha-2). \ntype: string \nenum: `\"AD\"` .. `\"ZW\"`\n\n**is_main_position**: Excludes positions in Sitelinks, Top stories, Image packs, and posts on X (Twitter). \ntype: boolean\n\n**is_main_position_prev**: Excludes positions in Sitelinks, Top stories, Image packs, and posts on X (Twitter) on the comparison date. \ntype: boolean\n\n**keyword**: The keyword your target ranks for. \ntype: string\n\n**keyword_difficulty**: An estimation of how hard it is to rank in the top 10 organic search results for a keyword on a 100-point scale. \ntype: integer nullable\n\n**keyword_has_data**: Will return `false` if the keyword is still processing and no SERP has been fetched yet. \ntype: boolean\n\n**keyword_is_frozen**: Indicates whether a keyword has exceeded the tracked keywords limit on your plan. Such keywords are \"frozen\", meaning they do not have their rankings updated. \ntype: boolean\n\n**keyword_prev**: The keyword your target ranks for on the comparison date. \ntype: string\n\n**keyword_words**: The number of words in a keyword. \ntype: integer\n\n**keyword_words_prev**: The number of words in a keyword on the comparison date. \ntype: integer\n\n**language**: The SERP language that a given keyword is being tracked for. \ntype: string\n\n**language_prev**: The SERP language on the comparison date. \ntype: string\n\n**location**: The location (country, state/province, or city) that a given keyword is being tracked in. \ntype: string\n\n**location_prev**: The location (country, state/province, or city) that a given keyword is being tracked in on the comparison date. \ntype: string\n\n**parent_topic**: Parent Topic determines if you can rank for your target keyword while targeting a more general topic on your page instead. To identify the Parent Topic, we take the #1 ranking page for your keyword and find the keyword responsible for send" (at position 13733)
Implement data flow taint tracking: tag data from sensitive sources (databases, credentials, files) and prevent it from flowing to external sinks (HTTP, webhooks, email) without explicit sanitization/redaction. Apply data classification and enforce boundary controls per trust level. Required by ISO 27001 A.5.14 and CoSAI MCP-T5.
highD1Known CVEs in DependenciesMCP08-dependency-vuln
Dependency "@modelcontextprotocol/sdk@1.8.0" has known CVEs:
Update dependencies to versions that patch known CVEs. Run 'npm audit fix' or 'pip-audit' to identify and resolve vulnerable dependencies.
highD1Known CVEs in DependenciesMCP08-dependency-vuln
Dependency "axios@1.8.0" has known CVEs:
Update dependencies to versions that patch known CVEs. Run 'npm audit fix' or 'pip-audit' to identify and resolve vulnerable dependencies.

Low1

lowF4MCP Spec Non-ComplianceMCP07-insecure-config
Server fails MCP spec compliance checks: required:server_name; required:server_version; required:protocol_version; recommended:tool_descriptions; recommended:parameter_descriptions
Follow the MCP specification for server metadata. Include server name, version, and protocol version. Provide descriptions for all tools and parameters.