Back to skill

Security audit

SEO Content Engine

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it uses a hard-coded local secrets file and an authenticated Chrome session in ways users should review before installing.

Install only if you are comfortable running it in a dedicated project environment with an explicit GEMINI_API_KEY, an isolated Chrome profile, and manual review of generated articles before publication. Remove or change the hard-coded .env path before use.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T09 · Insecure Skill Coding Practices

Warning
Location
engine.py:187
Finding

Indirect Prompt Injection Through Untrusted Competitor Content

Content
View full analysis
{ const results = []; // Organic results document.querySelectorAll('#search .g, #rso .g').forEach(el => { const titleEl = el.querySelector('h3'); const linkEl = el.querySelector('a[href^="http"]'); const snippetEl = el.querySelector('[data-sncf], .VwiC3b, [style*="-webkit-line-clamp"]'); if (titleEl && linkEl) { results.push({ title: titleEl.textContent.trim(), url: linkEl.getAttribute('href'), snippet: snippetEl ? snippetEl.textContent.trim() : '' }); } }); return results.slice(0, 10); }""") ``` Headings are also collected from arbitrary competitor pages: ```python data = await page.evaluate("""() => { const headings = []; document.querySelectorAll('h1, h2, h3').forEach(h => { headings.push({ level: h.tagName.toLowerCase(), text: h.textContent.trim().substring(0, 200) }); }); // Estimate word count const article = document.querySelector('article, main, [role="main"], .post-content, .entry-content'); const text = (article || document.body).innerText; const wordCount = text.split(/\\s+/).length; return {headings, word_count: wordCount}; }""") ``` The resulting attacker-controlled text is directly interpolated into the generation prompt: ```python serp_section = "" if serp_results: serp_section = "## Top Competing Articles\n" for i, r in enumerate(serp_results[:10], 1): serp_section += f"{i}. ...[truncated 3428 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:12
Finding

Unpinned and Incompletely Declared Third-Party Dependencies

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

The credential-loading behavior at line 21 is a genuine credential access concern because the skill reaches into a fixed local .env file and imports secrets unrelated to the task. In the context of an agent skill, this broadens access beyond least privilege and could expose sensitive API keys or other environment data if the file contains more than the intended Gemini credential.

Content

Scanner excerpt · engine.py (reported line 21)May include surrounding context.

python
from dotenv import load_dotenv

# Load env
load_dotenv(Path("/Users/edwin/.openclaw/workspace/dreams-arts/.env"))

try:
    import google.generativeai as genai

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares executable behavior that can access environment secrets, write files, and use the network, but it does not define any explicit tool scope or permission boundaries. In practice, this can cause an agent to invoke the skill with broader capabilities than the user expects, especially since the instructions direct use of a local .env path and web access, increasing the chance of secret exposure or unintended side effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs the agent to perform competitor research by scraping Google results and using Chrome with an active Google session, but it does not provide a clear privacy warning or require consent for using a logged-in browser context. That creates risk of leaking account-linked data, sending authenticated requests unintentionally, or exposing browsing/session information during automated actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code loads environment variables from a hard-coded absolute path in a user home directory, which is unrelated to the skill’s stated purpose and can cause the skill to access local secrets implicitly. In an agent/skill setting, this creates unauthorized credential exposure risk and makes behavior environment-dependent in a way the user may not expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Hard-coding a specific local .env file path causes the skill to read credentials from the host machine without portability safeguards or user consent. This is dangerous because it silently reaches outside the skill boundary and may ingest unrelated secrets from a developer workstation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill transmits assembled prompt data, including scraped competitor research and user-supplied brand/location details, to an external Gemini API. While external inference is expected for an AI-writing skill, the absence of clear disclosure or consent creates a privacy and data-handling risk, especially if users assume research remains local.

Content

No source excerpt is available for this finding.