Back to skill

Security audit

Grok Geo

Security checks for vulnerabilities and agentic risk

Overview

This GEO audit skill is mostly purpose-aligned, but its MCP tools can read outside the intended runs directory when given crafted run IDs, so it needs review before installation.

Install only in a trusted, local environment until the MCP run_id path handling is fixed. Do not expose the MCP server to untrusted clients, and avoid using untrusted run IDs. Expect live AI/search queries to send audit prompts and brand information to configured providers, and expect optional alert channels to send alert details to configured email or webhook destinations. Avoid scheduler command helpers with untrusted names or cron values until they validate and quote inputs.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
mcp/mcp_server.py:140
Finding

MCP Run Identifier Path Traversal Allows Unauthorized File Disclosure

Content
View full analysis
Dict[str, Any]: """Check audit run status.""" run_id = args["run_id"] run_dir = self.base_dir / run_id try: manifest = load_manifest(run_dir) except FileNotFoundError: return {"content": [{"type": "text", "text": f"Run not found: {run_id}"}], "isError": True} ``` ```python def _tool_audit_report(self, args: Dict[str, Any]) -> Dict[str, Any]: """Get audit report.""" run_id = args["run_id"] fmt = args.get("format", "markdown") run_dir = self.base_dir / run_id ext = "md" if fmt == "markdown" else "json" report_path = run_dir / "output" / f"report.{ext}" if not report_path.exists(): return {"content": [{"type": "text", "text": f"Report not found: {report_path}"}], "isError": True} content = report_path.read_text(encoding="utf-8") ``` ```python def _tool_audit_metrics(self, args: Dict[str, Any]) -> Dict[str, Any]: """Get computed metrics, optionally filtered by tier.""" run_id = args["run_id"] tier_filter = args.get("tier", "all") run_dir = self.base_dir / run_id metrics_path = run_dir / "intermediate" / "metrics.json" if not metrics_path.exists(): return {"content": [{"type": "text", "text": "Metrics not found. Run calculate_metrics.py first."}], "isError": True} metrics = read_json(metrics_path) ``` ### Technical Analysis The MCP handlers accept `run_id` directly from tool-call arguments and combine it with `self.base_dir` without validating the identifier or applying the project's existing `resolve_under()` containment function. A relative value containing `../` components can escape the configured audit directory ...[truncated 1979 chars]
Remediation
View remediation
Path: if not isinstance(run_id, str) or not RUN_ID_PATTERN.fullmatch(run_id): raise ValueError("Invalid run identifier") return resolve_under(base_dir, run_id) ``` 3. Use the same centralized resolver in `_tool_audit_status()`, `_tool_audit_report()`, and `_tool_audit_metrics()`. 4. After resolving the path, verify that it represents a valid audit run and that the manifest's stored `run_id` equals the requested identifier. 5. Reject symlink-based escapes by resolving the final target and confirming that it remains beneath the resolved base directory before every read. 6. Add regression tests covering: - `../` traversal. - Absolute Unix and Windows paths. - Encoded or mixed-separator traversal. - Symlink escapes. - Valid generated run identifiers. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scheduler.py:165
Finding

Shell Command Injection in Generated Cron and Windows Scheduled-Task Commands

