Oktaは最近、macOSとWindows向けのOkta Verifyクライアントに高度なポスチャチェックを導入しました。この機能では、軽量なエンドポイントエージェントであるosqueryを利用しています。osqueryは、ログイン時にSQLクエリを実行して、重要なデバイスデータを検出できます。検出されるデータには、launchdサービス、ファイルパス、実行中のプロセス、パッケージマネージャー、リッスンポート、インストール済みアプリ、コンテナアーティファクトなどがあり、これらの情報を総合すると、サインイン時のデバイス保証シグナルを得られます。高度なポスチャチェックを使用すると、デバイスが想定されるセキュリティ基準を満たしていない場合、そのユーザーはアクセスできません。
その続報として、こちらの記事では、本来実行されているべきセキュリティアプリケーションが無効化されている、または実行されていない場合に、この機能を使って検知する方法をご紹介しました。Oktaのチームは、セキュリティツールのウォッチドッグ検出機能をリリースしました。これは、モバイルデバイス管理(MDM)ソフトウェア、データ漏洩防止(DLP)ツール、DNSセキュリティソフトウェアなど、実行されているべきセキュリティツールに基づいてデバイスをスコアリングするものです。
osqueryの優れた点の1つは、変化し続ける脅威環境に適応できることです。本当の価値は、1つの脅威を検知することではありません。AIエージェント、コーディングアシスタント、ローカルモデルランタイムなど、気付かないうちに誰もが利用する開発環境の一部となったものも含め、デバイス上で実行されているあらゆるものを幅広く可視化できることにあります。
初日からこの作業を容易にするために、Oktaは公開customer-detectionsリポジトリに広範なサンプルチェックを公開しました。macOSとWindowsにわたる24種類のAIツールをカバーしています。
未承認のAIツール
セキュリティチームはこの2年間、SaaSのAIチャットインターフェイスの利用に関するポリシーの策定に取り組んできました。しかし、対応はまだ終わっていません。次に課題となるのは、こうしたAIチャットインターフェイスとともに登場している、第2波のツールです。
エージェント型コーディングアシスタントは、アクションごとの確認をほとんど、あるいはまったく行うことなく、ファイルの読み書き、シェルコマンドの実行、外部サービスの呼び出しを行います。Cursor、Goose、Aider、Cline、Windsurf、OpenAI Codex CLI、Gemini CLIなどがその例です。
Ollama、LM Studio、GPT4All、llama.cppなどのローカルLLMランタイムは、モデルをエンドポイントで直接実行し、いくつかのデフォルト構成では、認証されていないREST APIをローカルネットワーク上で公開します。
クラウドに接続されたデスクトップアプリやIDE拡張機能は、その設計上、コード、ファイル、会話履歴をデバイスの外部に送信します。これには、ChatGPT Desktop、GitHub Copilot、Microsoft Copilot、Sourcegraph Cody、Tabnine、Supermavenなどが含まれます。
企業の認証情報を持つエージェント(Amazon Qの後継であるKiroなど)は、AWS IAM Identity Centerのセッションを引き継ぎ、サインインしているユーザーと同じ権限を持つことができます。これには、本番環境のインフラストラクチャへのアクセス権も含まれます。
こうしたエージェント型アプリケーションは、2つのカテゴリーに分けられます。1つは、認証を行うタイプのエージェントです。たとえば、Claude CodeのセッションがSSOを介して認証するケースです。一方、大半は別のタイプに分類されます。たとえば、開発者がOllamaをインストールしたり、エージェントをアイデンティティプロバイダーに登録せずにCursorをプライベートリポジトリに接続したりするケースです。これが「シャドーAI」と呼ばれるもので、AIに関する会話でOktaが最も頻繁に耳にする意見の1つです。大半の組織は、正式なガバナンスも一貫した所有者の割り当てもないまま、本番環境でAIエージェントが稼働していると報告しています。これは、あらゆる組織にとってリスクになります。
機密性の高いソースコードやシークレットが、DLPツールでは検査できないエージェント型チャネルを通じて組織外に流出する可能性があります。デバイス上で無人で実行されているシェルアクセス権を持つ自律型エージェントが、機密性の高いアプリに認証する可能性があります。その結果、後になって管理者はどのツールがデータベースを「rm -rf」で削除したのか分からなくなります。管理者は、セキュリティチームがその存在を認識していないエージェントをシャットダウンすることはできません。
可視性と明確性をもたらす方法があります。エンドポイントレベルの検出機能により、「エンジニアがローカルAIツールを実行していると想定される」という推測が、管理可能な資産へと変わり、デバイス保証ポリシーに組み込むことができるようになります。
本格的なアイデンティティ機能を持つツール(KiroのAWS IAM Identity CenterセッションやCopilotのGitHub OAuth認可付与など)についても同様に、デバイスのポスチャは独立した、必要不可欠なシグナルです。エージェントが正しく認証されたことが分かっていても、そのエージェントが実行されているデバイスまで信頼すべきだとは限りません。そのギャップを埋めることが、こうしたチェックの目的であり、アイデンティティレイヤーの制御を補完するものでもあります。高度なポスチャチェックを使用すれば、ツールのポスチャをアクセスの条件にすることができます。
クロスプラットフォームのツールリポジトリ
sample_osquery_checksフォルダーは、プラットフォーム別に構成されています。
sample_osquery_checks/
├── Cross/ # あらゆるOSに適用されるチェック(サプライチェーン/マルウェアキャンペーン)
├── macOS/ # macOS固有のosqueryテーブル
└── Windows/ # Windows固有のosqueryテーブル
すべてのチェックは、同じ形式のYAMLファイルとして記述されています。
タイトル:<Human-readable name>
id: <一意の識別子>
description:<What the check detects and why it matters>
参考文献:
- <ベンダーのドキュメントまたは脅威インテリジェンスへのリンク>
著者:
- <作成者のメールアドレス>
プラットフォーム:
- macOS | Windows | Linux
クエリ: |
<osquery SQLクエリ>
この例では、「query」はosqueryの仮想テーブルに対する標準的なSQLクエリです。条件が検出された場合は空でない結果を返し、クリーンなデバイスでは空の結果を返します。その結果は、Okta Verifyのデバイス保証ポリシーの評価に直接反映されます。
リポジトリで対象としている24種類のツールのうち、23種類にはmacOS版とWindows版の両方があります。それぞれのプラットフォームのosqueryスキーマに合わせて調整されており、macOSではアプリとlaunchd、Windowsではプログラムとサービスを対象とします。Microsoft Copilotは、当然ながらWindows専用です。
カテゴリ | ツール |
エージェント型コーディングCLI/IDEエージェント | Aider、Cline/Roo、Continue.dev、Cursor、Goose、Kimi Code、OpenCode、Sourcegraph Cody、Supermaven、Tabnine、Windsurf/Codeium |
クラウドコーディングアシスタント | GitHub Copilot、Microsoft Copilot、OpenAI Codex CLI、Gemini CLI、Claude(Desktop + Code)、Kiro(Amazon Q) |
ローカルLLMランタイム | Ollama、LM Studio、GPT4All、llama.cpp、Jan, AnythingLLM |
デスクトップチャットクライアント | ChatGPT Desktop |
4種類のリスク
すべてのチェックは、元の記事で紹介したものと同じ構造になっています。つまり、それぞれ1種類のアーティファクトをチェックする独立した共通テーブル式(CTE)を複数用意し、それぞれの結果をスコアとして合算したうえで、しきい値を設定します。チェックが実行されるには、2つ以上の独立した検出シグナル(スコア > 1)が必要です。これは、誤検知を抑制するための意図的な仕組みです。アンインストール後に残ったファイルや、たまたま部分一致したプロセス名が1つあるだけでは、チェックは実行されません。一方、バイナリ、設定ファイル、実行中のプロセスがそろえば、はるかに信頼性の高いシグナルになります。これは、単一の情報源から得られるノイズの多いアラートにも適用すべき相関ロジックと同じです。
代表的な例として以下に、AI向けに設計されたVS CodeのフォークであるCursorを対象としたmacOS用のチェックを紹介します。
title: Cursor AIエディターの検出
id: e9b3f6d2a7c1450e8f3b9d6a2c5e7f1b
description: |
macOSデバイス上で、VS Codeをベースに構築されたAIネイティブのコードエディターであるCursorの存在を検知します。
Cursorは、エディターにAIコーディング支援機能を直接組み込んでおり、デフォルトでは、
開いているファイル、ターミナル出力、リポジトリの履歴などのコードコンテキストをCursorのサーバーと
サードパーティのAIプロバイダー(OpenAI、Anthropic、Google)に送信します。エディターのエージェントモードは、自律的に
アクションごとの確認なしに、コードの実行、ターミナルコマンドの実行、ファイルの変更ができます。プライバシー
モードは利用可能ですが、明示的なオプトインが必要です。
プラットフォーム:macOS
クエリ: |
WITH launchd_cursor AS (
SELECT COALESCE(COUNT(*), 0) AS total
FROM launchd
WHERE name LIKE '%cursor%'
)、
file_cursor AS (
SELECT COALESCE(COUNT(*), 0) AS total
FROM file
WHERE path LIKE '/Applications/Cursor.app'
OR path LIKE '/Users/%/.cursor/mcp.json'
OR path LIKE '/Users/%/.cursor/extensions/%'
OR path LIKE '/Users/%/Library/Application Support/Cursor/User/settings.json'
)、
process_cursor AS (
SELECT COALESCE(COUNT(*), 0) AS total
FROM processes
WHERE name LIKE '%cursor%'
AND path NOT LIKE '/System/%'
AND path NOT LIKE '/Library/%'
)、
apps_cursor AS (
SELECT COALESCE(COUNT(*), 0) AS total
FROM apps
WHERE (name LIKE '%cursor%' OR bundle_identifier LIKE '%cursor%')
AND bundle_identifier NOT LIKE 'com.apple.%'
)、
final_score AS (
SELECT
launchd_cursor.total + file_cursor.total
+ process_cursor.total + apps_cursor.total
ASスコア
FROM launchd_cursor, file_cursor, process_cursor, apps_cursor
)
SELECT
CASE WHEN score <= 1 THEN 0 ELSE 1 END AS cursor_detected
FROM final_score;
次に、別のツールであるローカルLLMサーバーのOllamaについて説明します。Ollamaは完全にデバイス上で実行されるため、クラウドAPIのトラフィックを検査するDLPツールは適用できません。
また、OllamaのREST APIはデフォルトでは認証なしで0.0.0.0:11434にバインドされるため、同じローカルネットワーク上のほかのデバイスからもアクセスできます。
title: OllamaローカルLLMサーバーの検出
プラットフォーム:macOS
クエリ: |
WITH launchd_ollama AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM launchd WHERE name LIKE '%ollama%'
)、
file_ollama AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM file
WHERE path LIKE '/Applications/Ollama.app'
OR path LIKE '/Users/%/.ollama/models/%'
OR path LIKE '/opt/homebrew/bin/ollama'
)、
process_ollama AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM processes WHERE name LIKE '%ollama%'
)、
netports_ollama AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM listening_ports
WHERE port = '11434' OR path LIKE '%ollama%'
)、
final_score AS (
SELECT launchd_ollama.total + file_ollama.total
+ process_ollama.total + netports_ollama.total AS score
FROM launchd_ollama, file_ollama, process_ollama, netports_ollama
)
SELECT CASE WHEN score <= 1 THEN 0 ELSE 1 END AS ollama_detected
FROM final_score;
プロセスとファイルのチェックに加えて、`listening_ports`テーブルをインジケーターとして含めることで、このクエリは単にバイナリの存在だけでなく、ネットワークに公開されている誤設定のインストールにもフラグを立てることができます。
Blockが開発したオープンソースの自律型エンジニアリングエージェントであるGooseは、3種類目のリスクを示す例です。Gooseは、テストスイートの実行、ビルドパイプラインの変更、外部APIの呼び出しなど、監視なしで複数のステップからなるタスクを実行するよう設計されたエージェントです。こうした処理は、APIキーを含む可能性のあるプレーンテキストの設定を使って実行される場合があります。
タイトル:Goose AIエージェント検出
プラットフォーム:macOS
クエリ: |
WITH file_goose AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM file
WHERE path LIKE '/opt/homebrew/bin/goose'
OR path LIKE '/Users/%/.config/goose/profiles.yaml'
OR path LIKE '/Users/%/.local/share/goose/sessions/%'
)、
process_goose AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM processes
WHERE name = 'goose' OR cmdline LIKE '%block-goose%'
)、
final_score AS (
SELECT file_goose.total + process_goose.total AS score
FROM file_goose, process_goose
)
SELECT CASE WHEN score <= 1 THEN 0 ELSE 1 END AS goose_detected
FROM final_score;
また、Amazon Q Developerの後継となるAWSのKiroは、4つ目の潜在的なリスクシナリオである認証情報の継承を示す例です。KiroはAWS IAM Identity Centerを介して認証するため、Kiroのセッションが侵害されると、サインインしているユーザー自身のAWS権限がそのまま含まれる可能性があります。
タイトル:Kiro(Amazon Q)AI開発者ツール検出
プラットフォーム:macOS
クエリ: |
WITH file_kiro AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM file
WHERE path LIKE '/Applications/Kiro.app'
OR path LIKE '/Users/%/.kiro/settings/mcp.json'
-- QからKiroへの移行時に残ったAmazon Qのアーティファクト
OR path LIKE '/Users/%/.amazonq/scopes/scope.json'
OR path LIKE '/Users/%/.vscode/extensions/amazonwebservices.aws-toolkit-vscode-%'
)、
process_kiro AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM processes
WHERE name LIKE '%kiro%' OR name LIKE '%amazon-q%'
)、
apps_kiro AS (
SELECT COALESCE(COUNT(*), 0) AS total FROM apps
WHERE name LIKE '%kiro%' OR bundle_identifier LIKE '%amazonq%'
)、
final_score AS (
SELECT file_kiro.total + process_kiro.total + apps_kiro.total AS score
FROM file_kiro, process_kiro, apps_kiro
)
SELECT CASE WHEN score <= 1 THEN 0 ELSE 1 END AS kiro_detected
FROM final_score;
このクエリは、レガシー構成パス(~/.amazonq/)が含まれているため、Amazon Q Developerのインストールを検出します。Kiro独自のパスとともに含まれています。
全デバイスのデータを収集しながら、ツールごとにしきい値を調整することをお勧めします。今回のサンプルで使用しているデフォルトの「スコア > 1」は、妥当な開始点です。検出可能なアーティファクトが少ないツール(たとえば、Gooseには2つのCTEがあるのに対し、Claudeには8つあります)では、誤検知と検知漏れの傾向も異なります。また、アンインストールしたツールの残存ファイルがノイズの原因になることもあるため、チェックを監視モードから強制適用に切り替える前に、その影響を確認しておくことをお勧めします。
スコアからサインイン時の判断へ
こうしたチェックはそれぞれ単一の0/1列を返します。これは、デバイスアシュアランスのポリシー条件で想定されているものです。そこから先、何らかの対応を取るか、取るとすればどのような対応を取るかは、管理者が決定します。こうした決定は、ユーザーの種類や役割によって異なる場合があります。同じシグナルであっても、適用されるオーディエンスによって、まったく異なる応答をサポートすることがあります。つまり、ツールごとに許可/ブロックを二者択一で判断するだけでなく、より高度な対応が可能になります。以下のアプローチを検討してください。
シェルアクセスやファイルアクセスが可能なツールをはじめ、未承認のエージェント型コーディングツールを実行しているデバイスから機密性の高いアプリへのサインインをブロックします。
ネットワークに公開されたポートを持つローカルLLMランタイムが検出された場合、管理者に警告と通知を送信します。これにより、IT部門は即座にブロックするのではなく、OLLAMA_HOST(または同等のもの)の設定を追跡調査できます。
条件付きで許可 — 例えば、エンジニアリンググループにはGitHub CopilotやCursorを許可し、財務や法務部門にはエージェント型アプリケーションをブロックするなど。
強制的な制御は行わず、導入状況を受動的に追跡します。ポリシーを決定する前に、フリート全体でのシャドーAIの利用状況を把握できます。
すべてのクエリは、ポリシーに組み込む前に、osqueryi(osqueryの対話型コマンドラインシェル)を介してローカルインスタンスに対してスタンドアロンで実行し、結果を検証できます。適用する前に、これらの検出結果を監視することをお勧めします。まず、レポート専用モードのポリシーにチェックを組み込み、その後、フリートの代表的な部分におけるヒット率を確認します。「ブロック」モードに移行する前に、検出された項目が実際のインストールであり、アンインストールによって残されたアーティファクトではないことを確認してください。これにより、ソフトウェアエンジニアがロックアウトされてヘルプデスクに問い合わせが殺到する事態を防ぐことができます。
すべてのチェックは同じCTEと閾値のパターンに従うため、新しいツールにカバレッジを拡張するには、これらのファイルのいずれかをコピーし、そのツールに固有のパス、プロセス名、ポートを入れ替えるだけです。
カバレッジギャップを解消する
これらのクエリは、現在フリート全体で実行されているAIツールのインベントリを作成するための手段となります。セキュリティチームは、どのエージェント型ツールがデバイスで実行されているかを推測したり、夜も眠れないほど悩んだりする必要がなくなります。
osqueryを書くのが得意でない場合でも、OktaのIdentity Security Posture Management(ISPM)を利用すれば、このブログ記事で説明したことをすべて(さらに多くのことも)実行できます。検出ロジックはOktaが管理します。Okta for AI Agentsのライセンスで利用する場合、AIツールに関連する管理外のOAuth認可付与を検出し、管理者に通知して、こうしたエージェントを管理対象にするよう促すこともできます。
24個のクエリの完全なセットは、OktaのGitHubにあるこちらで入手できます。コントリビューションを歓迎します。まだOktaでカバーされていないAIツールを追跡している場合は、リポジトリをフォークし、同じYAML形式で新しいチェックを含むPRを送信してください。このリポジトリを使用している他のすべてのチームに、これを最も早く共有する方法です。