首页
/ ECC 的 Swift 安全规则:解析 .cursor/rules/swift-security.md 如何为 Swift 项目建立密钥、传输与输入三道防线

ECC 的 Swift 安全规则:解析 .cursor/rules/swift-security.md 如何为 Swift 项目建立密钥、传输与输入三道防线

2026-09-06 21:18:06作者:平淮齐Percy

在 ECC 仓库中,.cursor/rules/swift-security.md 是一份面向 Cursor 环境的 Swift 安全规则文件,它在通用安全基线之上补充了 Swift 平台特有的密钥管理、传输安全与输入校验约束。本文以该文件为核心,逐条拆解其三大安全主题,并结合仓库中配套的通用安全规则(rules/common/security.md)、Swift 规则包与安装机制,说明这些规则如何在 Agent 辅助开发流程中落地,帮助你在 Swift/Swift Package 项目中建立可执行的安全基线。

规则文件本身:Cursor 规则的 Frontmatter 与生效条件

.cursor/rules/swift-security.md 文件头部的 Frontmatter 定义了它在 Cursor 中的行为方式:

description: "Swift security extending common rules"
globs: ["**/*.swift", "**/Package.swift"]
alwaysApply: false

三个字段的作用:

  • description:声明该规则"扩展通用规则"(extending common rules),提示其定位是增量补充而非独立基线;
  • globs**/*.swift**/Package.swift 表明该规则仅在编辑 Swift 源码文件或 SwiftPM 清单时被匹配注入,不会污染其他语言项目;
  • alwaysApply: false:该规则不会被无条件加载到每个上下文,而是按文件类型惰性生效,从而控制 Agent 的上下文开销。

文件正文第一行即明确其与通用规则的关系:

This file extends the common security rule with Swift specific content.

这一"扩展"关系在仓库中有对应的通用层实现,即 通用安全规则。该通用规则(在 .cursor 下对应 .cursor/rules/common-security.md,且 alwaysApply: true 常驻生效)规定了三条对所有语言生效的基线:

  1. 强制安全检查清单(Mandatory Security Checks):任何 commit 前必须确认——无硬编码密钥、所有用户输入已校验、SQL 注入防护(参数化查询)、XSS 防护(HTML 消毒)、CSRF 防护开启、认证/授权已验证、所有端点有速率限制、错误信息不泄露敏感数据;
  2. 密钥管理:永远不在源码中硬编码密钥,始终使用环境变量或密钥管理器,并在启动时校验必需密钥存在,任何可能泄露的密钥必须轮换;
  3. 安全响应协议(Security Response Protocol):发现安全问题时立即停止,调用 security-reviewer agent 介入,先修复 CRITICAL 级问题再继续,轮换已暴露密钥,并排查整个代码库中的同类问题。

.cursor/rules/swift-security.md 的价值正在于:它把上述语言无关的"原则"翻译成 Swift 平台的具体技术手段。仓库中同样存在一份面向 Claude Code 规则体系的对应文件 rules/swift/security.md,内容与 .cursor 版本一致,仅 Frontmatter 使用 paths 字段而非 globs 字段——说明 ECC 对同一套 Swift 安全约束在多个 Agent 宿主(Cursor、Claude Code)下做了格式适配。按照 rules/README.md 的层级设计,语言特定规则与通用规则冲突时,语言特定规则优先(specific overrides general)。

密钥管理:Keychain、环境变量与启动校验

规则原文的 Secret Management 一节给出三条 Swift 特有约束:

  • 敏感数据(tokens、passwords、keys)必须使用 Keychain Services——永远不要使用 UserDefaults
  • 构建期密钥(build-time secrets)使用环境变量或 .xcconfig 文件;
  • 永远不要在源码中硬编码密钥——反编译工具可以轻易将其提取出来。

为什么 UserDefaults 不适合存密钥

UserDefaults 的数据落在沙盒内的 Library/Preference plist 中,未加密、可被同设备的工具链与备份直接读取;而 Keychain Services 由操作系统级安全子系统托管,支持按 keychain 条目粒度设置访问控制(access control)与保护级别(如"设备解锁后且应用运行时可访问")。对于 token、密码、对称密钥这类凭据,Keychain 是 iOS/macOS 平台上的标准落点。

硬编码密钥为何在 Swift 二进制中"裸奔"

