AI TOOLS

EP09. "wp-rest-api-development REST API 开发审查"

首页 AI 工具 Claude · Skills · WordPress Skills · EP09
约 19 分钟· #EP09#Claude#WordPress Skills
🔒 登录后可标记已读
  • register_rest_route() 里那个 permission_callback 参数,你是不是也图省事写过 __return_true?WP 5.5 之后这已经是强制要求,写操作漏了这一条就是 CRITICAL
  • wp-rest-api-developmentjorgerosal/wordpress-skills 这套 18 个 skill 里专门审查 WordPress REST API 的一个,覆盖路由注册、权限回调、参数校验、response 结构这几块
  • 核心原则一句话:每条路由都要有清楚的契约——明确的权限、经过校验的输入、可预期的输出,三者缺一都算问题
  • 前置知识:先看过 EP01「wp-security-review 安全审查」,两者都会碰到权限/nonce 相关的判断,REST API 用的是 permission_callback 这套模型,不是 nonce

重点内容


这个 Skill 是做什么的

wp-rest-api-development 是针对 WordPress 自定义 REST 路由的系统化审查,覆盖路由注册、controller class 设计、request 解析、schema 校验、response 格式、缓存考量、版本兼容性,报告固定带行号、严重度、对照代码示例。

适合用在:

  • 审计 register_rest_route() 的实现
  • 审查自定义 API endpoint 或 controller class
  • 检查 permission_callback 实现是否够严谨
  • 校验 WP_REST_Request 的输入处理
  • 评估 response 结构、HTTP 状态码、schema 是否对齐
  • 为 headless / block 驱动应用设计带版本号的 endpoint

