エンジニアリング記事

クラウドMac CIで実行を阻止されたツールの隔離属性を安全に解除する

クラウドMac CIで実行を阻止されたツールの隔離属性を安全に解除する

対話型ターミナルでは正常に動作するビルドタスクが、無人 runner に切り替えると「開けない」「操作が許可されていない」といったエラーを出したり、プロセスが起動直後に終了したりすることがあります。多くの場合、最初に試されるのは chmod +x ですが、ファイルにすでに実行権限があるなら、実際に実行を阻止しているのは Gatekeeper、コード署名の評価、またはダウンロードしたファイルに付与された隔離属性である可能性があります。ブラウザからツールをダウンロードした場合、別のセッションで生成された成果物をコピーした場合、拡張属性を保持するアーカイブからキャッシュを復元した場合などによく発生します。

まず4種類の実行エラーを切り分ける

「実行できない」というだけで、すぐに属性を削除してはいけません。まずファイル形式、権限、アーキテクチャ、拡張属性を確認します。この4項目だけで、誤った原因判断の大半を除外できます。

TOOL="/opt/build-tools/example-tool"

ls -leO@ "$TOOL"
file "$TOOL"
uname -m
xattr -l "$TOOL"

ls では所有者と実行ビットを確認します。file の結果には、ノードと一致する実行可能アーキテクチャが表示される必要があります。xattrcom.apple.quarantine が含まれていても、分かるのはそのファイルが隔離評価の対象になったことだけであり、ファイルの安全性を直接証明するものではありません。エラーが Permission denied なら、まず親ディレクトリをたどる権限があるか、マウントポイントに実行制限が設定されていないかを確認します。Bad CPU type in executable なら、隔離属性を操作するのではなく、正しいアーキテクチャの成果物に差し替える必要があります。

現象 優先して確認する項目 すぐに実行すべきでない操作
Permission denied ファイルと親ディレクトリの権限 拡張属性の再帰的な削除
Bad CPU type fileuname -m 実行ビットの繰り返し変更
破損している、または検証できない 署名と Gatekeeper の判定結果 システムのセキュリティチェックを無効にする
runner でのみ失敗する 実際のパス、ユーザー、キャッシュの取得元 対話環境と完全に同じだと仮定する

隔離属性は取得元を追跡するための手掛かりであり、障害そのものではありません。まず想定どおりのファイルを取得していることを証明し、その後で実行を許可するか判断します。

Gatekeeperの明確な判定を確認する

単一のバイナリまたはアプリを評価する

コマンドラインツールでは、最初に署名を確認し、その後でシステムポリシーによる判定を取得します。アプリケーションバンドルの場合は、TOOL を対象の .app パスに置き換えます。

codesign --display --verbose=4 "$TOOL"
codesign --verify --deep --strict --verbose=2 "$TOOL"
spctl --assess --type execute --verbose=4 "$TOOL"

署名されていない社内ツールが必ずしも問題とは限りません。ただし、管理されたビルドプロセスで作成され、ダイジェスト検証によって完全性を証明できる必要があります。署名付きとして配布されているサードパーティー製のビルド済みツールで検証に失敗した場合は、使用を中止して信頼できる成果物を取得し直してください。隔離属性を削除して署名の変化を覆い隠してはいけません。

ポリシーログを確認する

ダイアログや runner の標準エラー出力では、原因が省略されることがよくあります。問題を再現した直後にセキュリティポリシーの最新ログを確認すれば、実際に評価されたパスを特定できます。これにより、キャッシュ A を調べていたのに実際にはキャッシュ B が実行されていた、といった行き違いを防げます。

log show --last 10m \
  --predicate 'subsystem == "com.apple.security.syspolicy"' \
  --style compact

ログに記録されたパスを、command -v の結果、runner の設定、スクリプト変数と一つずつ照合します。特にシンボリックリンクは不一致の原因になりやすく、入口はツールディレクトリにあっても、最終的なファイルが古いキャッシュを参照している場合があります。

実行を許可する前に成果物を検証する

