跳转到正文
报告库
用途分类 / 开发辅助

Xcode Project Setup Skill 安全审计

作者说它能做什么(原文)

Safely modifies Xcode projects (.pbxproj) to add Swift Packages and link files. Use this skill whenever an iOS project needs dependencies installed (e.g. Firebase, Alamofire).

第三方安全检查结论

先别安装或运行

已检查文件
5
发现的风险
5
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。发现 2 项风险
高风险

选择 Crashlytics 时会植入一个在后续构建中运行的下载脚本

原文依据:2 处
发现了什么

当产品名包含 `FirebaseCrashlytics` 时,工具向项目加入 `/bin/sh` 构建阶段,执行 Firebase 包检出目录中的 `Crashlytics/run`。该脚本源码不在所提供材料中,因此无法从本次审计确认其完整行为。构建阶段还明确授予它读取 dSYM、可执行文件和 GoogleService plist 的输入路径。

为什么需要注意

后续构建会以开发者的本地权限运行来自所解析 Firebase SDK 的代码,并让它接触应用二进制、调试符号及配置文件。若依赖来源或解析版本遭到破坏,这会成为代码执行及敏感构建资料泄露的入口。

选择名称含 `FirebaseCrashlytics` 的产品时,工具会把一个 `/bin/sh` 构建阶段写入项目;以后构建会执行 Firebase SDK 检出目录中的 `Crashlytics/run`,并向该阶段声明 dSYM、应用可执行文件和 GoogleService plist 等输入。该脚本不在所给源码中,因此其具体网络或数据处理行为无法确认。用户可要求作者说明并固定 Firebase 依赖版本,或限制该构建阶段的输入与执行环境。

