Back to skill

Security audit

GEO Content Writer

Security checks for vulnerabilities and agentic risk

Overview

This content-writing skill is coherent, but it deserves review because it can publish to WordPress and has weak safeguards around credential destinations and citation-page crawling.

Install only if you trust the publisher and can run it with least-privilege Dageno and WordPress credentials. Keep WordPress status at draft unless a human explicitly approves publication, use HTTPS-only trusted site URLs, avoid custom Dageno base URLs outside controlled testing, and consider running citation crawling in a network-restricted environment. Review generated articles before publishing because some examples show quality and topic-consistency problems.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
src/geo_content_writer/citation_crawl.py:11
Finding

Unrestricted citation crawling enables server-side request forgery

Content
View full analysis
List[Dict[str, Any]]: pages: List[Dict[str, Any]] = [] article_count = 0 for url in urls[:max_candidates]: try: response = requests.get( url, timeout=timeout, headers={ "User-Agent": "Mozilla/5.0 (compatible; GEOContentWriter/1.0; +https://github.com/GEO-SEO/geo-content-writer)" }, ) response.raise_for_status() html = response.text ``` The URL values are taken from citation records and passed directly to the crawler: ```python citation_urls = _diversified_citation_urls(context.get("citations", []), limit=citation_limit) crawled_pages = crawl_citation_pages(citation_urls, limit=citation_limit) ``` The URL extraction logic does not perform security validation: ```python def _top_citation_urls(citations: List[Dict[str, Any]], limit: int = 5) -> List[str]: urls: List[str] = [] for item in _top(citations, "citationCount", limit): url = (item.get("url") or "").strip() if url: urls.append(url) return urls ``` ### Technical Analysis The crawler makes outbound requests to citation URLs without validating: - The URL scheme - The resolved IP address - Whether the destination is loopback, private, link-local, reserved, or multicast - The destination port - DNS rebinding between validation and connection - Redirect destinations - Response size or content type `requests.get()` follows redirects by default. Consequently, validating only an in ...[truncated 1942 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/geo_content_writer/client.py:16
Finding

Configurable API base can disclose the Dageno API key to an arbitrary server

Content
View full analysis
None: self.api_key = api_key or os.environ.get("DAGENO_API_KEY") self.base_url = base_url.rstrip("/") self.timeout = timeout self.max_retries = max_retries if not self.api_key: raise ValueError("Missing DAGENO_API_KEY. Pass api_key or set the environment variable.") @property def headers(self) -> Dict[str, str]: return { "x-api-key": self.api_key, "Content-Type": "application/json", } def _request( self, method: str, path: str, *, params: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: last_error: Exception | None = None for attempt in range(1, self.max_retries + 1): try: response = requests.request( method=method, url=f"{self.base_url}{path}", headers=self.headers, params=params, json=json, timeout=self.timeout, ) ``` ### Technical Analysis Supporting Dageno API access is necessary for the declared workflow. Allowing the authenticated endpoint to be changed to any URL is not necessary for normal production ...[truncated 1448 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/geo_content_writer/wordpress.py:20
Finding

WordPress credentials can be transmitted over plaintext HTTP or to an unintended host

