站点头像 Amosolin · 慕阳
security signature · 实测,不是口号classification · public

这个站子的安全签名

我是一个正在备考 CISP 的写作者。这一页不是安全承诺,而是我对自己站点的实测结论——写代码的人顺手会做的事,列给你看,也欢迎你来验。

最低 TLS 1.2+ Cloudflare 自动签发 可由一条命令复核

一页读完01summary

最后核对:2026-10-11
A+传输评分
7显式安全响应头
0第三方请求
0Cookie / 追踪器

安全这件事,最实在的部分往往是"少做":少一个后端、少一个第三方、少一次数据落地,攻击面就少一大块。

已经做到的02in place

8 条
  • 没有后端:没有数据库、没有登录、没有表单提交,因此也没有可注入的接口
  • 没有第三方:0 个 CDN、0 个统计脚本、0 个字体外链,页面首屏只请求本站资源
  • 没有 Cookie、没有 localStorage 追踪,主题偏好只存在你自己的浏览器里
  • 内容真源是仓库里的 data/*.json,所有页面由构建脚本生成,发布链路只有 git push
  • 真上了 CSP:default-src 'none' 兜底,脚本样式只放同源,且一个 'unsafe-inline' 都没开——所以我把全站内联样式和两段内联脚本都拆成了文件
  • security.txt 按 RFC 9116 放在 /.well-known/,根路径 301 过去;想报漏洞,不用先猜我邮箱
  • 响应头全写在仓库的 _headers 纯文本里,一条 curl 或一条我这边的脚本就能逐项核对,不用信我自己说
  • 允许自己不被画像:Permissions-Policy 里显式关掉 browsing-topics 与 interest-cohort,并在 /.well-known/gpc.json 声明支持 Global Privacy Control——反正是真没什么可卖的

响应头03headers

来自仓库里的 _headers 文件
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: accelerometer=(), browsing-topics=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Strict-Transport-Security: max-age=15552000; includeSubDomains

HSTS:max-age=15552000(180 天,含子域,未预置 preload)。这些头不靠插件,就是仓库里一个纯文本文件,跟着提交一起走。

另有 Cross-Origin-Resource-Policy: cross-origin 单独加在 /assets/brand/*(头像、图标、社交卡片是留给别人外链引用的)。它不写进上面这份全局清单,是因为 Pages 对同名响应头是叠加而非覆盖:全局写一份、某条路径再写一份,浏览器会收到解析不了的合并值。

内容安全策略04csp

不带 unsafe-inline
Content-Security-Policy: default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self' data:;
  connect-src 'self';
  base-uri 'none';
  form-action 'none';
  frame-ancestors 'none';
  object-src 'none';
  upgrade-insecure-requests

故意不写 'unsafe-inline'——为了这条策略,我把全站最后一行内联样式、最后一段内联脚本都搬进了文件:style="" 全部换成语义工具类,主题引导与数据装配各拆成一个 .js。现在哪个页面被人塞进内联脚本,浏览器会直接拦下来。

上面按分号换了行,线上发出去的其实是同一行。

两份标准文件05well-known

RFC 9116 · W3C GPC
Contact: mailto:security@amosolin.com
Expires: 2027-10-01T00:00:00.000Z
Canonical: https://www.amosolin.com/.well-known/security.txt
Preferred-Languages: zh, en
Policy: https://www.amosolin.com/security.html

security.txt 放在 /.well-known/security.txt;/security.txt → 301 → /.well-known/security.txt,老约定的根路径不会 404。RFC 9116 那一套:位置、字段名、Expires 都在规矩里。没做的是 PGP 签名——见下面的诚实清单。

{
  "gpc": true,
  "lastUpdate": "2026-10-11"
}

上面这份在 /.well-known/gpc.json。W3C 的 Global Privacy Control:浏览器说「别卖我的数据」,站点回一句「好,而且本来也没什么可卖」。同一个意思也写在 Permissions-Policy 里——browsing-topics 和 interest-cohort 都被显式关掉了,Chrome 的隐私沙箱兴趣定向在这个站上拿不到任何画像,因为这里既没有第三方脚本,也没有可以画像的行为。

没做到的,以及为什么06not yet

诚实清单
  • security.txt 的 PGP 签名:RFC 9116 建议签,我现在只保证这份纯文本是新的、字段齐的;等密钥管理这套流程理顺再补签名
  • Subresource Integrity:站点没有任何外部资源可被投毒,等引入外部依赖时再加
  • CAA 记录:换过证书签发方一次,等证书链路稳定后再锁,避免把自己锁死
  • DNSSEC:要跨注册商交一次 DS 记录,改动窗口里解析有风险;域名刚上线,等它稳定下来再做这一步

你自己验一下07verify

不需要装任何东西

本站所有验收脚本都在公开仓库里,克隆下来直接跑:

node scripts/check-live-deep.mjs https://www.amosolin.com

它会逐条打印:HTTP→HTTPS 跳转、26 条路径的状态码、404 行为、SVG 是否被强制下载、缓存策略,以及上面那些安全响应头的逐项核对——哪一条没生效,脚本会直接标 BAD 并以非零码退出。看到的结果应该和这一页写的一致。

安全联系08contact

负责任披露
如果你在这个站上发现了问题,请发到 security@amosolin.com,写清复现步骤即可;也可以先看一眼 /.well-known/security.txt,联系方式与有效期都写在那里。我不做漏洞奖励(个人站,没什么可奖的),但会认真回信、尽快修,并在修好后如实说明。

以上是我对自己站点的实测结论,不是安全承诺;发现问题欢迎随时发邮件。