Skip to content

Repository files navigation

MoonCSP

MoonBit 的 Content-Security-Policy 解析、序列化与请求判定库。

功能

  • 解析 default-srcscript-srcstyle-srcimg-src*-src 指令
  • 源表达式:'self''none''unsafe-inline''nonce-*''sha256-*'、scheme、host、通配符
  • 规范化 to_string
  • 请求检查:default-src 回退、nonce/hash、'strict-dynamic'

安装与构建

moon check --target wasm-gc --deny-warn
moon test --target wasm-gc

可运行示例:cmd/demo

三个示例

示例 1:网关转发图片

反向代理解析响应头后,判断 CDN 图片是否允许。

let policy = @mooncsp.parse(
  "default-src 'self'; img-src https: cdn.example.com",
).unwrap()
let req = @mooncsp.request(
  "img",
  "https://cdn.example.com/a.png",
  "https://app.test",
  None,
  None,
)
// decide = "allow"
let decision = @mooncsp.decide(policy, req)

同策略下,kind=script 且 URL 为 https://evil.test/x.js 时得到 csp.blocked

示例 2:构建流水线校验脚本 nonce

内联脚本必须带匹配 nonce;存在 'strict-dynamic' 时,缺少 nonce 不能靠 host 放行。

let policy = @mooncsp.parse(
  "script-src 'self' 'strict-dynamic' 'nonce-n1'",
).unwrap()
let ok = @mooncsp.request(
  "script",
  "https://evil.test/x.js",
  "https://app.test",
  Some("n1"),
  None,
)
// decide = "allow"
let allowed = @mooncsp.decide(policy, ok)

let missing = @mooncsp.request(
  "script",
  "https://app.test/app.js",
  "https://app.test",
  None,
  None,
)
// decide = "csp.strict-dynamic"
let blocked = @mooncsp.decide(policy, missing)

示例 3:测试夹具断言样式被 'none' 拒绝

安全测试解析 style-src 'none',确认外链 CSS 不会被允许。

let policy = @mooncsp.parse("style-src 'none'").unwrap()
let req = @mooncsp.request(
  "style",
  "https://app.test/a.css",
  "https://app.test",
  None,
  None,
)
// allows = false,decide = "csp.none"
let allowed = policy.allows(req)
let code = @mooncsp.decide(policy, req)

更完整的走读见 examples/gateway.md

边界

本库不是浏览器、HTML 解析器、nonce 生成器,也不实现完整的 CSP Level 3 上报管道。调用方需自行提供 origin、nonce 和已计算的 sha256。

许可证

MIT

About

Parse, serialize, and check Content-Security-Policy headers in MoonBit

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages