Skip to content

feat(csp): auto-inject purchase_subscription_url origin into frame-src#702

Closed
touwaeriol wants to merge 2 commits intoWei-Shaw:mainfrom
touwaeriol:feat/csp-auto-frame-src
Closed

feat(csp): auto-inject purchase_subscription_url origin into frame-src#702
touwaeriol wants to merge 2 commits intoWei-Shaw:mainfrom
touwaeriol:feat/csp-auto-frame-src

Conversation

@touwaeriol
Copy link
Contributor

背景 / Background

当管理员配置了「购买订阅」页面 URL(purchase_subscription_url)后,该 URL 所在域名需要出现在 CSP 的 frame-src 指令中,否则浏览器会拒绝加载 iframe。以往只能手动在配置文件的 SECURITY_CSP_POLICY 里写死域名,每次更换 URL 都需要改配置并重启服务。

When an admin configures a purchase_subscription_url, its origin must be present in the CSP frame-src directive, or the browser will block the iframe. Previously, the domain had to be hard-coded in SECURITY_CSP_POLICY, requiring a config change and service restart whenever the URL changed.


目的 / Purpose

让系统自动从 purchase_subscription_url 提取 origin 并注入到 frame-src,管理员修改 URL 后下一次请求即刻生效,无需重启。

Automatically extract the origin from purchase_subscription_url and inject it into frame-src. Changes take effect on the next request after the admin saves settings — no restart required.


改动内容 / Changes

后端 / Backend

  • SecurityHeaders 新增参数:增加可选的 getFrameSrc func() string 参数;每次请求时调用一次,若返回非空 origin 则用已有的 addToDirective 注入到 frame-src;传 nil 时行为与原来完全一致
  • router.go 动态缓存SetupRouter 内用 atomic.Pointer[string] 缓存支付域名 origin;启动时读一次 settings 初始化,通过 SetOnUpdateCallback 在 settings 变更时即时刷新;每次请求只做一次 atomic.Load(纯内存,纳秒级)
  • router.go 新增 extractOrigin:从原始 URL 中提取 scheme://host,解析失败或空 host 时返回 ""
  • 测试:新增三个测试用例覆盖注入、nil 跳过、空字符串跳过场景;所有原有测试调用更新为传 nil

  • SecurityHeaders new parameter: adds optional getFrameSrc func() string; called once per request, injects the returned origin into frame-src via the existing addToDirective; passing nil preserves existing behavior exactly
  • router.go dynamic cache: SetupRouter uses atomic.Pointer[string] to cache the payment origin; initialized at startup and refreshed via SetOnUpdateCallback on every settings change; each request does one atomic.Load (in-memory, nanosecond cost)
  • router.go new extractOrigin: extracts scheme://host from a raw URL, returning "" on parse error or empty host
  • Tests: three new test cases cover injection, nil skip, and empty-string skip; all existing call sites updated to pass nil

效果 / Behavior

场景 / Scenario 行为 / Behavior
未配置 purchase_subscription_url frame-src 不变 / unchanged
配置了 URL frame-src 自动追加 origin / origin auto-appended
管理员修改 URL 下一次请求即刻生效 / effective on next request
管理员清空 URL 自动移除注入 / injection removed automatically
每次请求开销 / per-request cost 一次 atomic.Load(纳秒级)/ one atomic.Load (nanosecond)

@touwaeriol
Copy link
Contributor Author

Superseded by #727, which extends this PR's CSP frame-src logic to also support custom menu pages with multi-origin deduplication. Closing in favor of the more complete PR.

@touwaeriol touwaeriol closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant