moonf99

给旧博客做一次安全加固:检查、修改与验证

2026/09/25

重新找回这个博客的维护方法后,我请 Codex 帮忙检查了它的安全性。本文记录这次实际完成的检查、代码修改和验证,也保留尚未处理的问题,方便以后接着维护。

这是一轮基础加固,不是一份“网站已经绝对安全”的证明。本文所述改动已在本地构建验证;远程账户设置和完整浏览器交互不在本次已验证范围内。

一、先确认网站是怎么运行的

检查公开仓库和本地工程后,确认这个网站使用 Hexo 6.3.0、Archer 主题,由 GitHub Pages 托管。公开仓库的 main 分支保存生成后的 HTML、CSS、JavaScript 和图片;本地工程还保留文章 Markdown、主题模板和配置。

维护流程因此是:修改源文件,生成静态网页,检查结果,再发布。直接修改生成目录中的 HTML,下一次构建时可能被覆盖。

本轮主要检查了以下位置:

  • package.json 和 package-lock.json:构建依赖及锁定版本。
  • _config.yml 和 _config.archer.yml:网址、主题、统计和图表配置。
  • themes/archer/layout/:页面模板与脚本引用。
  • source/ 和 public/:发布输入与生成结果。
  • .gitignore:哪些本地文件会被排除在版本管理之外。

开始修改前,备份了将要改动的配置和模板,并记录文件清单。文章内容和已有图片没有被替换。

二、降低凭证误上传的风险

检查发现,本地工程需要更明确的凭证隔离规则。此次没有在聊天或文章中展示真实密钥,也没有删除或移动原有凭证。

首先补充 .gitignore,忽略本地凭证文件、常见私钥文件以及 .env 配置。需要注意:忽略规则主要影响尚未跟踪的文件,不能清除已经提交的内容,更不能让已泄露的密钥失效。

其次新增 scripts/security-guard.js,利用 Hexo 的过滤器执行检查:

执行时机 检查目录 处理方式
before_generate source/ 检测到可疑内容就停止生成
before_deploy public/ 检测到可疑内容就停止发布

检查内容包括常见凭证文件名、私钥文本标记、部分令牌格式以及符号链接。错误信息只显示相关文件路径,不输出疑似密钥正文。

这是防止误操作的基础检查,不能识别所有秘密格式;也不能替代仓库历史审计。当前下载的公开仓库快照中,没有匹配到本次扫描覆盖的私钥或令牌格式,但没有据此推断历史上从未泄露。

三、调整前端脚本的加载方式

更新并本地加载 jQuery

主题原来引用 CDN 上的 jQuery 3.6.0,并带有一段失效的加载回退代码。本轮将其更新为 3.7.1,保存在主题的本地静态资源目录中,由网站自身提供。

相关修改位于 layout.ejs、base-head.ejs 和 source/lib/jquery.min.js。这样可以减少对第三方脚本地址的运行时依赖,也移除了不可靠的回退逻辑。

为 Fancybox 加入完整性校验

图片查看组件暂时保留固定版本 Fancybox 3.5.7。下载对应脚本后计算 SHA-384 摘要,并在脚本标签上添加 integrity 和 crossorigin="anonymous"。

浏览器会校验拿到的脚本是否符合指定摘要。以后如果升级文件,必须同步更新摘要。

完整性校验防的是脚本内容被替换,不是库本身的漏洞。因此不能把这一步当成 Fancybox 已完成安全升级。

停用暂时不用的脚本

本轮关闭了不蒜子访问统计,页面不再显示访问计数,也不再加载对应统计脚本。

检查现有 Markdown 后,未发现 Mermaid 图表代码块或对应 HTML 标记,因此关闭了主题中旧版 Mermaid 的前端加载。构建插件依赖没有随之卸载;将来需要图表时,应先升级和验证,再恢复功能。

四、补充浏览器侧的基础保护

在公共页面头部加入以下 Content Security Policy:

1
object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests

它限制对象嵌入、页面基准地址和表单提交目标,并要求浏览器升级可适用的不安全资源请求。

这只是基础 CSP,没有设置严格的 script-src,也没有解决旧主题所有内联脚本和事件处理方式,不能宣称全面阻断了 XSS。通过 HTML 元标签设置 CSP 也不等同于控制所有服务器响应头。

同时新增:

1
<meta name="referrer" content="strict-origin-when-cross-origin">

对打开新窗口的链接,统一保留原有 rel 值并补充 noopener noreferrer,降低新页面访问来源窗口的风险,并减少该链接向目标发送来源信息。

五、修正元信息和网址配置

原站点配置还使用示例网址。本轮将其修正为:

1
url: https://moonf99.github.io

主题中的知识共享许可链接也改为 HTTPS。

另外,页面 HTML 元信息改用转义输出;site-meta.ejs 中的配置值通过 JSON 序列化,并转义可能影响脚本边界的字符。这样可以避免带特殊字符的配置意外破坏 HTML 属性或内联脚本结构。

六、实际做了哪些验证

完成首轮修改后,在博客工程中运行:

1
npm.cmd run build

构建成功。添加本文之前,对生成的 20 个 HTML 页面执行了自动检查:

  • 所有页面包含基础 CSP。
  • 新窗口链接均具备相应的外链保护。
  • HTTPS 外部脚本包含完整性校验属性。
  • 页面不再加载旧统计脚本和 Mermaid 脚本。
  • 页面不再引用原来的示例站点网址。

还执行了针对性的行为测试:使用虚构的私钥标记和测试 .env 文件,确认检查能阻止生成或发布;实际源文件和生成目录通过扫描。测试中的凭证内容均为虚构数据,不包含真实密钥。

对脚本配置转义,使用包含脚本结束标签的测试字符串验证:渲染结果不会直接插入危险标签,JavaScript 读取后的配置值仍与输入一致。

这些检查覆盖了构建结果和新增防护逻辑,没有完成整个网站在浏览器中的交互回归。

七、仍然存在的问题

依赖扫描使用:

1
npm.cmd audit --omit=dev

现有锁文件共报告 30 项告警:2 项 critical、13 项 high、10 项 moderate、5 项 low。这是当时的依赖扫描结果,会随漏洞数据库和依赖版本变化。

其中包含构建工具和传递依赖,不能直接解读为静态网站存在 30 个可被访客远程利用的漏洞。但它们仍值得处理,特别是构建时会读取不可信内容的工具。

本轮没有直接跨大版本升级 Hexo 和所有插件。下一步应在独立副本中升级、构建和检查旧主题,避免一次性升级导致图片、样式或文章渲染失效。

还需要继续处理:

  • 检查旧前端组件是否应替换,而不只依靠完整性校验。
  • 改造内联脚本后,逐步收紧 CSP。
  • 检查 GitHub 账户二步验证、仓库访问权限及 Pages 的强制 HTTPS 设置。
  • 另行检查历史提交是否包含敏感信息;如确认泄露,应撤销并轮换对应凭证。

这些账户配置和凭证轮换并未在本次操作中完成。

八、以后怎样维护

修改文章后先构建、预览,确认正常后再运行发布命令:

1
2
npm.cmd run build
npm.cmd run server

在本地浏览器检查页面。结束预览后,再按需要执行:

1
npm.cmd run deploy

新增的发布检查会在 Hexo 发布流程中运行。应继续使用正确的发布流程,避免把整个本地工程直接当作静态站点上传。

配置和模板的修改均保留了备份。如果需要回滚,恢复相应原文件、移除新增检查脚本,再重新生成。备份和凭证应保存在发布目录之外。

参考资料

本文根据 Codex 在本项目中的实际操作记录整理。

CATALOG
  1. 1. 一、先确认网站是怎么运行的
  2. 2. 二、降低凭证误上传的风险
  3. 3. 三、调整前端脚本的加载方式
    1. 3.1. 更新并本地加载 jQuery
    2. 3.2. 为 Fancybox 加入完整性校验
    3. 3.3. 停用暂时不用的脚本
  4. 4. 四、补充浏览器侧的基础保护
  5. 5. 五、修正元信息和网址配置
  6. 6. 六、实际做了哪些验证
  7. 7. 七、仍然存在的问题
  8. 8. 八、以后怎样维护
  9. 9. 参考资料