scripts/xcode_spm_setup/Sources/main.swift:43来自说明文档打开原文件
    var inputPaths = [        "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}",        "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${PRODUCT_NAME}",        "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist",        "$(TARGET_BUILD_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/GoogleService-Info.plist",        "$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)"    ]    if isUserScriptSandboxingEnabled(project: project) {        inputPaths.append("${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${PRODUCT_NAME}.debug.dylib")    }    let phase = PBXShellScriptBuildPhase(        files: [],        inputPaths: inputPaths,        outputPaths: [],        shellPath: "/bin/sh",        shellScript: "\"${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\n",        runOnlyForDeploymentPostprocessing: false
查看另外 1 个位置
scripts/xcode_spm_setup/Sources/main.swift:210来自说明文档打开原文件
        if products.contains(where: { $0.contains("FirebaseCrashlytics")}) {            print("Setting the debug format to DWARF with dSYMs")            setDwarfWithDsymDebugInformationFormat(project: pbxproj)            print("Adding the Crashlytics Run Script Build phase")            if !hasCrashlyticsRunScriptBuildPhase(project: pbxproj) {                addCrashlyticsRunScriptBuildPhase(project: pbxproj)            } else {                print("Crashlytics Run Script Build phase already exists")            }        }
中风险

所谓版本号实际是允许未来同一主版本更新的范围

原文依据:2 处
发现了什么

文档示例把参数表现为具体版本号并要求使用最新版本,但代码通过 `upToNextMajorVersion` 保存要求,而不是固定到该版本。因此后续解析可能选择尚未审核的较新次版本或补丁版本。

为什么需要注意

构建内容可能随依赖解析时间或缓存状态改变;后来发布但被破坏或不兼容的包版本可能被下载、编译并进入应用。

文档要求传入“最新版本号”,但实现将该值转换为 `.upToNextMajorVersion` 要求,而不是精确固定版本。包解析时可能采用同一主版本内更晚发布、尚未由用户审核的版本。工具自身依赖虽有 `Package.resolved` 修订固定,但这不固定它写入用户 Xcode 项目的新依赖。用户可要求支持精确版本或提交并审查项目的解析锁文件。

SKILL.md:88来自说明文档打开原文件
### **CRITICAL: Always Use Latest SDK Version**To ensure access to the latest features and security fixes, always use the mostrecent version of the Firebase iOS SDK. Check for the latest release version at[https://github.com/firebase/firebase-ios-sdk/releases](https://github.com/firebase/firebase-ios-sdk/releases).- Use the most recent version number (e.g., `11.x.y`) in your commands instead  of hardcoded placeholders.
查看另外 1 个位置
scripts/xcode_spm_setup/Sources/main.swift:151来自说明文档打开原文件
        } else {            packageRef = try rootObject.addSwiftPackage(                repositoryURL: repoURL,                 productName: products.first!,                 versionRequirement: .upToNextMajorVersion(versionRequirementString),                 targetName: target.name            )
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。发现 1 项风险
中风险

`--plist` 可把任意指定的 plist 打包进应用资源

原文依据:3 处
发现了什么

实现接受任意 plist 路径,不检查内容或是否位于项目内,然后将文件引用加入目标的 Resources 构建阶段。该参数虽用于 GoogleService 配置,但没有限制文件名或敏感字段。

为什么需要注意

如果代理或用户误传包含私钥、服务账号、内部端点或其他秘密的 plist,它可能进入构建产物并随应用分发。

`--plist` 后的路径被直接接受,源码中没有文件名、位置或内容检查;若项目中尚无同名项,它会建立引用并加入所选 target 的 Resources 构建阶段。因此,在代理或用户传入敏感 plist 时,它可能随应用资源打包。此行为需要显式使用 `--plist`,并非自动扫描文件。用户可限制为预期的 `GoogleService-Info.plist`、要求路径必须位于项目内,并在构建前检查资源清单。

scripts/xcode_spm_setup/Sources/main.swift:93来自说明文档打开原文件
        var plistPath: Path? = nil    if let plistIndex = arguments.firstIndex(of: "--plist"), plistIndex + 1 < arguments.count {        plistPath = Path(arguments[plistIndex + 1])        arguments.remove(at: plistIndex + 1)        arguments.remove(at: plistIndex)    }
查看另外 2 个位置
scripts/xcode_spm_setup/Sources/main.swift:129来自说明文档打开原文件
                        // Only add if it doesn't already exist            if groupToAddTo?.children.contains(where: { $0.path == plistPath.lastComponent || $0.name == plistPath.lastComponent }) == false {                let fileRef = try groupToAddTo?.addFile(at: plistPath, sourceRoot: projectPath.parent())                                if let fileRef = fileRef, let buildPhase = target.buildPhases.first(where: { $0.buildPhase == .resources }) as? PBXResourcesBuildPhase {                    _ = try buildPhase.add(file: fileRef)                    print("Successfully added \(plistPath.lastComponent) to resources build phase.")                }
scripts/xcode_spm_setup/Sources/main.swift:121来自说明文档打开原文件
                // 1. Add Plist to the project (Optional)        if let plistPath = plistPath {            print("Adding \(plistPath.lastComponent) to project...")            let mainGroup = rootObject.mainGroup                        let appName = target.name            let groupToAddTo = mainGroup?.children.first(where: { $0.path == appName }) as? PBXGroup ?? mainGroup                        // Only add if it doesn't already exist            if groupToAddTo?.children.contains(where: { $0.path == plistPath.lastComponent || $0.name == plistPath.lastComponent }) == false {                let fileRef = try groupToAddTo?.addFile(at: plistPath, sourceRoot: projectPath.parent())                                if let fileRef = fileRef, let buildPhase = target.buildPhases.first(where: { $0.buildPhase == .resources }) as? PBXResourcesBuildPhase {                    _ = try buildPhase.add(file: fileRef)                    print("Successfully added \(plistPath.lastComponent) to resources build phase.")                }
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。发现 1 项风险
中风险

所有更改都静默应用到项目中的第一个原生 target

原文依据:5 处
发现了什么

命令没有 target 参数,也不按用户指定名称选择 target;实现直接采用 `nativeTargets.first`。依赖、产品链接和 Firebase 构建设置随后都应用到该 target。

为什么需要注意

在含扩展、测试、多个应用或排序不同的项目中,工具可能永久修改错误的 target,使错误组件获得 SDK、链接标志或构建脚本,并可能导致构建失败或意外的数据收集。

命令接口没有 target 参数,代码直接选择 `nativeTargets.first`,随后把包依赖、产品和构建设置应用到它。文档称其为“main target”,但没有证明第一个 target 就是用户想修改的主应用;多 target 项目可能被改错。操作并非完全静默,因为程序会打印进度。用户可要求作者增加明确的 target 选择和修改前预览。

scripts/xcode_spm_setup/Sources/main.swift:116来自说明文档打开原文件
                guard let target = pbxproj.nativeTargets.first else {            print("Error: No native targets found")            exit(1)        }        
查看另外 4 个位置
scripts/xcode_spm_setup/Sources/main.swift:151来自说明文档打开原文件
        } else {            packageRef = try rootObject.addSwiftPackage(                repositoryURL: repoURL,                 productName: products.first!,                 versionRequirement: .upToNextMajorVersion(versionRequirementString),                 targetName: target.name            )        }