规则特别强调"decompilation tools extract them trivially"(反编译工具可轻易提取)。这一点在 Swift 项目中成立:编译后的二进制保留字符串常量与符号信息,攻击者无需完整反编译即可用字符串搜索定位硬编码的 API key。因此 ECC 的规则要求把密钥移出版本控制,落到环境变量或 .xcconfig

规则给出的标准代码:从环境读取并启动即校验

let apiKey = ProcessInfo.processInfo.environment["API_KEY"]
guard let apiKey, !apiKey.isEmpty else {
    fatalError("API_KEY not configured")
}

这段代码体现了通用规则"Validate that required secrets are present at startup"的 Swift 实现方式:

  • ProcessInfo.processInfo.environment 是 Swift 读取进程环境变量的标准入口,适用于命令行工具与通过 Xcode 运行配置/CI 注入环境变量的场景;
  • guard let apiKey, !apiKey.isEmpty 采用 Swift 5.7+ 的省略类型 guard let 写法,同时校验"存在"与"非空"两个条件——避免拿到空字符串后在后续网络请求中才失败;
  • 缺失时直接 fatalError 快速失败(fail fast),而不是带着未配置的密钥继续运行产生难以排查的运行时错误。

对 App 工程而言,对应的构建期注入渠道是 .xcconfig:将 API_KEY 等值写入配置片段,通过 Build Settings 的预处理器宏传递,既避免密钥进入源码文件,又保留"不同构建配置使用不同密钥"的灵活性。

与通用清单的对应关系

对照 通用安全规则 的 commit 前清单第一条 "No hardcoded secrets (API keys, passwords, tokens)",Swift 规则把它具体化为三个可检查的点:运行时密钥走 Keychain、构建期密钥走环境变量/.xcconfig、源码中零字面量密钥。Agent 在提交前扫描 Swift 文件时,这三条就是判定依据。

传输安全:ATS 默认强制、证书固定与证书校验

Transport Security 一节只有三条,但每条都指向 iOS/macOS 网络栈的关键防线:

  • App Transport Security (ATS) 默认强制——不要禁用
  • 对关键端点使用证书固定(certificate pinning)
  • 校验所有服务器证书

ATS 是平台默认防线

ATS 自 iOS 10 起默认开启,强制 HTTPS、最低 TLS 版本与证书链校验,可防止中间人攻击和明文流量嗅探。"do not disable it" 对应的是 Info.plist 中的 NSAppTransportSecurity 字典:向其中添加 NSAllowsArbitraryLoads = true(或按域配置的 exception)都会削弱默认保护。ECC 规则的立场很明确——除非有无法升级的遗留内网服务,不应通过 ATS exception 关闭校验;即便临时使用,也应收窄到具体域并规划退出路径。

证书固定适用于关键端点

"Use certificate pinning for critical endpoints" 的限定词 "critical" 值得注意:证书固定(将服务端证书或公钥指纹写入客户端,在 TLS 握手后比对)能抵御"证书被信任的 CA 误发/私钥泄露"这类攻击,但代价是证书续期后必须随版本更新。因此规则建议只对支付、登录等关键链路启用固定,而非全局铺开。在 Swift 中,这一能力通常通过实现 URLSession 的委托方法(在 didReceive challenge 中比对固定指纹)来完成。

所有服务器证书都要校验

第三条要求与 ATS 形成互补:ATS 校验"证书由可信 CA 签发",而"validate all server certificates" 强调任何自行实现的 TLS 握手路径(例如直接基于 Security 框架的连接)都不应跳过验证链、有效期与主机名匹配——关闭任一项都会使连接退化为可被中间人劫持的"加密隧道"。

输入校验:显示前消毒、URL 安全构造与外部数据源

Input Validation 一节覆盖三条:

  • 所有用户输入在显示前消毒,防止注入;
  • 使用带校验的 URL(string:) 而非强制解包;
  • 来自外部来源(APIs、deep links、pasteboard)的数据在处理前必须校验。

显示前消毒防止注入

在 SwiftUI/UIKit 中直接渲染用户输入时,若输入包含可被解释的标记(如 HTML 片段、格式化占位符),就可能造成界面注入甚至后续逻辑注入。规则的落点是:渲染前统一消毒(strip/escape 不可信标记),与通用清单中的 XSS prevention(sanitized HTML)一一对应,只是平台从 Web 换到了 Swift 界面层。

