Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Wopdpress AI Blogger

v1.0.0

Create, edit, and publish WordPress posts via REST API with full Gutenberg block support. Use when Codex needs to automate WordPress content publishing, gene...

0· 437·4 current·4 all-time
byBogdan Chirukin@chirukinbb
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
Name/description match the included scripts: block generation, media upload, and post publishing via the WordPress REST API. The code implements the advertised features (Gutenberg serialization, media upload, categories/tags, publish workflow). However, registry metadata declares no required environment variables even though SKILL.md and the scripts clearly expect WP_URL, WP_USERNAME, WP_APPLICATION_PASSWORD (or username/password for JWT). This metadata omission is an inconsistency.
Instruction Scope
SKILL.md and the scripts remain within the stated purpose: they call WordPress REST endpoints, read files specified for upload, and serialize blocks. Some troubleshooting guidance recommends disabling SSL verification (requests.verify=False) and enabling verbose request logging; those are useful for debugging but increase risk of credential exposure if used indiscriminately. The instructions do not introduce obvious exfiltration endpoints or actions outside the WordPress domain.
Install Mechanism
No install spec (instruction-only) and no external downloads are present; risk from installation mechanism is low. The repository contains runnable Python scripts but nothing is being fetched from untrusted URLs at install time.
!
Credentials
The skill requires WordPress credentials to operate (application password or username/password) and expects a WP_URL, but the registry metadata lists no required env vars or primary credential — a mismatch that obscures the fact that secrets are necessary. The scripts also recommend logging requests (which can include sensitive info); combine this with missing metadata declaration and it increases the chance a user might hand over high-privilege credentials unknowingly.
Persistence & Privilege
Skill flags show no 'always:true' and it doesn't request permanent platform-level privileges. The scripts do file I/O for media uploads and read files the user instructs them to, but they do not attempt to modify other skills or system-wide agent settings.
What to consider before installing
This package appears to do what it says (create Gutenberg posts, upload media, manage categories/tags), but exercise caution before using it with real credentials or a production site. Key points to consider: - Registry metadata does not advertise the environment variables the scripts need (WP_URL, WP_USERNAME, WP_APPLICATION_PASSWORD). Treat that omission as a red flag: verify required variables and where they are stored before use. - Prefer creating a low-privilege WordPress account (capabilities: edit_posts, but not full admin) or use a scoped Application Password for the site instead of an admin password. - Review the included Python scripts locally before running. They perform filesystem reads (uploads) and network requests to the specified WP_URL; ensure you won't accidentally upload sensitive local files. - Avoid following the troubleshooting advice to disable SSL verification in production (verify=False) or to log full HTTP requests in environments where credentials or sensitive content might be recorded. - Test on a staging site first. Confirm behavior (what gets uploaded, what fields are set) and monitor server logs for unexpected activity. If you want higher confidence, ask the author/source for corrected registry metadata listing required env vars, or request a minimal example run showing only a safe demo against a known test site.

Like a lobster shell, security has layers — review code before you run it.

latestvk9788wz9za2t8fxm8v2xpdb2qh81z1nt

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

WordPress API with Gutenberg

Overview

This skill provides comprehensive guidance for interacting with WordPress REST API to create and manage posts using Gutenberg block editor format. It covers authentication, block serialization, media upload, and publishing workflows.

Quick Start

Before using the API, ensure you have:

  1. WordPress site with REST API enabled (default)

  2. Authentication credentials:

    • Application Password (WordPress 5.6+): Generate at /wp-admin/admin.php?page=application-passwords
    • JWT Authentication plugin installed (alternative)
    • Username/password for Basic Auth (not recommended for production)
  3. Base URL: https://your-site.com/wp-json/wp/v2

Authentication

Application Password (Recommended)

# Set environment variables
export WP_URL="https://your-site.com"
export WP_USERNAME="admin"
export WP_APPLICATION_PASSWORD="xxxx xxxx xxxx xxxx xxxx xxxx"
import requests
import os

wp_url = os.environ.get('WP_URL')
username = os.environ.get('WP_USERNAME')
password = os.environ.get('WP_APPLICATION_PASSWORD')

auth = (username, password)

JWT Authentication

If using JWT plugin, obtain token first:

import requests

wp_url = "https://your-site.com"
username = "admin"
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']

headers = {"Authorization": f"Bearer {token}"}

Creating Posts with Gutenberg Blocks

WordPress REST API expects posts in Gutenberg's serialized block format. The content field should contain block comments and HTML.

Basic Block Structure

def create_gutenberg_post(title, content_blocks):
    """
    Create a post with Gutenberg blocks.
    
    Args:
        title: Post title
        content_blocks: List of block dictionaries with 'blockName' and 'attrs'
    
    Returns:
        JSON data for POST request
    """
    # Serialize blocks to Gutenberg format
    block_html = []
    for block in content_blocks:
        block_name = block.get('blockName', 'core/paragraph')
        attrs = block.get('attrs', {})
        inner_html = block.get('innerHTML', '')
        
        # 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)
    
    return {
        "title": title,
        "content": content,
        "status": "draft",  # or "publish"
        "format": "standard"
    }

Common Block Examples

See references/common_blocks.md for detailed examples of:

  • Paragraph blocks with formatting
  • Heading blocks (h2-h4)
  • Image blocks with captions and alignment
  • List blocks (ordered/unordered)
  • Quote blocks
  • Code blocks
  • Custom HTML blocks
  • Columns and layout blocks

Complete Workflow

Step 1: Prepare Authentication

Set up credentials as environment variables or in a configuration file.

Step 2: Create Post Data

Define title, content blocks, categories, tags, featured image.

Step 3: Upload Media (if needed)

def upload_image(image_path, post_id=None):
    """Upload image to WordPress media library."""
    with open(image_path, 'rb') as f:
        files = {'file': f}
        data = {}
        if post_id:
            data['post'] = post_id
        
        response = requests.post(f"{wp_url}/wp-json/wp/v2/media",
                                 files=files, data=data, auth=auth)
        return response.json()

Step 4: Create Post

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()

Step 5: Update Status

Change from draft to publish:

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()

Advanced Features

Categories and Tags

# Get or create category
def ensure_category(name, slug=None):
    categories = requests.get(f"{wp_url}/wp-json/wp/v2/categories",
                             params={"search": name}, auth=auth).json()
    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']

Featured Image

# Upload image first, then set as featured
image_data = upload_image("path/to/image.jpg")
post_data["featured_media"] = image_data['id']

Custom Fields (ACF)

If using Advanced Custom Fields plugin:

post_data["meta"] = {
    "your_field_name": "field_value"
}

Error Handling

Always check responses:

response = requests.post(...)
if response.status_code in [200, 201]:
    print("Success!")
else:
    print(f"Error {response.status_code}: {response.text}")

Common issues:

  • 401: Authentication failed
  • 403: User lacks permission
  • 404: Endpoint not found (check WordPress version)
  • 500: Server error (check PHP error logs)

Scripts

The scripts/ directory contains helper utilities:

  • wp_publish.py: Complete publishing pipeline
  • block_generator.py: Generate Gutenberg block HTML from markdown
  • media_uploader.py: Batch upload images

References

Assets

  • templates/article_template.json: JSON template for typical article structure
  • block_samples/: Example block HTML for various content types

Example Request

# 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" \
  -d '{
    "title": "My New Post",
    "content": "<!-- wp:paragraph --><p>Hello World!</p><!-- /wp:paragraph -->",
    "status": "draft"
  }'

Files

9 total
Select a file
Select a file to preview.

Comments

Loading comments…