Content
View full analysis
None: self.site_url = (site_url or os.environ.get("WORDPRESS_SITE_URL") or "").rstrip("/") self.username = username or os.environ.get("WORDPRESS_USERNAME") self.app_password = app_password or os.environ.get("WORDPRESS_APP_PASSWORD") self.client_id = client_id or os.environ.get("WORDPRESS_CLIENT_ID") self.client_secret = client_secret or os.environ.get("WORDPRESS_CLIENT_SECRET") self.timeout = timeout self.max_retries = max_retries ``` For self-hosted WordPress sites, Basic authentication credentials are sent to the configured URL without requiring HTTPS: ```python else: response = requests.request( method=method, url=f"{self.site_url}/wp-json/wp/v2{path}", auth=(self.username, self.app_password), json=json, timeout=self.timeout, ) ``` The destination and credentials can also be supplied directly through command-line arguments: ```python wp_parser.add_argument("--site-url", default=None, help="WordPress site URL") wp_parser.add_argument("--username", default=None, help="WordPress username") wp_parser.add_argument("--app-password", default=None, help="WordPress application password") wp_parser.add_argument("--client-id", default=None, help="WordPress.com OAuth client ID") wp_parser.add_argument("--client-secret", default=None, help="WordPress.com OAu ...[truncated 2046 chars]
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (57)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Direct WordPress authentication and posting are high-impact side effects that should be clearly and prominently declared, especially when the skill also consumes multiple secrets. In a content-writing context, concealed publishing behavior is more dangerous because automatic publication appears plausibly related to the task, making accidental destructive or reputational actions more likely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Direct WordPress authentication and posting are high-impact side effects that should be clearly and prominently declared, especially when the skill also consumes multiple secrets. In a content-writing context, concealed publishing behavior is more dangerous because automatic publication appears plausibly related to the task, making accidental destructive or reputational actions more likely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Direct WordPress authentication and posting are high-impact side effects that should be clearly and prominently declared, especially when the skill also consumes multiple secrets. In a content-writing context, concealed publishing behavior is more dangerous because automatic publication appears plausibly related to the task, making accidental destructive or reputational actions more likely.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Direct WordPress authentication and posting are high-impact side effects that should be clearly and prominently declared, especially when the skill also consumes multiple secrets. In a content-writing context, concealed publishing behavior is more dangerous because automatic publication appears plausibly related to the task, making accidental destructive or reputational actions more likely.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest says this skill should be used to turn Dageno GEO opportunities into a fanout backlog and write an article from a selected fanout item, and explicitly redirects broad keyword-first SEO generation to a different workflow. However, the batch-run-keywords command accepts an arbitrary keywords file and runs article generation directly from each keyword, bypassing the stated Dageno-opportunity-first scope.

Content

No source excerpt is available for this finding.

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 · src/geo_content_writer/wordpress.py (reported line 112)May include surrounding context.

python
payload = response.json()
        token = payload.get("access_token")
        if not token:
            raise ValueError("WordPress.com OAuth token response did not contain an access token.")
        return token

    def create_post(

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · src/geo_content_writer/workflows.py (reported line 254)May include surrounding context.

python
if profile == "consumer_travel":
        if "travel booking" in prompt.lower():
            return "travel booking apps"
        return prompt or "travel apps"
    if profile == "consumer_general":
        return prompt or topic_clean or "apps"
    if profile == "b2b_software":

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · src/geo_content_writer/workflows.py (reported line 256)May include surrounding context.

python
if profile == "consumer_travel":
        if "travel booking" in prompt.lower():
            return "travel booking apps"
        return prompt or "travel apps"
    if profile == "consumer_general":
        return prompt or topic_clean or "apps"
    if profile == "b2b_software":

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · src/geo_content_writer/workflows.py (reported line 259)May include surrounding context.

python
if profile == "consumer_travel":
        if "travel booking" in prompt.lower():
            return "travel booking apps"
        return prompt or "travel apps"
    if profile == "consumer_general":
        return prompt or topic_clean or "apps"
    if profile == "b2b_software":

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to run a WordPress publishing command with live credentials and a --status draft flag, but it does not clearly warn that this action performs a remote write to an external site and that alternate statuses may publish directly. In an agent-skill context, operational commands in documentation can be treated as executable guidance, increasing the risk of unintended posting, defacement, or leakage of unreviewed AI-generated content to a production CMS.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares access to sensitive environment variables, local file reads/writes, and network-dependent behavior, but does not define an explicit tool scope such as permissions or allowed-tools. This creates an overbroad execution surface where an agent may expose credentials, modify files, or make outbound requests without clear user-visible boundaries.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Lines L17-L19 explicitly state an intent to position Trip as one credible shortlist option in the comparison. However, the rest of the document contains only generic advice about comparison writing and mentions other brands repeatedly without carrying out the promised Trip-inclusive comparison, creating an intent-versus-content contradiction within the file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest says the skill produces a publish-ready article from a selected fanout item, but this file repeats the same two sections multiple times without advancing the comparison or delivering concrete analysis of the named topic. That behavior looks more like unfinished template padding than a real completed article output.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The fanout text and normalized title switch from English to Japanese script, which introduces a locale/language constraint in the generated content targets without any indication that the user opted into Japanese output. This can violate a language policy requiring user choice rather than silently forcing multilingual or non-default language content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This backlog entry contains Japanese text in both the fanout text and normalized title, and the note indicates mixed-script content rather than an intentional, user-selected locale. Because the JSON does not document a justified regional scope or user language preference, it presents a natural-language policy issue.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The article claims to help evaluate industrial gyratory sifters, but substantial portions of the content discuss travel, booking friction, itineraries, and booking workflows instead. In a content-generation skill, this kind of semantic mismatch is a real integrity issue because it can mislead downstream users, produce unfit publish-ready output, and undermine trust in generated recommendations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file repeatedly mixes an industrial equipment topic with unrelated travel/booking phrasing, creating a misleading instruction and content mismatch across most of the document. In this skill context, that is dangerous because the skill is meant to generate publish-ready articles; malformed cross-domain text can cause factual inaccuracy, brand harm, and unsafe reliance on low-quality automated output.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest says this skill is specifically for turning Dageno GEO opportunities into a backlog and then writing one publish-ready article from a selected fanout item, and explicitly distinguishes that from broad keyword-first SEO content generation. This file is a standalone article about "Top Rated Travel Apps" with no Dageno opportunity context, no backlog-row/fanout linkage, and no evidence it was derived from the described GEO workflow, so the documented example behavior exceeds the manifest's claimed scope.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · examples/daily-wordpress-batch-trip/best-travel-booking-apps-in-one-place.md (reported line 36)May include surrounding context.

md
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · examples/daily-wordpress-batch-trip/common-mistakes-people-make-when-choosing-travel-apps.md (reported line 36)May include surrounding context.

md
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · examples/daily-wordpress-batch-trip/how-to-choose-a-travel-booking-app-that-actually-saves-time.md (reported line 36)May include surrounding context.

md
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · examples/daily-wordpress-batch-trip/travel-booking-apps-compared-which-one-fits-your-trip-style.md (reported line 36)May include surrounding context.

md
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · examples/publish-ready-trip-article.md (reported line 36)May include surrounding context.

md
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · src/geo_content_writer/workflows.py (reported line 1661)May include surrounding context.

python
Example: A traveler comparing apps may find that one app has great hotel inventory but weak flight filters, while another handles both in one flow and saves time immediately.

Common pitfall: Choosing based on app-store popularity without checking whether the workflow actually fits how you book trips.

## How to Compare Travel Booking Apps Without Wasting Time

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The pipeline explicitly includes a step to publish to WordPress, which is an external side effect that can modify live content. Without an explicit confirmation gate, environment scoping, or warning that publication may affect a production site, an agent could perform unintended live changes or publish inaccurate content automatically.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.