This commit implements several security enhancements based on the findings of a new security audit report, which has also been added to the documentation. - **Security Headers:** Adds a strict Content-Security-Policy (CSP) and other security headers (X-Content-Type-Options, Referrer-Policy) via Nuxt route rules. - **Production Hardening:** Disables Nuxt DevTools in production environments to reduce the attack surface. - **Mixed Content:** All image assets are now loaded over HTTPS to resolve mixed content issues. - **Tabnabbing:** Secures `window.open` calls by adding `noopener,noreferrer`. - **Configuration:** Updates `.gitignore` to ignore all `.env.*` files. - **Docs:** Adds the full security audit report for reference. - **Build:** Corrects a case-sensitive import path to ensure cross-platform build compatibility.
6.7 KiB
6.7 KiB
title, description, lastUpdated
| title | description | lastUpdated |
|---|---|---|
| 安全审计报告(Tootaio Studio 网站) | 开源发布前的安全评估与加固建议与清单 | 2025-11-07 |
概览(Summary)
- 架构为 Nuxt 4 + @nuxt/content 的前端站点,无自建服务端 API/上传功能,攻击面小。若开源,整体安全风险低。
- 主要关注点:外部资源使用 HTTP、窗口打开的
opener风险、生产环境 DevTools 启用、缺少统一安全响应头、依赖冗余与未来内容来源治理。
审计范围
- 配置与依赖:
nuxt.config.ts、package.json、.env*、.gitignore。 - 前端页面与可执行逻辑:
app/下的页面、布局、可组合函数(composables)。 - 内容与多语言:
content/**.yml与i18n/**.json。 - 文档与脚本:
docs/内建议信息。
结论与优先级
- 风险等级:低-中(Low–Medium)。不存在明显的密钥泄露或远程代码执行面。
- 高价值、低成本修复项(建议开源前完成):
- 将所有外部资源统一为 HTTPS。
- 生产环境禁用 DevTools。
window.open显式使用noopener,noreferrer。- 为外链/图片增加基础协议白名单校验(http/https)。
- 通过网关或 Nitro
routeRules添加基础安全响应头与静态资源缓存策略。 - 精简未使用依赖(如未使用
better-sqlite3)。
关键发现与证据(Evidence)
-
公开运行时配置(非敏感):
nuxt.config.ts:22暴露runtimeConfig.public.whatsappNumber(按设计公开,无敏感性)。
-
DevTools 在生产可能启用:
nuxt.config.ts:14devtools: { enabled: true },建议生产禁用。
-
外链/图片使用了 HTTP(混合内容与篡改风险):
app/pages/index.vue:83-92背景图http://img.tootaio.com/...content/en-US/index.yml:25,29与content/zh-CN/index.yml:31,35项目图片使用http://。
-
外链打开策略:
app/pages/index.vue:37-38使用target="_blank"已含rel="noopener",建议补充noreferrer。app/composables/WhatsAppMsgSender.ts:11的window.open未显式noopener,noreferrer。
-
统一安全头缺失:
- 未在
nuxt.config.ts配置routeRules的安全头(可在网关/Nginx 层或 Nitro 层补充)。
- 未在
-
依赖冗余:
package.json:19引入了better-sqlite3,当前项目未使用,建议移除以降低供应链与构建复杂度。
-
非安全但会影响构建的细节:
content.config.ts:2大小写引用与实际文件名不一致(Linux 下可能报错):应从./app/schemas/PricingPlanSchema调整为./app/schemas/pricingPlanSchema。
-
环境文件治理:
.env已被.gitignore忽略(.gitignore:22),且内容仅有公开号码(.env:1)。建议继续保持从未提交到历史。
修复与加固建议(Actionable)
开源前必须(High Priority)
-
统一使用 HTTPS 资源
- 将
http://img.tootaio.com/...统一替换为https://img.tootaio.com/...。 - 建议将资源基址抽离到
runtimeConfig.public.assetBase并集中管理,减少散落硬编码。
- 将
-
生产禁用 DevTools
- 将
devtools改为:devtools: { enabled: process.env.NODE_ENV !== 'production' }。
- 将
-
window.open加固- 修改为:
window.open(url, '_blank', 'noopener,noreferrer')或在新窗口上设置opener = null。
- 修改为:
-
外链与图片的协议白名单
- 在渲染外链/图片前校验 URL 协议,只允许
http:与https:,避免javascript:、data:等危险 scheme。
- 在渲染外链/图片前校验 URL 协议,只允许
-
安全响应头(建议由网关/Nginx 配置,或用 Nitro routeRules)
- 最小集:
Content-Security-Policy(仅放行必要域名,样例见下)。X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policy(按需收紧)
- 静态资源缓存:
/_nuxt/**设置Cache-Control: public, max-age=31536000, immutable。
- 最小集:
建议完成(Medium Priority)
-
依赖精简
- 若未用到
better-sqlite3,从package.json移除并更新锁文件。
- 若未用到
-
.gitignore更严格忽略 env 变体- 将当前注释掉的
.env.*忽略规则启用,并保留示例白名单:- 忽略:
.env、.env.* - 白名单:
!.env.sample
- 忽略:
- 将当前注释掉的
-
文件名大小写一致性
content.config.ts引用改为实际文件名大小写以避免跨平台问题。
可选增强(Nice-to-have)
-
在 CI 中启用:
pnpm install --frozen-lockfile- 依赖与漏洞审计(Dependabot /
pnpm audit --prod) - Secrets 扫描(
gitleaks/trufflehog)
-
HSTS 与全站 HTTPS
- 前置网关开启 HSTS,并确保所有外链与资源均可通过 HTTPS 访问。
附录:建议配置片段
1) Nitro routeRules(示例)
// nuxt.config.ts
export default defineNuxtConfig({
// ...
routeRules: {
'/**': {
headers: {
'Content-Security-Policy': [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' https://img.tootaio.com data:",
"connect-src 'self'",
"frame-ancestors 'self'",
'upgrade-insecure-requests',
].join('; '),
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'strict-origin-when-cross-origin',
},
},
'/_nuxt/**': {
headers: { 'cache-control': 'public, max-age=31536000, immutable' },
},
},
})
请按实际依赖域名精简 CSP,特别是 img-src、connect-src。
2) window.open 安全用法(示例)
const win = window.open(url, '_blank', 'noopener,noreferrer')
// 或者:
const win = window.open(url, '_blank')
if (win) win.opener = null
3) 外链协议白名单(示意)
function isSafeHttpUrl(href: string) {
try {
const u = new URL(href)
return u.protocol === 'http:' || u.protocol === 'https:'
} catch {
return false
}
}
// 使用时:
// <UButton v-if="item.demoLink && isSafeHttpUrl(item.demoLink)" :href="item.demoLink" ... />
4) DevTools 生产禁用
export default defineNuxtConfig({
devtools: { enabled: process.env.NODE_ENV !== 'production' },
})
5) .gitignore 建议
# Local env files
.env
.env.*
!.env.sample
附注(Non-security 但建议修复)
content.config.ts:2的大小写引用问题:应改为./app/schemas/pricingPlanSchema(与实际文件名一致),避免在大小写敏感的文件系统上构建失败。
下一步
- 如需,我可以基于本报告直接提交最小化补丁(HTTPS 资源替换、
devtools切换、window.open加固、routeRules安全头、.gitignore调整、文件名大小写修复),并附上验证与回退说明。