{"data":{"skill":{"slug":"aaron-he-zhu-serp-analysis","name":"serp-analysis","icon":"📦","repo":"https://github.com/aaron-he-zhu/aaron-marketing-skills/tree/main/seo-geo/research/serp-analysis","status":"approved","author":"aaron-he-zhu","authorVersion":null,"skillstoreRevision":null},"audit":{"id":"b66605a6-7962-4dd6-980c-78a5ef37022d","skill_id":"7e098604-b0d8-4641-adcc-302bac78d83e","version":3,"content_hash":"v2:9f22d902a4190b1e33cced8a68441beb8e612f59:cb2b6ea0382a2ea3d0850563ada5c82b56588f807802fbe18f8e7e365422fcd4:f36fc1379a0854ecb0cfef1aff563f5e88561c5bdd5f191f5553b881639dceeb:8439786393fed654aa0baa4c0a203d40","risk_level":"high","is_blocked":false,"safe_to_publish":false,"analysis_status":"ok","agent_auto_install_policy":"confirmation_required","manual_install_policy":"allowed","summary":"Most static findings are false positives from Markdown code fences, metadata URLs, and documentation links. The confirmed risks are external Python connector commands, optional environment API key use, and a mismatch between declared WebFetch-only tooling and connector-based network behavior.","remediation":[{"issue":"External connector commands","severity":"medium","suggestion":"Replace shell examples with a host-approved structured tool call, or require explicit user confirmation before running the connector scripts."},{"issue":"Declared tool boundary mismatch","severity":"high","suggestion":"Update allowed tools and marketplace disclosures to list external command and network connector behavior, or remove the connector instructions."},{"issue":"Environment API key handling","severity":"high","suggestion":"Document FIRECRAWL_API_KEY use clearly and require opt-in before any connector reads or sends an environment credential."},{"issue":"Parent-directory documentation links","severity":"low","suggestion":"Replace parent-directory links with packaged reference files or plain names so the skill does not imply access outside its bundle."}],"risk_factor_evidence":[{"factor":"external_commands","evidence":[{"file":"SKILL.md","line_end":25,"line_start":23},{"file":"SKILL.md","line_end":27,"line_start":25},{"file":"SKILL.md","line_end":29,"line_start":27},{"file":"SKILL.md","line_end":33,"line_start":29},{"file":"SKILL.md","line_end":37,"line_start":33},{"file":"SKILL.md","line_end":37,"line_start":37},{"file":"SKILL.md","line_end":49,"line_start":49},{"file":"SKILL.md","line_end":51,"line_start":51},{"file":"SKILL.md","line_end":84,"line_start":82},{"file":"SKILL.md","line_end":88,"line_start":84},{"file":"SKILL.md","line_end":90,"line_start":88},{"file":"SKILL.md","line_end":94,"line_start":90},{"file":"SKILL.md","line_end":96,"line_start":94},{"file":"SKILL.md","line_end":100,"line_start":96},{"file":"SKILL.md","line_end":102,"line_start":100},{"file":"SKILL.md","line_end":116,"line_start":102},{"file":"SKILL.md","line_end":116,"line_start":116}]},{"factor":"network","evidence":[{"file":"SKILL.md","line_end":10,"line_start":10},{"file":"SKILL.md","line_end":14,"line_start":14}]},{"factor":"filesystem","evidence":[{"file":"SKILL.md","line_end":39,"line_start":39},{"file":"SKILL.md","line_end":43,"line_start":43},{"file":"SKILL.md","line_end":47,"line_start":47},{"file":"SKILL.md","line_end":49,"line_start":49},{"file":"SKILL.md","line_end":112,"line_start":112},{"file":"SKILL.md","line_end":116,"line_start":116},{"file":"SKILL.md","line_end":123,"line_start":123},{"file":"SKILL.md","line_end":127,"line_start":127}]},{"factor":"env_access","evidence":[{"file":"SKILL.md","line_end":49,"line_start":49}]}],"critical_findings":[],"high_findings":[{"title":"Generic API/secret keys","locations":[{"file":"SKILL.md","line_end":49,"line_start":49}],"confidence":0.64,"description":"**Zero-dependency live SERP (keyless)**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecraw","review_kind":"capability","source_category":"env_access","source_severity":"high","confidence_reasoning":"Line 49 documents optional FIRECRAWL_API_KEY use by the connector, which may consume an environment credential for a third-party service. I found no evidence of credential exfiltration beyond intended API use, but secret access needs explicit disclosure and consent."},{"title":"Declared Tool Boundary Mismatch","locations":[{"file":"SKILL.md","line_end":13,"line_start":13},{"file":"SKILL.md","line_end":51,"line_start":49}],"confidence":0.88,"description":"The skill declares allowed-tools: WebFetch, but later instructs users to run Firecrawl and Tavily Python connector commands for live SERP data. This creates a marketplace disclosure gap because users may expect WebFetch-only behavior while the skill can ask for shell-based network connectors.","review_kind":"security","source_category":"semantic","source_severity":"high","confidence_reasoning":"The allowed tool declaration and connector commands are explicit in the same file. This context-level risk changes the expected permission boundary beyond the raw shell-command pattern."}],"medium_findings":[{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":49,"line_start":49}],"confidence":0.8,"description":"**Zero-dependency live SERP (keyless)**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecraw","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The skill instructs users to run a Firecrawl Python connector with a user-supplied keyword and optional scraping. This is real external command execution with third-party network behavior, so it needs explicit permission and structured argument handling."},{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":51,"line_start":51}],"confidence":0.78,"description":"**Second keyless engine for corroboration**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/tavi","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The skill instructs users to run a Tavily Python connector with a user-supplied keyword and optional answer synthesis. This is external command execution that can contact a third-party service."}],"low_findings":[],"dangerous_patterns":[],"files_scanned":4,"total_lines":416,"audit_model":"codex","audited_at":"2026-07-07T17:25:01.827+00:00","created_at":"2026-07-07T20:48:43.015951+00:00","static_findings":[{"id":"external_commands:SKILL.md:23:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":25,"severity":"medium","line_start":23},{"id":"external_commands:SKILL.md:25:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":27,"severity":"medium","line_start":25},{"id":"external_commands:SKILL.md:27:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":29,"severity":"medium","line_start":27},{"id":"external_commands:SKILL.md:29:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":33,"severity":"medium","line_start":29},{"id":"external_commands:SKILL.md:33:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**Expected output**: a prioritized SERP brief plus the standard handoff summary for `memory/research","category":"external_commands","line_end":37,"severity":"medium","line_start":33},{"id":"external_commands:SKILL.md:37:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **Promotes**: durable keyword priorities, competitor facts, and pending strategy decisions to `mem","category":"external_commands","line_end":37,"severity":"medium","line_start":37},{"id":"external_commands:SKILL.md:49:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**Zero-dependency live SERP (keyless)**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecraw","category":"external_commands","line_end":49,"severity":"medium","line_start":49},{"id":"external_commands:SKILL.md:51:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**Second keyless engine for corroboration**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/tavi","category":"external_commands","line_end":51,"severity":"medium","line_start":51},{"id":"external_commands:SKILL.md:82:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":84,"severity":"medium","line_start":82},{"id":"external_commands:SKILL.md:84:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":88,"severity":"medium","line_start":84},{"id":"external_commands:SKILL.md:88:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":90,"severity":"medium","line_start":88},{"id":"external_commands:SKILL.md:90:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":94,"severity":"medium","line_start":90},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":96,"severity":"medium","line_start":94},{"id":"external_commands:SKILL.md:96:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":100,"severity":"medium","line_start":96},{"id":"external_commands:SKILL.md:100:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":102,"severity":"medium","line_start":100},{"id":"external_commands:SKILL.md:102:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":116,"severity":"medium","line_start":102},{"id":"external_commands:SKILL.md:116:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"Write path: `memory/research/serp-analysis/YYYY-MM-DD-<topic>.md`; promote durable difficulty/intent","category":"external_commands","line_end":116,"severity":"medium","line_start":116},{"id":"network:SKILL.md:10:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"homepage: \"https://github.com/aaron-he-zhu/aaron-marketing-skills\"","category":"network","line_end":10,"severity":"low","line_start":10},{"id":"network:SKILL.md:14:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"metadata: {\"author\": \"aaron-he-zhu\", \"version\": \"16.0.0\", \"discipline\": \"seo-geo\", \"phase\": \"researc","category":"network","line_end":14,"severity":"low","line_start":14},{"id":"filesystem:SKILL.md:39:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"- **Primary next skill**: [content-writer](../../build/content-writer/SKILL.md) when the user is rea","category":"filesystem","line_end":39,"severity":"high","line_start":39},{"id":"filesystem:SKILL.md:43:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"> Emit the standard shape from [skill-contract.md §Handoff Summary Format](../../../references/skill","category":"filesystem","line_end":43,"severity":"high","line_start":43},{"id":"filesystem:SKILL.md:47:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"Optional integrations: ~~SEO tool, ~~search console, ~~AI monitor. Before fetching third-party SERP ","category":"filesystem","line_end":47,"severity":"high","line_start":47},{"id":"filesystem:SKILL.md:49:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"**Zero-dependency live SERP (keyless)**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecraw","category":"filesystem","line_end":49,"severity":"high","line_start":49},{"id":"filesystem:SKILL.md:112:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"See [references/platforms/youtube.md](../../../references/platforms/youtube.md) for YouTube-as-citat","category":"filesystem","line_end":112,"severity":"high","line_start":112},{"id":"filesystem:SKILL.md:116:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"Write path: `memory/research/serp-analysis/YYYY-MM-DD-<topic>.md`; promote durable difficulty/intent","category":"filesystem","line_end":116,"severity":"high","line_start":116},{"id":"filesystem:SKILL.md:123:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"- [YouTube as citation surface](../../../references/platforms/youtube.md) — Video SERP / outlier pac","category":"filesystem","line_end":123,"severity":"high","line_start":123},{"id":"filesystem:SKILL.md:127:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"Primary: [content-writer](../../build/content-writer/SKILL.md).","category":"filesystem","line_end":127,"severity":"high","line_start":127},{"id":"env_access:SKILL.md:49:generic-api-secret-keys","file":"SKILL.md","pattern":"Generic API/secret keys","snippet":"**Zero-dependency live SERP (keyless)**: `python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecraw","category":"env_access","line_end":49,"severity":"high","line_start":49}],"finding_verdicts":[{"id":"external_commands:SKILL.md:23:ruby-shell-backtick-execution","reason":"This is a Markdown code fence around an example user prompt, not executable Ruby or shell syntax. No command is invoked and no user input is evaluated.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:25:ruby-shell-backtick-execution","reason":"The flagged backticks are Markdown fencing between example prompts. They do not create shell execution or dynamic code evaluation.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:27:ruby-shell-backtick-execution","reason":"This block contains a plain-language example prompt for SERP analysis. The backticks are Markdown formatting, not executable command syntax.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:29:ruby-shell-backtick-execution","reason":"The flagged text closes a Markdown example and introduces a documentation section. It does not instruct the agent to run Ruby, shell, or generated code.","verdict":"false_positive","confidence":0.95},{"id":"external_commands:SKILL.md:33:ruby-shell-backtick-execution","reason":"The inline backticks identify a memory path in prose. This is documentation of expected output, not a command execution primitive.","verdict":"false_positive","confidence":0.94},{"id":"external_commands:SKILL.md:37:ruby-shell-backtick-execution","reason":"The inline backticks mark memory file paths for saved research notes. No shell command, interpreter, or user-controlled execution path is present.","verdict":"false_positive","confidence":0.94},{"id":"external_commands:SKILL.md:49:ruby-shell-backtick-execution","reason":"The skill instructs users to run a Firecrawl Python connector with a user-supplied keyword and optional scraping. This is real external command execution with third-party network behavior, so it needs explicit permission and structured argument handling.","verdict":"confirmed","severity":"medium","confidence":0.8},{"id":"external_commands:SKILL.md:51:ruby-shell-backtick-execution","reason":"The skill instructs users to run a Tavily Python connector with a user-supplied keyword and optional answer synthesis. This is external command execution that can contact a third-party service.","verdict":"confirmed","severity":"medium","confidence":0.78},{"id":"external_commands:SKILL.md:82:ruby-shell-backtick-execution","reason":"This is a Markdown fence around a multi-keyword comparison prompt. It is not executable shell or Ruby code.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:84:ruby-shell-backtick-execution","reason":"The flagged text is Markdown formatting between example prompts. It contains no command invocation or code execution behavior.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:88:ruby-shell-backtick-execution","reason":"This is a Markdown fence around an example historical SERP prompt. It is not executable code.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:90:ruby-shell-backtick-execution","reason":"The flagged backticks are Markdown fencing around documentation examples. No runtime command is created.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","reason":"This is a Markdown fence around a local SERP comparison prompt. It does not execute a command.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:96:ruby-shell-backtick-execution","reason":"The flagged text is Markdown formatting around prompt examples. It is not Ruby backtick execution or shell execution.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:100:ruby-shell-backtick-execution","reason":"This is a Markdown fence around a mobile versus desktop SERP prompt. It contains no executable command.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:102:ruby-shell-backtick-execution","reason":"The flagged range starts with the end of a Markdown prompt block and continues into prose analysis instructions. It does not contain executable code.","verdict":"false_positive","confidence":0.95},{"id":"external_commands:SKILL.md:116:ruby-shell-backtick-execution","reason":"The inline backticks identify a recommended output path for saved research. This is not a shell command or dynamic interpreter execution.","verdict":"false_positive","confidence":0.94},{"id":"network:SKILL.md:10:hardcoded-url","reason":"The URL is homepage metadata for the skill source repository. It is not fetched by the skill and does not create runtime network behavior.","verdict":"false_positive","confidence":0.99},{"id":"network:SKILL.md:14:hardcoded-url","reason":"The URL appears inside metadata for the project homepage. This is descriptive metadata, not an instruction to send data over the network.","verdict":"false_positive","confidence":0.99},{"id":"filesystem:SKILL.md:39:path-traversal-sequence","reason":"The parent-directory sequence is part of a Markdown link to a related skill. It is documentation, not a runtime file read, write, or traversal operation.","verdict":"false_positive","confidence":0.9},{"id":"filesystem:SKILL.md:43:path-traversal-sequence","reason":"The flagged path is a Markdown reference to a shared skill contract document. No user-controlled path or file operation is performed.","verdict":"false_positive","confidence":0.9},{"id":"filesystem:SKILL.md:47:path-traversal-sequence","reason":"The parent-directory references point to repository documentation about security and connectors. They are not runtime traversal or filesystem mutation instructions.","verdict":"false_positive","confidence":0.88},{"id":"filesystem:SKILL.md:49:path-traversal-sequence","reason":"The traversal sequence is a Markdown README link, while the executable connector path uses CLAUDE_PLUGIN_ROOT. The real concern on this line is external command execution, which is confirmed separately.","verdict":"false_positive","confidence":0.7},{"id":"filesystem:SKILL.md:112:path-traversal-sequence","reason":"The path traversal sequence appears in a Markdown link to a YouTube reference document. It does not request arbitrary file access.","verdict":"false_positive","confidence":0.9},{"id":"filesystem:SKILL.md:116:path-traversal-sequence","reason":"The write path is a fixed memory location for research output, and the parent-directory sequence is a documentation link. There is no user-controlled traversal path.","verdict":"false_positive","confidence":0.82},{"id":"filesystem:SKILL.md:123:path-traversal-sequence","reason":"The flagged sequence is a Markdown link to a platform reference file. It is not a filesystem access primitive.","verdict":"false_positive","confidence":0.9},{"id":"filesystem:SKILL.md:127:path-traversal-sequence","reason":"The parent-directory sequence is a Markdown link to the recommended next skill. It does not perform file traversal at runtime.","verdict":"false_positive","confidence":0.9},{"id":"env_access:SKILL.md:49:generic-api-secret-keys","reason":"Line 49 documents optional FIRECRAWL_API_KEY use by the connector, which may consume an environment credential for a third-party service. I found no evidence of credential exfiltration beyond intended API use, but secret access needs explicit disclosure and consent.","verdict":"confirmed","severity":"high","confidence":0.64}],"semantic_findings":[{"title":"Declared Tool Boundary Mismatch","severity":"high","locations":[{"file":"SKILL.md","line_end":13,"line_start":13},{"file":"SKILL.md","line_end":51,"line_start":49}],"confidence":0.88,"description":"The skill declares allowed-tools: WebFetch, but later instructs users to run Firecrawl and Tavily Python connector commands for live SERP data. This creates a marketplace disclosure gap because users may expect WebFetch-only behavior while the skill can ask for shell-based network connectors.","confidence_reasoning":"The allowed tool declaration and connector commands are explicit in the same file. This context-level risk changes the expected permission boundary beyond the raw shell-command pattern."}],"subject_marketplace_commit_sha":null,"subject_content_hash":null,"subject_tree_hash":null,"subject_plugin_path":null,"audit_payload_hash":null,"confirmed_risk_level":null,"scanner_version":null,"policy_version":null,"subject":{"marketplaceCommitSha":null,"contentHash":null,"treeHash":null,"pluginPath":null,"auditPayloadHash":null},"scannerVersion":null,"policyVersion":null},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"not_attestable","url":null,"status":null,"reason":"confirmed_risk_level does not match the canonical trust resolver"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"high","confirmedFindingCount":1,"capabilityReviewCount":3,"needsReviewCount":0,"falsePositiveCount":0,"agentAutoInstallPolicy":"confirmation_required","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"not_attestable","verificationState":"not_verified"},"isLatest":false}}