scripts/xcode_spm_setup/Sources/main.swift:176来自说明文档打开原文件
                        let dependency = XCSwiftPackageProductDependency(productName: product, package: packageRef)            pbxproj.add(object: dependency)                        if target.packageProductDependencies == nil { target.packageProductDependencies = [] }            target.packageProductDependencies?.append(dependency)                        let buildFile = PBXBuildFile(product: dependency)            pbxproj.add(object: buildFile)                        if frameworksBuildPhase?.files == nil { frameworksBuildPhase?.files = [] }            frameworksBuildPhase?.files?.append(buildFile)        }
SKILL.md:107来自说明文档打开原文件
**The provided `xcode_spm_setup` Swift script automatically handles BOTH ofthese steps for you.** By passing the list of modules as arguments, it safelyinjects the package dependency and automatically wires those modules to the maintarget's Frameworks build phase. You do not need to do any manual linking.
scripts/xcode_spm_setup/Sources/main.swift:81来自说明文档打开原文件
func main() {    let args = CommandLine.arguments    guard args.count >= 5 else {        print("Usage: swift run --package-path <path> xcode_spm_setup <Path/To/Project.xcodeproj> <RepoURL> <VersionRequirement> [--plist <Path/To/Plist>] <Product1> [Product2 ...]")        exit(1)
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。未发现风险
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。发现 1 项风险
低风险

技能用虚构费用威胁来影响代理遵从

原文依据:1 处
发现了什么

实时说明声称违反其规则将收取“巨额费用”,但未提供收费主体、合同或用户授权。这与 Xcode 配置的技术需要无关,是针对执行代理的施压语言。

为什么需要注意

代理可能因为该威胁而拒绝用户允许的安全方案、夸大某些规则的优先级,或在缺少技术理由时要求用户安装额外工具。材料本身不能证明任何费用真实存在。

实时技能说明声称违反规则会产生“巨额费用”。所给材料没有收费机制或合同依据,因此这句话本身不能扣款;但它是与 Xcode 技术操作无关、用于影响代理决策的虚构威胁,可能使代理不当地服从技能作者的偏好。用户可要求作者删除该措辞,并仅保留有技术依据且符合用户授权的限制。

SKILL.md:11来自说明文档打开原文件
## ⛔️ CRITICAL RULES & ENVIRONMENT CHECKSBefore performing any Xcode setup or file manipulation, you **MUST** adhere tothe following rules. A hefty fee will be applied if you violate them.
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。未发现风险

Skill 逻辑拆解

4 个说明模块

该技能要求先确认本机存在 Swift,然后通过 `swift run` 执行随技能提供的配置工具,而不是让用户在 Xcode 中手工添加依赖。

查看原文
SKILL.md:38来自说明文档打开原文件
Because this skill relies entirely on a native Swift script, you must verify theenvironment:- Run `swift --version` before proceeding.- If the Swift command is not found, you must stop and recommend the user  install the Swift toolchain (e.g., via `xcode-select --install` on macOS), or  ask if you can attempt to install it for them. Do not attempt to proceed  without Swift.
SKILL.md:114来自说明文档打开原文件
1. **Locate the package path:** Find the absolute path to this skill's   `scripts/xcode_spm_setup` directory on disk.1. **Execute:** Run the native `swift run` command using the signature below:```bashswift run --package-path <PATH_TO_SKILL>/scripts/xcode_spm_setup xcode_spm_setup <ProjectPath.xcodeproj> <RepoURL> <VersionRequirement> [--plist <Optional/Path/To/Config.plist>] <Product1> [Product2 ...]```

配置工具会直接改写指定的 Xcode 项目:可加入 plist 资源、远程 Swift Package 和产品链接,并最终保存 `.xcodeproj`。

查看原文
scripts/xcode_spm_setup/Sources/main.swift:121来自说明文档打开原文件
                // 1. Add Plist to the project (Optional)        if let plistPath = plistPath {            print("Adding \(plistPath.lastComponent) to project...")            let mainGroup = rootObject.mainGroup                        let appName = target.name            let groupToAddTo = mainGroup?.children.first(where: { $0.path == appName }) as? PBXGroup ?? mainGroup                        // Only add if it doesn't already exist            if groupToAddTo?.children.contains(where: { $0.path == plistPath.lastComponent || $0.name == plistPath.lastComponent }) == false {                let fileRef = try groupToAddTo?.addFile(at: plistPath, sourceRoot: projectPath.parent())                                if let fileRef = fileRef, let buildPhase = target.buildPhases.first(where: { $0.buildPhase == .resources }) as? PBXResourcesBuildPhase {                    _ = try buildPhase.add(file: fileRef)                    print("Successfully added \(plistPath.lastComponent) to resources build phase.")                }
scripts/xcode_spm_setup/Sources/main.swift:151来自说明文档打开原文件
        } else {            packageRef = try rootObject.addSwiftPackage(                repositoryURL: repoURL,                 productName: products.first!,                 versionRequirement: .upToNextMajorVersion(versionRequirementString),                 targetName: target.name            )        }
scripts/xcode_spm_setup/Sources/main.swift:222来自说明文档打开原文件
                // Write changes        try xcodeproj.write(path: projectPath)        print("Successfully updated Xcode project!")        

该工具自身依赖远程的 XcodeProj 包;随附解析文件记录了当前使用的具体提交和版本。

查看原文
scripts/xcode_spm_setup/Package.swift:7来自说明文档打开原文件
    platforms: [.macOS(.v13)],    dependencies: [        .package(url: "https://github.com/tuist/XcodeProj.git", .upToNextMajor(from: "8.27.7")),    ],    targets: [        .executableTarget(            name: "xcode_spm_setup",            dependencies: ["XcodeProj"],            path: "Sources"        )
scripts/xcode_spm_setup/Package.resolved:31来自说明文档打开原文件
    {      "identity" : "xcodeproj",      "kind" : "remoteSourceControl",      "location" : "https://github.com/tuist/XcodeProj.git",      "state" : {        "revision" : "b1caa062d4aaab3e3d2bed5fe0ac5f8ce9bf84f4",        "version" : "8.27.7"      }
从这里开始 · 工作说明SKILL.md
xcode-project-setup
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。
文件与检查记录5 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文
  • scripts/xcode_spm_setup/.gitignore已纳入全文
  • scripts/xcode_spm_setup/Package.resolved已纳入全文
  • scripts/xcode_spm_setup/Package.swift已纳入全文
  • scripts/xcode_spm_setup/Sources/main.swift已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明
  • scripts/xcode_spm_setup/.gitignore配套文件
  • scripts/xcode_spm_setup/Package.resolved配套文件
  • scripts/xcode_spm_setup/Package.swift配套文件
  • scripts/xcode_spm_setup/Sources/main.swift配套文件

代码和说明中提到的操作

连接外部网站
SKILL.md:92来自说明文档打开原文件
recent version of the Firebase iOS SDK. Check for the latest release version at[https://github.com/firebase/firebase-ios-sdk/releases](https://github.com/firebase/firebase-ios-sdk/releases).
SKILL.md:102来自说明文档打开原文件
1. Adding the package repository dependency (e.g.,   `https://github.com/Alamofire/Alamofire`).1. Selecting the target (e.g., `MyApp`), navigating to **General > Frameworks,
SKILL.md:127来自说明文档打开原文件
```bashswift run --package-path /Users/foo/.agents/skills/xcode-project-setup/scripts/xcode_spm_setup xcode_spm_setup MyApp.xcodeproj https://github.com/Alamofire/Alamofire 5.8.1 Alamofire```
运行命令
SKILL.md:118来自说明文档打开原文件
```bashswift run --package-path <PATH_TO_SKILL>/scripts/xcode_spm_setup xcode_spm_setup <ProjectPath.xcodeproj> <RepoURL> <VersionRequirement> [--plist <Optional/Path/To/Config.plist>] <Product1> [Product2 ...]
SKILL.md:126来自说明文档打开原文件
```bashswift run --package-path /Users/foo/.agents/skills/xcode-project-setup/scripts/xcode_spm_setup xcode_spm_setup MyApp.xcodeproj https://github.com/Alamofire/Alamofire 5.8.1 Alamofire
SKILL.md:137来自说明文档打开原文件
```bashswift run --package-path /Users/foo/.agents/skills/xcode-project-setup/scripts/xcode_spm_setup xcode_spm_setup MyApp.xcodeproj https://github.com/firebase/firebase-ios-sdk 11.0.0 --plist MyApp/GoogleService-Info.plist FirebaseCore FirebaseA 
修改文件
scripts/xcode_spm_setup/Sources/main.swift:223来自说明文档打开原文件
        // Write changes        try xcodeproj.write(path: projectPath)        print("Successfully updated Xcode project!")
读取了多少行
446
文件校验值(用于核对版本)
15e533a3f5a4c476b5695bca1dfbdf5dfc61a4d01a357525c2d3d7717002dfa9