不适合用在:

  • 没有 REST 焦点的通用插件架构(交给 wp-plugin-development
  • 整个插件的全面安全审查(交给 wp-security-review
  • WooCommerce 专属的 endpoint 审查(交给 wp-woocommerce-dev
  • GraphQL 相关的指导

触发方式

方式写法说明
斜线指令(完整版)/wp-rest-review [path]完整审查,结果按文件、按严重度分组
斜线指令(快速版)/wp-rest [path]只抓高风险问题,速度快
自然语言「审查这个自定义 REST endpoint」「check my register_rest_route implementation」Claude 判断意图符合就自动触发

📌 触发关键词包括 register_rest_routepermission_callbackWP_REST_RequestREST endpointAPI schemaREST controllerheadless WordPressAPI auth 等。


审查流程

  1. 识别 REST 情境:插件初始化里的路由回调、继承 WP_REST_Controller 的 controller class、headless 前端整合场景、纯后台内部 API
  2. 先检查路由注册:namespace 与版本号格式、HTTP method 是否语义对应、permission_callback 有没有出现且够具体、args 有没有定义
  3. 审查 request 处理:用 $request->get_param() 或对应类型的 getter,而不是原生 superglobal;所有用户输入都要校验/消毒;不合法输入要回 WP_Error
  4. 审查 response 设计:结构统一、状态码合适、用 rest_ensure_response()、不暴露内部实现细节
  5. 按严重度分类(见下表)
  6. 交叉引用其他 skill:权限/nonce 问题突出时建议 /wp-sec-review;牵涉更大插件架构时建议 /wp-plugin-review

按检查对象分类的坑

检查对象CRITICALWARNINGINFO
路由注册 register_rest_routepermission_callback、写操作用 __return_truenamespace 没带版本号、路由注册在 rest_api_init 之外重复出现的 inline callback 适合重构成 controller method
权限回调私有数据缺 capability 检查特权操作的回调无条件回 true、没做归属校验重复的权限逻辑可以集中处理
Request args / 校验回调里直接用 $_GET/$_POSTsanitize_callback/validate_callback、缺枚举/格式限制可复用的 item schema 能减少重复
Response 处理各 endpoint 的成功 response 结构不统一、REST 回调里用 wp_send_json()WP_REST_Response 能更好地控制 header 和状态码

快速扫描指令(rg

# CRITICAL:定位所有 register_rest_route,检查是否有 __return_true 的权限回调,以及回调里直接用了原生 superglobal
rg -n "register_rest_route\s*\(" . -g '*.php'
rg -n "permission_callback.*__return_true" . -g '*.php'
rg -n "\$_GET|\$_POST|\$_REQUEST" . -g '*.php'

# WARNING:检查有没有用校验 helper、有没有该用 REST response 却用了 wp_send_json
rg -n "WP_REST_Request|get_param\s*\(" . -g '*.php'
rg -n "wp_send_json|wp_send_json_success|wp_send_json_error" . -g '*.php'

实操示例

// ❌ CRITICAL:没写 permission_callback,等于任何人都能打这条路由
register_rest_route( 'myplugin/v1', '/settings', array(
    'methods'  => 'POST',
    'callback' => 'myplugin_save_settings',
) );

// ❌ CRITICAL:写操作用 __return_true,等于对外公开写权限
register_rest_route( 'myplugin/v1', '/settings', array(
    'methods'             => 'POST',
    'callback'            => 'myplugin_save_settings',
    'permission_callback' => '__return_true',
) );

// ✅ GOOD:写操作要有明确的 capability 检查
register_rest_route( 'myplugin/v1', '/settings', array(
    'methods'             => 'POST',
    'callback'            => 'myplugin_save_settings',
    'permission_callback' => function () {
        return current_user_can( 'manage_options' );
    },
    'args'                => array(
        'value' => array(
            'required'          => true,
            'sanitize_callback' => 'sanitize_text_field',
            'validate_callback' => function ( $param ) {
                return is_string( $param ) && strlen( $param ) <= 200;
            },
        ),
    ),
) );
// ❌ CRITICAL:回调里直接用原生 superglobal,绕过了 REST 的参数校验机制
function myplugin_save_settings() {
    update_option( 'myplugin_setting', $_POST['value'] );
    wp_send_json_success();
}

// ✅ GOOD:用 $request 取参数,回 WP_Error / rest_ensure_response
function myplugin_save_settings( WP_REST_Request $request ) {
    $value = $request->get_param( 'value' );

    if ( empty( $value ) ) {
        return new WP_Error( 'missing_value', 'value 不能为空', array( 'status' => 400 ) );
    }

    update_option( 'myplugin_setting', $value );

    return rest_ensure_response( array( 'saved' => true ) );
}

怎么安装

这个 skill 是 wordpress-skills 这个开源仓库(jorgerosal/wordpress-skills)打包的 18 个技能之一,安装一次,18 个技能一起到位,不用逐个装:

Claude Code:

方式指令适用场景
装进单个项目(推荐)git submodule add https://github.com/jorgerosal/wordpress-skills.git .claude/plugins/wordpress-skills只想在这个项目用,团队成员 clone 项目就一起有
装到自己账号git clone https://github.com/jorgerosal/wordpress-skills.git ~/.claude/plugins/wordpress-skills所有项目都能用
只装这一个 skillcp -r claude-skills/wp-rest-api-development ~/.claude/skills/只想要 REST API 审查这一个功能,不要其他 17 个

装完重启 Claude Code,进到一个 WordPress 项目里跑 /wordpress-skills:wp-rest-review 验证有没有装成功(用 marketplace/submodule 方式装的话,指令前面会带插件命名空间 wordpress-skills:;用「只装这一个 skill」的方式则不带命名空间,直接 /wp-rest-review)。

Claude Desktop / claude.ai: 走 Settings → Capabilities → Skills,上传技能文件夹(把 claude-skills/wp-rest-api-development 这个文件夹打包上传,里面要包含 SKILL.md)——跟 Claude Code 的 git submodule/marketplace 安装方式不同,Desktop 端是手动上传 UI,装好之后同样能用自然语言或 slash 指令触发。

常见错误

  • ❌ GET 端点用 __return_true 被当成漏洞——公开可读数据故意开放是常见设计,这个 skill 只把「写操作」(POST/PUT/DELETE)用 __return_true 列为 CRITICAL,读操作不算
  • permission_callback 里同时写了 current_user_can() 检查被当成多余——这正是权限回调该放的位置,不是重复检查
  • ❌ 内部专用(后台专用、只在管理员触发)的 API 也被要求跟公开 endpoint 一样严格分页/schema 复用——skill 建议按情境判断,不是所有 INFO 级建议都要照单全收
  • ❌ 把「namespace 没带版本号」直接判定 CRITICAL——官方分级里这只是 WARNING,不影响功能,只是不利于以后升级
  • 💡 wp_send_json() 系列函数在 REST 回调里能跑、也不会报错,但会绕开 REST 该有的 header/状态码控制,skill 把这个列为 WARNING 而不是 CRITICAL,别混淆严重度

Sources

官方文档:

  1. wordpress-skills(GitHub 仓库)— https://github.com/jorgerosal/wordpress-skills
  2. wp-rest-api-development SKILL.md — https://github.com/jorgerosal/wordpress-skills/blob/main/claude-skills/wp-rest-api-development/SKILL.md