본문으로 건너뛰기
cccskills
무료GitHub에 공개

wp-security-audit

Audits WordPress plugin or theme PHP code for the most common security mistakes — missing nonce checks, capability checks, input sanitization, output escaping, unslashing, SQL preparation, AJAX nopriv exposure, file/path traversal, and unsafe redirects. Use when reviewing pull requests, before releasing a plugin, when the user asks "is this secure", or when handling code that touches $_GET / $_POST / $_REQUEST / $_COOKIE / $_FILES / $_SERVER, admin-ajax / admin-post, REST endpoints, options, user meta, custom DB queries, or file uploads.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구WordPress
설치 방법 보기

포함된 파일(2)

  • SKILL.md10.1 KB
  • reference.md10.4 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

WordPress security audit

A defensive checklist-driven review for WP plugin and theme PHP. Goal: catch the boring, repeatable mistakes that ship to production because no one ran through the basics. This is not a substitute for a real security review of cryptography, business logic, or third-party deps.

When to use this skill

Trigger this skill when ANY of the following is true:

  • The user asks for a security review, audit, or "is this safe".
  • The diff or file under discussion contains: $_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES, $_SERVER, wp_unslash, wp_verify_nonce, check_admin_referer, current_user_can, add_action( 'wp_ajax, add_action( 'admin_post, register_rest_route, $wpdb->, update_option, update_user_meta, wp_redirect, wp_safe_redirect, file_get_contents, move_uploaded_file.
  • The user is preparing a plugin for release or wp.org submission.
  • The user is reviewing a contributor's PR.

How to run the audit

Work through the Critical checks below in order. For each finding:

  1. State the file and line.
  2. Name the issue using its conventional WP terminology (e.g. "missing nonce", "unescaped output", "broken access control").
  3. Show the offending code (1–3 lines).
  4. Show the fix.
  5. Mark severity: HIGH (exploitable now), MEDIUM (exploitable under conditions), LOW (hardening / best practice).

Do NOT silently rewrite the file. Produce a report first; only edit if the user asks you to apply fixes.

Critical checks

1. Nonce verification on state-changing requests

Any handler that writes (saves option, updates meta, deletes a post, sends an email, mutates anything) must verify a nonce.

  • Forms: wp_nonce_field( 'action_name', '_wpnonce' ) → check_admin_referer( 'action_name' ) in handler.
  • AJAX: wp_create_nonce( 'action_name' ) → check_ajax_referer( 'action_name', 'nonce' ).
  • REST: rely on cookie auth + the built-in _wpnonce (wp-api nonce) for logged-in routes; for permission_callback use a real capability check.

Common mistake: verifying the nonce inside an if whose else branch still does the write. The nonce check must short-circuit.

2. Capability checks (authorization)

Authentication ≠ authorization. A logged-in subscriber is still a user.

  • Admin actions: current_user_can( 'manage_options' ) or a more specific capability (edit_posts, edit_post with object ID, manage_woocommerce etc.).
  • Object-level actions MUST pass the object ID: current_user_can( 'edit_post', $post_id ) — the ID-less form is wrong.
  • REST permission_callback must NEVER be __return_true for state-changing routes. Returning true unconditionally is the #1 plugin vulnerability pattern on wp.org.

3. Input: unslash → sanitize → validate

WordPress magically slashes superglobals. The pipeline is fixed:

$raw      = isset( $_POST['email'] ) ? wp_unslash( $_POST['email'] ) : '';
$email    = sanitize_email( $raw );
if ( ! is_email( $email ) ) { /* reject */ }
  • Missing wp_unslash before sanitization → escaped quotes leak through.
  • Wrong sanitizer for the data type. Map by intent:
    • text field: sanitize_text_field
    • textarea: sanitize_textarea_field
    • email: sanitize_email
    • URL: esc_url_raw (storage) / esc_url (output)
    • key/slug: sanitize_key, sanitize_title
    • integer: absint or (int) with range check
    • HTML allowed: wp_kses_post or wp_kses with explicit allowlist
    • file path: sanitize_file_name + realpath containment check
  • Never trust $_SERVER['HTTP_*'] headers without sanitizing; they're attacker-controlled.

4. Output escaping (XSS)

Escape at the point of output, in the right context:

  • HTML body: esc_html( $x )
  • HTML attribute: esc_attr( $x )
  • URL in href/src: esc_url( $x )
  • Inside <script> JSON: wp_json_encode( $x ), never raw concatenation
  • Translated strings with placeholders: escape the template AND the substituted value separately. esc_html__() only escapes the static template; printf( esc_html__( '%s', 'td' ), $name ) is XSS if $name contains markup. Correct form: printf( esc_html__( 'Hello, %s', 'td' ), esc_html( $name ) ).
  • Already-HTML content (post content): wp_kses_post( $x )

echo $foo; where $foo came from input or DB without escaping → XSS. This is the most common finding in plugin audits.

5. SQL: always prepare

// WRONG
$wpdb->get_results( "SELECT * FROM x WHERE id = $id" );

// RIGHT
$wpdb->get_results( $wpdb->prepare( "SELECT * FROM x WHERE id = %d", $id ) );
  • %d integers, %f floats, %s strings. Table/column names CANNOT be parameterized — validate against an allowlist before interpolating.
  • LIKE needs $wpdb->esc_like() BEFORE prepare(): $like = '%' . $wpdb->esc_like( $term ) . '%';
  • Prefer WP_Query / get_posts / get_users over raw SQL where possible.

6. AJAX endpoints

Two hooks, two meanings — confuse them and you ship a vulnerability:

  • wp_ajax_{action} — fires only for logged-in users.
  • wp_ajax_nopriv_{action} — fires for logged-out users.

Rules:

  • Register nopriv ONLY if the feature is genuinely meant for guests (e.g. public search, login form). Never copy-paste both registrations "to be safe".
  • Both handlers still need check_ajax_referer().
  • The nopriv handler must NOT perform actions that only logged-in users should do (saving prefs, accessing other users' data, etc.).
  • End with wp_send_json_success / wp_send_json_error, not echo + die.

7. admin-post and form handlers

admin_post_{action} and admin_post_nopriv_{action} follow the same rules as AJAX. Plus: redirect with wp_safe_redirect() + exit;. Never redirect with wp_redirect( $_GET['redirect_to'] ) without validating against an allowlist — that's an open-redirect.

8. REST API routes

register_rest_route( 'myplugin/v1', '/save', [
    'methods'             => 'POST',
    'callback'            => 'myplugin_save',
    'permission_callback' => function () {
        return current_user_can( 'manage_options' );
    },
    'args' => [
        'id' => [
            'required'          => true,
            'validate_callback' => 'is_numeric',
            'sanitize_callback' => 'absint',
        ],
    ],
] );

Findings to flag:

  • permission_callback missing, or __return_true on a non-public route.
  • No args schema — input is unsanitized.
  • Returning raw DB rows including sensitive columns (user_pass, user_activation_key, private meta).

9. File operations

  • Uploads: validate MIME via wp_check_filetype_and_ext(), store via wp_handle_upload(), never trust the client-provided extension or MIME.
  • Path joins with user input: after building, realpath() and check the result starts with the intended base dir. Otherwise: path traversal.
  • Never include / require a path containing user input.

10. Secrets and information disclosure

  • No API keys or DB credentials in the plugin source. Use options or constants in wp-config.php.
  • WP_DEBUG_DISPLAY should be off in prod; flag any var_dump, print_r, error_log( $sensitive ) left in handlers.
  • Don't leak stack traces, full SQL, or user enumeration via error messages ("user not found" vs "wrong password" — pick one).

11. Redirects

  • Use wp_safe_redirect() for any URL that may be influenced by input.
  • Always exit; after a redirect — execution continues otherwise.

12. Cron and background jobs

  • wp_schedule_event callbacks run with no current user. If the job performs privileged work, do not trust any "stored intent" without re-validating; treat persisted user input as untrusted.

What this skill does NOT cover

  • Cryptographic correctness (key derivation, signing schemes).
  • Business-logic flaws (race conditions, IDOR beyond capability checks).
  • Third-party library CVEs — run composer audit separately.
  • Frontend JS XSS — different skill.
  • Server / hosting hardening (file perms, disable_functions, etc.).
  • Object injection, SSRF, CSRF on GET, mass assignment, file include, mail/zip injection, timing comparison, TOCTOU races — these are covered by wp-security-deep. Run it after this one.
  • Hardcoded credentials, weak randomness for tokens, password storage, cookie flags, secrets in logs — covered by wp-security-secrets. Run it whenever auth or third-party integrations are in scope.

State this scope explicitly in the report. If the reviewed code clearly falls into one of the deeper categories above, recommend the appropriate skill in the report's footer.

Report format

# Security audit: <plugin name>
Scope: <files reviewed>
Date: <YYYY-MM-DD>

## HIGH
1. <file>:<line> — <issue>
   <code>
   Fix: <code>

## MEDIUM
...

## LOW / Hardening
...

## Out of scope
- <thing not checked>

References

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

Control a headless browser to navigate URLs, click elements, fill forms, extract content from JavaScript-rendered pages, take screenshots, and automate end-to-end web workflows.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

Review code for quality, simplicity, and maintainability. Identifies unnecessary abstractions, duplicated logic, oversized functions, missing error handling, and naming issues — then fixes them automatically before presenting the result.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

WooCommerce store operations through NV oOS Pro — product research, catalog cross-referencing, inventory lookups, and Shopify or Flowhub comparisons where integrations are configured.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nvdigitalsolutions/mcp-ai-wpoos72026년 10월 22일 업데이트

nvdigitalsolutions의 스킬 모두 보기

이 스킬의 문제 신고