URL(string:) 而非强制解包

URL(string:) 的初始化器返回可选值——非法的 URL 字符串(包含空格、未编码的保留字符等)会得到 nil。ECC 规则要求对结果做校验处理,而不是 URL(string: raw)! 强解包:后者会把"构造非法输入"这一可预期分支变成崩溃点,在解析 deep link 或用户粘贴的链接时尤其危险。安全的写法是先 guard 解包,再校验 scheme/host 白名单后才进入业务处理。

外部数据源三件套:API、deep link、pasteboard

规则点名了三类不可信数据入口:

  1. API 响应:即使服务端可信,传输层之外的数据仍可能被篡改或字段缺失,反序列化前应校验结构(Codable 解码失败即拒绝)与取值范围;
  2. Deep links:外部 App 可以构造任意 URL 唤起你的 App,onOpenURL/openURL 回调里的参数应视为攻击者可控输入——校验 scheme、host、路径与参数白名单后再路由;
  3. Pasteboard(剪贴板):系统剪贴板是跨 App 共享的,前一个 App 写入的内容随时可能被你读到,对其中携带的凭据类数据(如一次性验证码、token)在使用前同样要按"外部输入"处理,并且注意读取的隐私成本。

规则如何被 ECC 的规则体系激活与安装

理解了单条规则的内容之后,它在 ECC 中的生效方式也值得说明。仓库维护了两套同源的规则目录:

  • Cursor 侧.cursor/rules/ 下以 swift-security.mdcommon-security.md 等扁平文件名存放,Frontmatter 使用 globs/alwaysApply 字段;
  • Claude Code 侧rules/ 下按 common/ 与各语言子目录(swift/python/ 等)分层组织,Frontmatter 使用 paths 字段。

rules/README.md 给出两种安装方式:

  1. 安装脚本(推荐)./install.sh swift 一次性安装 common + Swift 规则集,也可 ./install.sh typescript python 批量安装多语言;
  2. 手动安装mkdir -p ~/.claude/rules/ecc 后分别 cp -r rules/commoncp -r rules/swift 到该命名空间。README 特别提醒要整目录复制、不要用 /* 扁平化,因为各语言目录内存在与 common 同名的文件(如 security.md),扁平化会相互覆盖,并破坏语言文件里 ../common/ 的相对引用。

Swift 规则包本身由五个文件构成(见 rules/swift/):coding-style.mdtesting.mdpatterns.mdhooks.md 与本文聚焦的 security.md。其中 rules/swift/patterns.md 强调协议导向设计与 actor 隔离共享可变状态,rules/swift/testing.md 指定使用 Swift Testing(@Test/#expect)——这些与安全规则共同构成"改代码按 patterns 写、提交前按 security 查、验证靠 testing"的闭环。

此外,scripts/sync-ecc-to-codex.sh 中定义了 CURSOR_RULES_DIR="$REPO_ROOT/.cursor/rules",说明 .cursor/rules 目录还会被同步脚本读取并转换为 Codex CLI 的规则提示,即这份 Swift 安全规则实际上可以分发到 ECC 支持的多个 Agent 宿主,而不仅限于 Cursor。

小结:一条 Swift 安全规则的完整检查路径

综合 .cursor/rules/swift-security.md 与它扩展的通用规则,Swift 项目在 ECC 流程中的安全检查路径可以归纳为:

主题 通用层(common-security) Swift 层(swift-security)
密钥 不硬编码;启动校验;泄露即轮换 Keychain 存运行时密钥;环境变量/.xcconfig 存构建期密钥;ProcessInfo.environment + guard + fatalError 启动校验
传输 错误信息不泄露敏感数据(通用面) ATS 不关闭;关键端点证书固定;全量校验服务器证书
输入 所有用户输入已校验;XSS 防护 显示前消毒;URL(string:) 校验解包;API/deep link/pasteboard 数据先验证后处理
响应 停止 → security-reviewer agent → 先修 CRITICAL → 轮换密钥 → 全库排查 继承通用协议,无额外覆盖

这套"common 定原则、language 给手段、globs/paths 控生效范围"的分层设计,让安全约束既保持跨语言一致,又能在 Swift 文件被编辑时精准注入平台化的落地方案。

登录后查看全文
热门项目推荐
相关项目推荐