最も確実なのは、ツールの配布元または社内の成果物管理プロセスから SHA-256 ダイジェストを提供してもらい、ダイジェストファイルをツールのバージョンとともにリポジトリ設定へ組み込む方法です。ダウンロードしたファイルからその場でダイジェストを計算し、同じファイルの検証に使ってはいけません。それでは読み取りの前後でファイルが変化していないことしか確認できず、取得元の正しさは証明できません。

cd /opt/build-tools
shasum -a 256 -c example-tool.sha256
codesign --verify --deep --strict --verbose=2 example-tool

社内でビルドしたツールには外部配布用の署名がなくても構いませんが、少なくともコミットのバージョン、ビルドスクリプトのバージョン、期待されるダイジェストを記録しておく必要があります。ツールが圧縮ファイルとして提供される場合は、まず圧縮ファイルを検証し、一時ディレクトリへ展開して最終的な実行ファイルを確認した後、正式なパスをアトミックに置き換えます。これにより、更新途中の不完全なファイルを runner が読み込むことを防げます。

対象の隔離属性だけを解除する

ダイジェスト、バージョン、署名が想定どおりであることを確認したら、検証済みの対象だけを処理します。最初に元の値を読み取ってジョブログへ記録し、その後で指定した属性を削除します。

TOOL="/opt/build-tools/example-tool"

xattr -p com.apple.quarantine "$TOOL" 2>/dev/null || true
if xattr -p com.apple.quarantine "$TOOL" >/dev/null 2>&1; then
  xattr -d com.apple.quarantine "$TOOL"
fi

spctl --assess --type execute --verbose=4 "$TOOL"
"$TOOL" --version

ワークスペースに対して xattr -cr . を実行してはいけません。この操作はリポジトリ、依存関係、スクリプト、一時成果物に付与された複数の拡張属性をまとめて削除します。実行を許可する範囲が広がるだけでなく、後から調査する際に取得元を示す証拠も失われます。アプリケーションバンドルでは、バンドル内に継承された属性を処理しなければならない場合がありますが、それでも対象は検証済みの単一バンドルに限定し、runner のキャッシュルート全体には広げないでください。

検証手順をインストールゲートとして定着させる

安定したクラウド Mac CI では、ビルドタスクごとにその場で権限を修正すべきではありません。ツールの準備を独立したインストール工程に分け、まず一時ディレクトリへダウンロードします。次にダイジェストの照合、アーキテクチャの確認、署名の検証、隔離状態の取得、対象限定の実行許可、バージョンのセルフチェックを行い、その後で共有ツールディレクトリへ配置します。

キャッシュキーには、少なくともツール名、バージョン、CPU アーキテクチャ、ダイジェストを含めます。キャッシュがヒットした場合も、手作業で上書きされている可能性があるため、簡易チェックは必ず実行します。runner の起動時には、id -ununame -m、解決されたツールパス、バージョンを記録できますが、認証情報や環境変数全体を出力してはいけません。

最後に、失敗時の原則を3つ維持します。ダイジェストが一致しなければ直ちに停止すること、本来存在するはずの署名を検証できなければ再取得すること、検証済みの成果物が隔離評価によってのみ阻止されている場合に限り対象属性を削除することです。システム全体のチェックを無効にするより数行多くのコマンドが必要になりますが、ツールの取得元、実行許可の操作、実際に実行されたバージョンをすべて監査できるようになります。

よくある質問

実行権限が付いていてもmacOSに阻止されるのはなぜですか?

実行権限とは別に、Gatekeeperが隔離属性、署名、取得元、システムポリシーを評価するためです。chmod +xだけではこの評価を変更できません。

CIの作業ディレクトリ全体にxattr -crを実行してもよいですか?

推奨しません。未知の成果物を含む全ファイルの属性まで消えるため、ハッシュと署名を確認した対象ファイルからcom.apple.quarantineだけを削除します。

毎回同じツールが阻止される状態を防ぐにはどうしますか?

ダウンロード、ハッシュ検証、展開、対象限定の解除を管理された導入処理にまとめ、検証済みファイルをバージョン、アーキテクチャ、ハッシュ単位でキャッシュします。

OrbVPS クラウドMac

専用のApple Silicon物理ノードでビルドを実行

機種、リージョン、レンタル期間を選んでノードを設定できます。実際の利用可否は、管理コンソールにリアルタイムで表示される情報をご確認ください。

クラウドMacを今すぐレンタル