T09 · Insecure Skill Coding Practices
- Location
references/troubleshooting.md:160- Finding
Authenticated requests may disable TLS certificate verification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a disclosed WordPress publishing helper, but users should treat its live publishing, credential handling, and insecure troubleshooting examples carefully.
Install only if you intend to let an agent create or update content on a WordPress site. Use a dedicated low-privilege WordPress account, keep posts as drafts until reviewed, confirm the exact WP_URL before writes, do not put real passwords directly in shell commands, and avoid copying the verify=False or wildcard credentialed CORS troubleshooting examples into any real environment.
references/troubleshooting.md:160Authenticated requests may disable TLS certificate verification
scripts/block_generator.py:118Markdown input is inserted into Gutenberg HTML without contextual escaping or URL validation
\1', text)
# Links: [text](url)
text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1', text)
return text
```
```python
heading_html = f'{text}'
if anchor:
heading_html = f'{text}'
```
```python
list_html = f'<{list_tag}>\n'
for item in items:
list_html += f' {code}{code}references/troubleshooting.md:142Troubleshooting guidance recommends unsafe credentialed CORS headers
The code’s actual purpose is narrower than the declared description. It only parses markdown/text and emits Gutenberg block markup for paragraphs, headings, lists, code blocks, quotes, images, separators, groups, columns, and inline markdown conversion. While this does align with the 'Gutenberg block serialization' portion of the description, it does not implement the central claimed capabilities of managing WordPress posts through the REST API. Because the declared purpose emphasizes end-to-end WordPress publishing automation and the code only provides content formatting/serialization, this is a material description-behavior mismatch.
The declared description centers on automating WordPress post publishing and management through the REST API, including post creation/editing, publishing workflows, taxonomy assignment, featured images, and Gutenberg block handling. The supplied code instead focuses on uploading and updating media assets in the WordPress media library. While it does interact with WordPress over the REST API and includes a small Gutenberg-related convenience feature (example image block snippets in a generated report), its primary purpose is materially different: media upload/metadata management, not post lifecycle automation. This is a substantive description-behavior mismatch rather than a minor omission.
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
# Create block comment
attrs_json = json.dumps(attrs) if attrs else ''
block_comment = f'<!-- wp:{block_name} {attrs_json} -->'
block_html.append(f'{block_comment}{inner_html}<!-- /wp:{block_name} -->')
content = '\n\n'.join(block_html)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
Delete post
DELETE /posts/{id}
Add ?force=true to bypass trash.
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
Each block is wrapped in HTML comments:
<!-- wp:block-name {json_attributes} -->
Block content (HTML)
<!-- /wp:block-name -->
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<!-- wp:preformatted -->
<pre class="wp-block-preformatted">This text
preserves
whitespace
The skill documents code that reads environment variables, local files, and performs network requests, but it does not declare any tool scope or permissions boundary. In an agent setting, this can cause the skill to be invoked with broader capabilities than users expect, increasing the chance of unintended credential access, file access, or remote modification of a WordPress site.
The skill provides instructions for creating posts, uploading media, and publishing drafts without clearly warning that these are live write operations that can modify production content and make content public. In an autonomous or semi-autonomous agent workflow, that missing warning increases the risk of accidental defacement, premature publication, or unauthorized content changes.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
password = "password"
# Get token
resp = requests.post(f"{wp_url}/wp-json/jwt-auth/v1/token",
json={"username": username, "password": password})
token = resp.json()['token']
This function sends post content to a remote WordPress API and can create content on an external system. In the context of an agent skill, outbound write operations are security-relevant because they can publish sensitive, incorrect, or policy-violating content if invoked without strong confirmation and target validation.
def create_post(post_data):
"""Create new WordPress post."""
response = requests.post(f"{wp_url}/wp-json/wp/v2/posts",
json=post_data, auth=auth)
return response.json()
This call changes a post's status to publish, which can immediately make content publicly visible on a live site. In agent environments, publish actions are higher risk than ordinary API calls because a mistaken invocation can cause reputational damage, leak sensitive information, or violate change-control requirements.
def publish_post(post_id):
"""Publish a draft post."""
response = requests.post(f"{wp_url}/wp-json/wp/v2/posts/{post_id}",
json={"status": "publish"}, auth=auth)
return response.json()
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if categories:
return categories[0]['id']
else:
new_cat = requests.post(f"{wp_url}/wp-json/wp/v2/categories",
json={"name": name, "slug": slug or name.lower()},
auth=auth).json()
return new_cat['id']
The curl example demonstrates passing the application password directly on the command line, which can expose credentials through shell history, process listings, or logs. Even though the secret is redacted in the example, modeling this pattern encourages insecure operational handling of credentials.
# Using curl with Application Password
curl -X POST https://your-site.com/wp-json/wp/v2/posts \
-u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \
-H "Content-Type: application/json" \
This markdown file describes deleting posts and explicitly notes that ?force=true bypasses trash, but it does not warn users that this can permanently remove content. For markdown files, SQP-2 applies when descriptions omit warnings about behaviors that could affect user data or system integrity.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
https://public-api.wordpress.com/wp/v2/sites/{site_id}/# Create post with Application Password
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl to test:
curl -X POST https://site.com/wp-json/jwt-auth/v1/token \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}'
The CORS example sets Access-Control-Allow-Origin: * while also allowing credentialed requests, which encourages an unsafe cross-origin configuration. In a WordPress API publishing skill that handles authenticated content operations, this can expose authenticated endpoints to abuse from arbitrary origins or lead users to deploy an overly permissive policy that weakens browser-based protections.
The guide presents disabling certificate verification as a troubleshooting step, which is an unsafe security decision delegated to the user without sufficient guardrails. In an automation context that performs authenticated WordPress actions, this can cause clients to accept spoofed servers and leak credentials or publish content through a tampered connection.
Problem: Certificate verification fails.
Solutions:
# Python requests
requests.post(url, auth=auth, verify=False)
The troubleshooting guide recommends disabling TLS certificate verification and using HTTP for development without a strong warning about the security consequences. Even though marked 'not recommended for production,' this normalizes insecure transport practices that can enable man-in-the-middle attacks, credential theft, and tampering during testing or accidental reuse in higher environments.
verify=False disables TLS certificate validation, creating an unsafe default troubleshooting pattern that users may copy directly into production scripts. For a skill handling WordPress authentication and publishing, that exposes credentials, tokens, and content operations to interception and manipulation by attackers on the network path.
# Python requests
requests.post(url, auth=auth, verify=False)
The manifest describes a skill for creating, editing, and publishing WordPress posts with features like featured images and Gutenberg block serialization, but this file implements a separate media-uploader utility that uploads arbitrary media files, batch-imports from directories/CSV, and updates existing media metadata. Managing the media library directly is related to WordPress, but it is broader than the manifest’s declared post-centric behavior and is not mentioned in the description.
This code can transition a draft into a publicly published WordPress post as soon as publish_immediately is set, which is a potentially irreversible content-disclosure action. Although the script's overall purpose is publishing, there is no runtime confirmation prompt before making a live post public, increasing the risk of accidental publication.
Beyond interacting with the WordPress REST API, the code generates local output artifacts such as upload reports and a JSON file of uploaded media IDs. The manifest describes API-based post management features, but does not mention local file generation or persistent local bookkeeping.
No suspicious patterns detected.