Content
View full analysis
str: """Generate crontab command for a schedule.""" python_path = sys.executable return f"{cron} cd {script_path.parent.parent} && {python_path} {script_path} --run {schedule_name}" def generate_windows_task_command(schedule_name: str, script_path: Path, time: str = "02:00") -> str: """Generate Windows Task Scheduler command.""" python_path = sys.executable return f'schtasks /create /tn "GEOAudit_{schedule_name}" /tr "{python_path} {script_path} --run {schedule_name}" /sc daily /st {time}' ``` ### Technical Analysis Both helper functions interpolate values directly into executable command strings without validation or platform-appropriate quoting. The Unix cron command is affected by several unsafe fields: - `cron` is inserted at the start of the cron entry. - `script_path.parent.parent` is inserted after `cd` without quoting. - `python_path` and `script_path` are unquoted. - `schedule_name` is appended as a shell argument without quoting. The Windows command embeds `schedule_name`, interpreter paths, script paths, and `time` inside a command line with incomplete quote boundaries. Embedded quotation marks or command metacharacters can alter the intended `schtasks` command. If attacker-controlled values reach either function and the generated command is executed by an operator or integration, the attacker can append or substitute local commands. Execution would occur with the privileges of the account installing the scheduled job. The reviewed implementation does not automatically invoke `crontab` or `schtasks`, and no call sites for these two command-generation helpers were identified in the audit history. Con ...[truncated 1449 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (161)

Direct flow: os.getenv (credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/api_adapters.py (reported line 351)May include surrounding context.

python
def _get_access_token(self) -> str:
        """Get access token from Baidu."""
        import httpx
        response = httpx.post(
            "https://aip.baidubce.com/oauth/2.0/token",
            params={
                "grant_type": "client_credentials",

Direct flow: os.getenv (credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/api_adapters.py (reported line 632)May include surrounding context.

python
def _get_access_token(self) -> str:
        """Get access token from Baidu."""
        import httpx
        response = httpx.post(
            "https://aip.baidubce.com/oauth/2.0/token",
            params={
                "grant_type": "client_credentials",

Direct flow: os.getenv (credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The Volcengine adapter prefers ARK_API_KEY from the environment over its own configured credential, causing a hidden credential source and potential cross-provider secret use. This can send a different secret than the one implied by validate_config(), which increases the chance of unintended credential disclosure, tenant mix-ups, and hard-to-audit outbound authentication.

Content

Scanner excerpt · scripts/api_adapters.py (reported line 660)May include surrounding context.

python
# Volcengine uses the same endpoint as ByteDance Doubao
            import httpx
            endpoint_id = kwargs.get("endpoint_id", "doubao-pro-4k")
            response = httpx.post(
                "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
                headers={
                    "Authorization": f"Bearer {os.getenv('ARK_API_KEY', self.api_key)}",

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This code chunk’s primary function is notification delivery, not GEO audit or AI-search visibility analysis. While alerts could be a supporting feature within a broader GEO monitoring system, the declared description does not mention alerting, messaging integrations, SMTP usage, or webhook-based communications. The code accesses external communication services and sends data outward, which is a materially different capability from diagnosing brand visibility or generating GEO reports. Therefore, this chunk is mismatched with the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description promises a comprehensive GEO/AI search audit capability focused on brand mention analysis, citations, competitor comparisons, factual accuracy, and content-gap diagnostics across many AI engines. The supplied code does something much narrower: it pulls analytics data from Google Analytics 4 for sessions whose source matches a fixed list of AI-related domains, optionally pulls Search Console query/page data, and summarizes traffic and engagement metrics. That is related to AI-search traffic analysis, but it does not inspect AI engine answers, citations, recommendations, competitor references, or factual accuracy, and it does not implement the broad cross-engine audit behavior claimed. Therefore the description materially overstates and misrepresents the actual functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The code is related to GEO/AI-search analysis, so there is partial alignment with the declared GEO audit purpose. However, the declared description emphasizes visibility, recommendations, citations, competitor presence, factual accuracy, and content-gap analysis across AI engines. This code chunk instead focuses on a different set of 'ceiling' capabilities: agentic commerce readiness, defensive GEO hallucination detection, A2A optimization/readiness, multimodal readiness, and heuristic prediction. It also optionally generates an agent manifest file and produces correction-action plans, which are undeclared capabilities. There is little in this chunk that performs competitor comparison, citation analysis, broad brand visibility diagnostics across 17+ engines, or content-gap analysis as described. Therefore the description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose describes a broad generative engine optimization and AI-search audit capability focused on brand visibility, citations, competitors, factual checks, and multi-engine analysis. The supplied code does none of that. It only classifies existing question records into funnel stages based on intent or keyword regexes and outputs summary counts. This is not merely a supporting implementation detail for the declared functionality; it is a distinct primary function with different inputs, outputs, and analytical scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes a high-level brand visibility and AI search audit capability across many engines. However, the provided code implements only low-level hashing utilities using SHA-256 for bytes, strings, files, and JSON serialization. This is a generic support function and, by itself, does not perform any of the declared analysis tasks, interact with AI engines, inspect search results, analyze citations, or compare brands versus competitors. Because the actual code chunk’s purpose is materially different and unrelated to the declared primary purpose, this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is a high-level brand visibility and AI search audit capability, but the supplied code chunk does not perform any analysis of brands, citations, competitors, AI engines, web search, or GEO reporting. Instead, it provides a generic concurrency helper for exclusive file locking on the local filesystem. While such locking could be an internal supporting utility in a larger system, this code chunk by itself has a materially different purpose from the declared description and exposes undeclared filesystem/process-synchronization behavior. Therefore this chunk does not accurately represent the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a brand visibility and AI-search/GEO auditing capability across multiple AI engines. The actual code chunk does not perform any search, brand analysis, citation analysis, competitor comparison, factual checking, content-gap analysis, or interaction with AI engines. Instead, it provides generic JSON Schema validation utilities and reads schema files from local storage. This is a materially different primary purpose, so the description does not accurately represent the code behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

This code has a much narrower purpose than the declared description. Its sole observable function is attribute mention extraction from search-result answer text using keyword matching, plus simple aggregation and brand-conditioned counting. That can be a supporting component within a larger GEO audit pipeline, but by itself it does not match the declared end-user capability set, which emphasizes comprehensive brand visibility diagnostics, citations, competitor comparisons, factual accuracy, and content-gap analysis across 17+ AI engines. There is no sign of engine-specific integrations, competitor handling, citation/source extraction, accuracy verification, or gap detection in this chunk. Therefore the description materially overstates what this supplied code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose centers on GEO/AI-search auditing and visibility analysis across multiple AI engines. In contrast, this code chunk only transforms structured brand input into standardized machine-readable files and performs basic validation. While such files might support GEO efforts indirectly, the chunk itself does not perform the claimed diagnostic or comparative auditing functions. This is a material purpose mismatch, not just an implementation detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

The code’s primary function is a rule-based pre-publication GEO lint report generator. It loads brand input plus optional precomputed metrics and search results, but the checks actually implemented are limited to site/page compliance heuristics such as JSON-LD presence, robots/llms.txt accessibility, citability signals, entity consistency, multimodal structure, and hreflang/i18n. While these checks are relevant to GEO optimization, they are only a subset of the declared product scope. The declared description emphasizes diagnosing brand visibility, recommendations, citations, competitor presence, and brand mention analysis across many named AI engines. None of that engine-specific querying, answer parsing, citation extraction, recommendation analysis, or competitor comparison logic appears in this code chunk. Therefore the code behavior is materially narrower and different in primary purpose than the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code chunk is a multi-engine query orchestrator, not a full GEO audit analyzer. It can send prompts to several AI engines, capture answers/citations, and compute basic aggregate metrics such as success rate, citation rate, and cross-engine citation consistency. However, the declared description claims substantially broader analytical functionality: diagnosing brand visibility, recommendations, citations, competitor presence, factual accuracy, and content gaps; supporting many more engines (17+ including multiple named Chinese platforms); and producing GEO audit/report-style analyses. None of the specific brand/competitor/factual-gap analysis logic appears in this code. While citation capture and cross-engine metrics partially align with the description, the primary implemented behavior is data collection and routing across 7 engines, which is materially narrower than declared.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an analysis/auditing skill focused on GEO and AI-search brand visibility diagnostics across multiple engines. The provided code does not perform any such analysis, querying, citation inspection, competitor comparison, or factual/content-gap evaluation. Instead, it handles post-processing of already-generated artifacts: locating output files, recording their paths in a manifest, zipping them, hashing the ZIP, and appending an event. While packaging outputs could be a supporting utility within a larger GEO audit system, this code chunk’s primary behavior is operational file packaging rather than the declared audit/analysis functionality. Therefore, this chunk does not accurately represent the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code chunk’s primary purpose is much narrower than the declared description. It reads brand/site metadata and produces an 'i18n_score' based on localization-related checks such as hreflang, localized content, local contact/address presence, and whether some engine responses appear multilingual. It does not inspect AI search outputs for brand visibility, recommendations, citations, factual accuracy, competitor presence, or content gaps in the broad way described. It also lacks any competitor comparison logic and does not substantiate the claimed support for 17+ AI engines; instead, it only explicitly scores a few engines and a generic local AI flag. This is a material description-to-behavior mismatch, not just an implementation detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an end-user analytical capability: diagnosing brand visibility and citations across AI search engines. The supplied code chunk does not perform any such analysis, search querying, citation checking, competitor comparison, or content-gap diagnosis. Instead, it is an internal orchestration/helper script for maintaining manifest metadata in a run directory. While such a script could be a supporting component inside a larger GEO audit system, this specific code chunk’s actual purpose is operational state management, not the declared audit/analysis function. Therefore the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises a comprehensive AI-search/GEO auditing capability across many AI assistants and use cases such as brand visibility analysis, citation analysis, competitor comparisons, and content diagnostics. The actual code chunk does none of that. It only validates the composition of a question set against schema and ratio constraints: non-brand question ratio, recommendation/comparison ratio, brand_fact ratio, required business_value fields, and duplicate normalized questions. This is at most a supporting preprocessing/QA utility for a larger GEO workflow, but by itself its primary purpose is materially different from the declared end-user functionality. Therefore this code chunk does not accurately represent the declared skill behavior.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 67)May include surrounding context.

md
- Skill root: directory containing this `SKILL.md`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/api_adapters.py (reported line 40)May include surrounding context.

python
@abstractmethod
    def _get_api_key_from_env(self) -> Optional[str]:
        """Get API key from environment variable."""
        pass
    
    @abstractmethod

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/api_adapters.py (reported line 349)May include surrounding context.

python
return bool(self.api_key) and bool(os.getenv("BAIDU_SECRET_KEY"))
    
    def _get_access_token(self) -> str:
        """Get access token from Baidu."""
        import httpx
        response = httpx.post(
            "https://aip.baidubce.com/oauth/2.0/token",

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code fabricates a complete_purchase capability and constructs a checkout API endpoint from the website URL without verifying that such an endpoint exists or is authorized. In an agent ecosystem, this is especially dangerous because generated manifests can be consumed as actionable instructions, potentially causing downstream agents to attempt purchase flows against nonexistent, unintended, or sensitive endpoints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README explicitly advertises real multi-engine queries and report generation, but it does not clearly warn users that the skill may perform outbound network activity and write generated artifacts to disk. In an agent or hosted environment, that omission can lead to unintended data exposure, surprising external requests, or unexpected persistence of potentially sensitive audit outputs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill requires powerful capabilities (web_search and shell) and references filesystem paths and environment-variable overrides, but it does not declare an explicit tool scope or permission boundary. That omission increases the chance of overbroad execution, accidental access to sensitive host resources, or future tool abuse if the runtime grants more capability than the skill strictly needs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The instruction 'Use the specified target region and language' imposes a language constraint, but the skill does not clearly state that the user chooses or opts into that language, nor does it justify a fixed locale policy. Under the policy rule, forcing a specific language or locale without explicit user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.