← 返回博客

博客

WordPress 安全审计:上线前检查什么

用于插件安全的系统性清单 — 从 SQL 注入防护到正确的 Nonce 验证。附带自动审计报告。

在任何 PAGEnza 生成的插件到达用户 WordPress 安装之前,它会经过三个自动安全检查。这篇帖子解释了这些检查在寻找什么 — 以及为什么每一项都很重要。

为什么 AI 生成的代码需要审计

大型语言模型在编写 WordPress 插件方面非常出色。它们了解钩子名称,理解 WP 编码标准,并生成可读的 PHP。但它们也会犯可预测的错误 — 而这些错误就是安全漏洞。

我们看到的最常见的:

  • 未经清理 (sanitization) 而使用 $_GET$_POST
  • 表单提交时缺少 Nonce 验证
  • 没有 $wpdb->prepare() 的直接数据库查询
  • 使用 eval()exec() 进行动态行为
  • 未经 esc_html()esc_attr() 而输出用户数据

这些不是罕见的边缘情况。它们会定期出现在 LLM 的输出中 — 即使是最好的模型也是如此。

阶段 1:提示验证

在 AI 编写任何代码行之前,我们会分析用户的描述。此步骤会捕获两类问题:

操纵尝试 — 试图让 AI 生成恶意代码的提示。例如“忽略之前的指令”或“为测试创建一个后门”。

模糊或不可行的描述 — 对于生成有用代码来说太短或太模糊的提示。“创建一个插件”会生成垃圾;“创建一个将提交发送到带垃圾邮件过滤功能的电子邮件地址的联系表单”会生成真实的东西。

如果提示未能通过此检查,用户将看到一个解释原因的具体错误消息 — 而不是通用的拒绝。

阶段 2:在隔离容器中进行 PHP linting

一旦 AI 生成了 PHP 代码,它将在完全隔离的环境的 Docker 容器中通过 php -l 执行。这会在插件到达 WordPress 安装之前捕获语法错误。

但我们做得更多:如果 linting 失败,系统不会简单地拒绝输出。它会将错误连同修复提示一起发送回 AI — 这就是我们所说的修复 (healing)。AI 会看到自己的错误并重试,最多三次。

这意味着用户几乎从不看到“生成失败”的消息。他们看到的是稍长的生成时间 — 以及可用的代码。

阶段 3:代码安全扫描

这是最重要的阶段。我们运行静态分析,检查:

危险函数: eval(), exec(), system(), shell_exec(), passthru() — 任何一个都会阻止插件发布。

SQL 注入向量: 带插值变量的原始 $wpdb->query() 调用,缺少 $wpdb->prepare(),直接使用 mysql_query()

缺少权限检查: 在执行任何特权操作之前不调用 current_user_can() 的 AJAX 处理程序。

缺少 Nonce 验证: 不调用 wp_verify_nonce()check_ajax_referer() 的表单处理器。

未转义的输出: echo $_GET[...], 没有转义函数的 echo $user_input

如果发现任何这些问题,插件将被阻止。用户将看到一个报告,其中准确列出了哪些函数触发了阻止以及原因 — 而不仅仅是“安全检查失败”。

审计报告的样子

每个生成的插件都附带一份通俗易懂的安全审计报告。它列出了:

  • 哪些检查通过了(绿色)
  • 哪些检查触发了警告(琥珀色)— 非阻塞但值得注意的问题
  • 在修复过程中自动应用的任何更正

报告会自动生成并附加到插件下载中。它既有助于您的信心,也有助于向客户表明您认真对待安全问题。

阶段 4:保存时验证

这不属于初始生成 — 当用户在 PAGEnza 编辑器中手动编辑插件代码时适用。

每次保存时,相同的 lint + 安全扫描会再次运行。如果您在编辑过程中引入了关键漏洞,保存将被阻止,直到您修复它为止。这可以防止开发人员进行快速的“临时”更改,而该更改在生产环境中保留两年这一常见情况。

自动审计的局限性

自动扫描能很好地捕获特定类别的问​​题。它不能捕获所有内容。

逻辑错误、损坏的业务逻辑以及不涉及已知危险模式的微妙权限升级问题仍然需要人工审查。我们在文档中对此保持透明 — 审计不能替代安全审查,它是一个保证最低标准的底线。

对于处理付款或敏感数据的生产插件,我们建议在自动检查之外进行手动审查。审计报告为人工审查员提供了一个很好的起点。

Sources (5)