ci(release): 显式 strip macOS bundle xattr (defense-in-depth)#83
Merged
Conversation
GitHub Actions 输出本来就不带 com.apple.quarantine (actions/upload-artifact 不跨机器持久化 xattr, softprops/action-gh-release 上传 binary stream 也不带), 但加这一步让 "云端 artifact 一定干净" 变成可验证的承诺, 未来 release 不会因 runner 环境变化退化. 用户下载到本地后浏览器/LaunchServices 仍会加 quarantine, 依赖 release notes 里的 xattr -cr 指引或一行安装命令处理.
Reviewer's guide (collapsed on small PRs)Reviewer's GuideAdds a defensive CI step in the Tauri release workflow to strip extended attributes (including com.apple.quarantine) from macOS bundles before uploading them as artifacts, ensuring uploaded artifacts are verifiably clean. Sequence diagram for macOS bundle xattr stripping before artifact uploadsequenceDiagram
participant WF as Workflow
participant R as Actions_runner_macos
participant X as xattr_tool
participant FS as macOS_filesystem
participant A as GitHub_Artifacts
WF->>R: Execute job for matrix.platform == macos-latest
R->>R: Build macOS bundles
R->>FS: List bundle directories (ls macos/ dmg/ ...)
WF->>R: Run Strip xattr / quarantine step
loop For each path in macos/*.app and dmg/*.dmg
R->>FS: Check if path exists
alt Path exists
R->>X: xattr -cr path
X->>FS: Clear extended attributes
R->>X: xattr -lr path
X->>R: List remaining attributes (for logging)
else Path does not exist
R-->>R: Skip path
end
end
WF->>R: Run Upload macOS artifacts step
R->>A: Upload sanitized .app and .dmg bundles
Flow diagram for new macOS xattr stripping step in release workflowflowchart TD
A["Build macOS bundles"] --> B["List bundle directories (ls macos/ dmg/ ...)"]
B --> C["Strip xattr / quarantine on macOS bundles (macos-latest only)"]
C --> D["Upload macOS artifacts via actions/upload-artifact"]
subgraph Strip_xattr_step
C1["Loop over macos/*.app"]
C2["Loop over dmg/*.dmg"]
C3["For each existing path: xattr -cr path"]
C4["Then: xattr -lr path (log remaining attributes)"]
C --> C1
C1 --> C3
C --> C2
C2 --> C3
C3 --> C4
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Consider using
xattr -d com.apple.quarantine(or a targeted attribute list) instead ofxattr -cr, so you only remove the quarantine flag and avoid unintentionally stripping other extended attributes that might be meaningful (e.g., for signing or metadata). - Right now both
xattrinvocations are suffixed with|| true, which will hide any unexpected failures; if the intent is defense-in-depth, you might want to at least log non-zero exit codes or only ignore specific, benign failures (like "No such xattr").
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider using `xattr -d com.apple.quarantine` (or a targeted attribute list) instead of `xattr -cr`, so you only remove the quarantine flag and avoid unintentionally stripping other extended attributes that might be meaningful (e.g., for signing or metadata).
- Right now both `xattr` invocations are suffixed with `|| true`, which will hide any unexpected failures; if the intent is defense-in-depth, you might want to at least log non-zero exit codes or only ignore specific, benign failures (like "No such xattr").Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
appergb
pushed a commit
that referenced
this pull request
Apr 30, 2026
…attr 修复 Codex audit 对 main HEAD a9c81e6 的 2 条 HIGH + 把 macOS auto-update 的 "重启后 Gatekeeper 拦截"问题封死。 ## HIGH #2: 版本号不一致 PR #84 没顺手 bump 版本,main 仍自报 1.2.2,下次直接打 v1.2.3-tauri 会让 updater manifest 自报 1.2.2,已安装的 1.2.2 客户端永远拿不到 "有新版本"。 修:package.json + tauri.conf.json + Cargo.toml 全部改 1.2.3。 ## HIGH #1: updater pubkey 所有权 PR #84 使用的 pubkey 是外部贡献者本地生成的,appergb 不掌握对应 private key。 任何持有那把私钥的人都能签发更新 -> 客户端 OTA 装上恶意版本。 修: - 用 npx @tauri-apps/cli signer generate --ci 生成 appergb 自己的 keypair - 新 pubkey: F0FCDE68E08E6D4E (写入 tauri.conf.json plugins.updater.pubkey) - 私钥已通过 gh secret set TAURI_SIGNING_PRIVATE_KEY 配到 GitHub repo secret - 私钥本地副本只在 /tmp,不进 git,commit 后会清除 ## macOS auto-update 后 strip xattr restart_app 在 app.restart() 前对 .app bundle 跑 /usr/bin/xattr -cr。这是 Tauri auto-updater + 未公证应用的组合下唯一让"自动更新对用户零摩擦"的解法 — 否则 Gatekeeper 在重启时会拦说"OpenLess 已损坏",用户必须开终端 xattr 才能 继续用,违反 auto-update 的本意。 未来发版逻辑必须保留这一步。release-tauri.yml 上一次 PR (#83) 已经在 CI 侧 strip 过一次,本次在 client 侧重启时再 strip 一次,双保险覆盖 "下载 -> 解压 -> 安装 -> 重启"全链路。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
防御性步骤:在 macOS 产物 upload 之前 xattr -cr 一次。GitHub Actions 输出本来就不带 quarantine,但显式声明让 "云端 artifact 一定干净" 变成可验证承诺。
Summary by Sourcery
CI: