セキュリティとコンプライアンス
何が、どのように保護され、誰が責任を負うのか。セキュリティレビューのために。
このページは、セキュリティレビューの担当者、IT 管理者、そして「これを導入しても安全か」に答えなければならないすべての人のためのものです。
一文で表す脅威モデル
ObjectOS は、1 つのデータベースと通信する単一の Node.js プロセスとして動作します。ObjectOS Enterprise ではあなたのネットワークの中で、ObjectOS Cloud では私たちのネットワークの中で動作します。セルフマネージドの場合、ObjectOS が自ら行う唯一のアウトバウンドの呼び出しはライセンスの検証であり、Enterprise のエアギャップライセンスはオフラインで検証されます。侵害の影響範囲は、接続先のデータベース上のデータであり、それ以上ではありません。
データレジデンシー
この表は、セルフマネージドのエディションである ObjectOS Enterprise について記述しています。ObjectOS Cloud では、同じ種類のデータが私たちがあなたのために運用するインフラストラクチャに置かれます。どちらのエディションでも、オントロジーは通常の ObjectStack メタデータです。オープンソースの ObjectStack ランタイムへのエクスポートは計画中です。
| データの種類 | 置き場所 | ネットワークの外に出るか |
|---|---|---|
| 業務レコード | あなたのデータベース | いいえ |
| ユーザーアカウント、セッション、OAuth トークン | あなたのデータベース | いいえ |
| 監査ログ | あなたのデータベース | いいえ |
| 設定、API キー、シークレット | あなたのデータベース / あなたのシークレットマネージャー | いいえ |
| アップロードされたファイル | あなたのディスク、または S3 互換のバケット(S3、R2、MinIO) | いいえ |
コンパイル済みのアプリ定義(objectstack.json) | ディスク上のファイル、またはあなたのコントロールプレーンから取得 | 任意 |
| ランタイム自体 | あなたのサーバーまたはコンテナ | いいえ |
| テレメトリ / 利用データ | — | 一切収集しません |
明示的に設定した連携(OIDC ディスカバリー、メールプロバイダー、AI プロバイダー、Webhook の送信先、外部ストレージ)以外で、セルフマネージドの ObjectOS が自ら行う唯一のアウトバウンドの呼び出しはライセンスの検証です。Enterprise のエアギャップライセンスはオフラインで検証されるため、エアギャップのデプロイメントは何も呼び出しません。ライセンスと料金を参照してください。
暗号化
| 層 | 仕組み | 責任 |
|---|---|---|
| 通信中(ブラウザ ↔ ObjectOS) | TLS。あなたのエッジ / イングレスで終端 | あなた |
| 通信中(ObjectOS ↔ データベース) | ドライバーレベルの TLS(Postgres の sslmode=require、MongoDB の tls=true など) | あなた(接続文字列で設定) |
| 保存時(業務データ) | データベースネイティブ(例:Postgres TDE、RDS の暗号化) | あなた |
| 保存時(アップロードされたファイル) | ストレージネイティブ(S3 SSE、R2 のデフォルト、ディスクレベルの FDE) | あなた |
| DB 内のシークレット(設定、OIDC クライアントシークレット) | 設定サービスによって暗号化 | ObjectOS |
| セッション Cookie / トークン | OS_AUTH_SECRET で HMAC 署名 | ObjectOS |
| API キーの値 | DB ではハッシュ化。DB の行が漏洩してもキーは復元できません | ObjectOS |
認証
組み込み(Better Auth を基盤とする @objectstack/plugin-auth による):
- 確認とリセット付きのメール/パスワード
- 取り消しが可能なセッション管理
- ソーシャル OAuth(Google、GitHub、Microsoft、Apple など)
- エンタープライズの OIDC/SSO(Okta、Entra ID、Keycloak、Ping)
- 二要素認証(TOTP)
- パスキー / WebAuthn
- マジックリンク
- 電話番号と SMS の OTP によるサインインとパスワードリセット(
auth.plugins.phoneNumberでオプトイン。Aliyun / Twilio のトランスポート、レート制限付き) - CLI/ブラウザのデバイスフロー
- API キー(ハッシュ化、有効期限付き、取り消し可能、ユーザーに紐づく)
- MCP クライアント向けのセルフサービスの OAuth 2.1(認可コード + PKCE、動的クライアント登録、スコープから導出される権限の上限)
- 管理者主導のユーザー作成と一括インポート(
must_change_passwordによる強制変更付きのワンタイムパスワード)
認証を参照してください。
認可
Permission Model v2(ObjectStack 13、ADR-0090)に従った、層状の強制(@objectstack/plugin-security による):
- オブジェクト権限:権限セットごと、オブジェクトごとの CRUD。ユーザーに直接、またはフラットなポジションを通じて配布されます
- 組織全体のデフォルト:所有者を持つカスタムオブジェクトは、デフォルトで
privateの共有モデルになります。オブジェクトのデータへの匿名アクセスは無条件に拒否され、それを開くスイッチはありません(ObjectStack 17.0)。公開アクセスはサーフェスごとに宣言します(公開フォームまたは共有リンク)。guestアンカーは何も付与しません - 行レベルセキュリティ:クエリに注入される宣言的なポリシー式。省略はできず、ランタイムが強制できないポリシーは範囲を広げるのではなく拒否します(ObjectStack 17.5)
- フィールドレベルのセキュリティ:フィールドはレスポンスから除去されるか、部分的にマスクされるか(
maskingRule、ObjectStack 17.1)、書き込み時に拒否されます(キーはオブジェクトで修飾され、lint で強制されます)。非表示またはマスクされたフィールドでは、絞り込み、並べ替え、グループ化、集計ができません。ObjectStack 17.6 以降、すべてのクエリの入り口で403になります - 組織のスコープ:マルチテナントの分離。回避には明示的な
viewAllRecordsが必要です
システムコンテキストの操作は、内部のジョブやマイグレーションが実行できるようにチェックを回避します。これらの経路は監査可能です。
それを支える仕組み:
- 説明エンジン:
explain(principal, object, operation)は、強制と同じ評価器を使って、各層の判定を層ごとの根拠とともに報告します(構造上ずれは生じません)。 - 作成時の lint:
os compileはセキュリティの姿勢(security-owd-unset、security-anchor-high-privilege、security-fls-unqualified-keyなど)によってビルドを制限します。また、任意でコミットするaccess-matrix.jsonのスナップショットにより、機能のずれがあると明示的に再承認されるまで CI が失敗します。 - 委任された管理:権限セットに
adminScopeを持たせると、サブ管理者は自分のビジネスユニットのサブツリー内でのみ、許可リストから、granted_byの監査付きで割り当てを管理できます。 - MCP のスコープの上限:OAuth で接続した AI エージェントは
effective_permission = scope_ceiling ∩ user_grants(data:read/data:write/actions:execute)のもとで実行され、フェイルクローズです。
権限を参照してください。
監査と証拠
監査機能(@objectstack/plugin-audit)が読み込まれている場合:
- すべてのオブジェクトにおけるすべての CRUD 操作 → 監査の行。
- フィールドの変更の変更前と変更後の値。
- 認証、権限の付与、セッションの取り消しのイベント。
- 監査の行は改ざんできません。変更はできず、アーカイブのみ可能です。
- 保持期間はオブジェクトの
lifecycleブロックで宣言され(sys_audit_logは 90 日間ホット、その後アーカイブとして提供されます)、lifecycle.retention_overridesで環境ごとに調整できます。データベースのアーカイブポリシーと組み合わせてください。
これが、SOC 2 CC6/CC7、ISO 27001 A.12.4、HIPAA §164.312(b)、GDPR 第 30 条の証拠の基盤になります。
コンプライアンスのフレームワーク
ObjectOS は、一般的なフレームワークのすべてが求める技術的なプリミティブを提供します。認証はソフトウェアではなくデプロイメントの性質ですが、統制はきれいに対応します。
| フレームワーク | ObjectOS が提供するもの |
|---|---|
| SOC 2 | アクセス制御(CC6)、変更管理(監査ログ)、暗号化(デプロイメント)、監視(オブザーバビリティ)、バックアップ(operate/backup) |
| ISO 27001 | A.5 ポリシー(RBAC)、A.8 資産管理(オブジェクトのカタログ)、A.9 アクセス制御、A.12 運用、A.18 コンプライアンス |
| HIPAA | アクセス制御(§164.312(a))、監査制御(§164.312(b))、完全性(改ざんできない監査)、伝送のセキュリティ(TLS) |
| GDPR | 第 30 条 処理の記録(監査)、第 32 条 処理のセキュリティ、第 17 条 消去権(論理削除と物理削除をサポート)、データレジデンシー(リージョンを選択可能) |
| CCPA / 中国データセキュリティ法 / ロシア 152-FZ | 適切なリージョンの ObjectOS Enterprise でレジデンシーを満たします。アクセス制御と監査で、報告義務のほとんどをカバーします |
認証の対象はバイナリではなく稼働中のデプロイメントであるため、ObjectOS 自体は認証を受けていません。あなたのデプロイメントは認証を受けることができ、すでに多くが受けています。
シークレットの取り扱い
| シークレット | 置き場所 |
|---|---|
OS_AUTH_SECRET | あなたのシークレットマネージャー(Vault、AWS Secrets Manager、k8s Secret)。環境変数として注入します |
| 認証情報を含むデータベース URL | 同上 |
| OIDC クライアントシークレット | 同上 |
| OAuth プロバイダーのシークレット | 同上 |
| API プロバイダーのキー(メール、ストレージ、AI) | 同上 |
| DB に保存された設定 | 保存時に設定サービスによって暗号化 |
シークレットをアーティファクト(objectstack.json)、Docker イメージ、compose ファイル、Git に決して焼き込まないでください。Setup の設定 UI は、環境で管理された値をロックされた状態で表示するため、オペレーターが誤って上書きすることはありません。
ネットワークモデル
必須のインバウンド:
- イングレス / ロードバランサーから ObjectOS の
:3000(デフォルト)への HTTPS。
必須のアウトバウンド:
- セルフマネージドの ObjectOS のライセンスの検証。Enterprise のエアギャップライセンスはオフラインで検証されるため、そのための送信は不要です。
次の機能を設定した場合にのみ必要なアウトバウンド:
- データベース(Postgres / Mongo / Turso など)。
- S3 互換のストレージ(
storage機能を S3 アダプターで有効にした場合)。 - OIDC のディスカバリー URL(SSO を有効にした場合)。
- メールプロバイダーの API(Resend / Postmark)。
- AI プロバイダーの API(OpenAI / Anthropic / Google など)。
- Webhook の送信先。
送信のサーフェスはこれですべてです。さらに削減するデプロイメントについてはエアギャップを参照してください。
AI:ツール、承認、分離
AI Builder は、公開するものの中で最もセキュリティに敏感なサーフェスです。そのため、上記のすべてに加えて独自の強制の層を持っています。
AI が状態を変更する仕組み
モデルはデータベースに直接書き込むことはできません。状態が変わる唯一の方法は、構造化されたツール呼び出しを出力し、AI サービスがそれを受け取り、検証し、キューに入れることです。その流れは次のとおりです。
user prompt
→ model emits tool call (e.g. add_field { object: 'ticket', name: 'severity', type: 'select' })
→ AI service validates payload against the tool's Zod schema
→ if the tool is "mutating": queue as pending action (no state change yet)
→ human reviewer approves → mutation applied → audit row written
→ if the tool is "read-only": run immediately, response returned to modelファーストパーティのメタデータツールが 11 個あり(構築 → AI Builder を参照)、加えて、作成者が AI に公開したアクションごとに action_<name> ツールが 1 つあります。公開とは、UI なしで実行されるタイプ(script、flow、api)で、40 文字以上の ai.description とともに ai: { exposed: true } を指定することです。公開されていないアクションはエージェントからは見えず、呼び出されても拒否されます。ファーストパーティでもカスタムでも、すべてのツールは同じライフサイクルを持ちます。
権限のキー
| キー | 付与するもの |
|---|---|
ai:chat | 会話を行う、モデルを使う、エージェントに読み取り専用のツールを呼び出させる |
ai:complete | 生の補完エンドポイント(エージェントループなし) |
ai:conversations | 会話の一覧表示 / 確認 / 削除(RBAC のスコープに応じて自分のものまたはすべて) |
ai:agents | エージェントのメタデータの管理(呼び出すには ai:chat も必要) |
ai:tools | ツールのカタログの一覧表示 |
ai:execute | REST でツールを直接呼び出す(上級者向け。通常は常駐エージェントだけが必要とします) |
ai:read | 保留中のアクションのキューとモデルの一覧の読み取り |
ai:approve | キューに入った変更の承認 / 却下 |
ai:admin | AI サービスの完全な管理 |
重要な分離は ai:chat ≠ ai:approve です。アシスタントが機能するように、ほとんどのユーザーには ai:chat を付与し、ai:approve は構造的な変更をレビューすべき管理者 / アプリのオーナーに限定します。そうすれば、エンドユーザーは安全に「バイブビルド」できます。最悪の場合でも、他の誰かが承認しなければならない悪い変更をキューに入れるだけです。
テナントの分離
- エージェント、会話、ナレッジベース、保留中のアクションは、1 つの Environment(テナント)にスコープされます。テナント A は、同じマーケットプレイスのパッケージから同じエージェント定義をインストールしていても、テナント B の会話、AI が提案したツール、ナレッジのコーパスを見ることはできません。
- メタデータツール(
create_object、add_fieldなど)は、呼び出し元のテナントのアクティブなパッケージに対して動作します。その外には届きません。 - ツールの入力は CEL で検証され、エンジンは予約されたシステムパッケージ(
sys.*)や他のテナントのオブジェクト名への参照を拒否します。
監査イベント
監査機能が読み込まれている場合:
ai.chat.message:ユーザー / アシスタントのすべてのメッセージ。モデルとトークン数付きai.tool.call:ツール名、検証済みの入力、完全な出力(またはエラー)ai.pending_action.queued:提案された変更と、その完全な差分ai.pending_action.approved/.rejected:誰が、いつ、なぜ決めたかai.metadata.applied:メタデータストアへの実際の書き込みと、その差分
これらの行は改ざんできず、セキュリティレビューやチャージバックのためにエクスポートできます。(プロバイダー、モデル、ユーザー)ごとのトークン数が、コストの配分に使われます。
プロンプトインジェクションへの姿勢
間接的なプロンプトインジェクション(エージェントが取得したドキュメント内の悪意あるコンテンツなど)は現実のリスクです。ObjectOS は構造的に影響範囲を縮小します。
- AI はツールの検証を回避できません。悪意のあるペイロードを出力するよう説得されたとしても、Zod スキーマが不正な形式の入力をエンジンに届く前に拒否します。
- 変更を行うツールは常にキューに入ります。注入されたプロンプトが黙ってデータベースに書き込むことはできません。
- ツールの呼び出しは、モデルのサービスアカウントの権限ではなく、エンドユーザーの権限を継承します。ユーザーが UI や REST で自分ではできないことを、AI を使って行うことは決してできません。
- エージェントに読み込まれるスキルは、バージョン管理された明示的なものです。構築 → IDE スキルと構築 → AI Builder を参照してください。
外部の AI プロバイダーへのデータの流れ
プロバイダー(OpenAI、Anthropic など)を設定した場合、ネットワークの外に出るのは次のものだけです。
- モデルが必要とする会話の履歴
- ツールの定義(名前、JSON スキーマ。レコードのデータは含みません)
- モデルが続行するために必要なツールの出力(ユーザーが明示的に求めたクエリの結果など)
エアギャップのデプロイメントでは、AI サービスをローカルの Ollama / vLLM / TGI のエンドポイントに向ければ、同じ流れが境界の内側にとどまります。
脆弱性の開示
セキュリティの問題は security@objectstack.ai に非公開で報告してください。1 営業日以内に回答します。セキュリティの問題について、公開の GitHub issue を作成しないでください。
サプライチェーン
- Community イメージ
ghcr.io/objectstack-ai/objectstackは公開されています。ObjectStack のリリースごとに、オープンソースの objectstack-ai/objectstack リポジトリからビルドされて公開され、タグは内部の ObjectStack CLI のバージョンを反映しています。 - Enterprise イメージはライセンスされたイメージで、プライベートレジストリから取得します。レジストリの認証情報はライセンスとともに提供されます。デプロイを参照し、Docker の説明に従って本番の前にイメージを検証してください。
- すべての
@objectstack/*パッケージは、ソースが GitHub で公開されています。Apache-2.0 で、難読化はありません。 - 本番では正確なイメージをひとつに固定し、ダイジェストで固定してください。決して動かないのはダイジェストだけです。Community では、正確なバージョンタグ(
X.Y.Z)を実行し、そのダイジェストを固定します。latestのような移動するタグはリリースのたびに付け替えられ、公開済みのバージョンの再ビルドは、そのX.Y.Zタグを新しいバイトに再プッシュします。Enterprise では、リリースノートに記載されたダイジェストを固定します。Docker を参照してください。
推奨される堅牢化のチェックリスト
- 本物の証明書で、エッジで TLS が終端されている。
-
OS_AUTH_SECRETが 32 バイト以上のランダムな値で、シークレットマネージャーにある。 - データベースの接続が TLS を使っている。
- TLS の検証後に HSTS が有効になっている。
- CORS のオリジンが明示されている(認証情報と
*を決して組み合わせない)。 - 認証エンドポイントにレート制限がある(
10/min/IPを推奨)。 - 監査の保持期間がポリシーと一致している。
- 人のアカウントには OIDC、マシンのアカウントには API キー。
- バックアップと復元の予行演習を実施し、所要時間を計測した。
- 否定テスト:組織をまたぐアクセスが拒否される、フィールドのセキュリティが保たれる、期限切れのセッションが拒否される。
- イメージが移動するタグではなく、ダイジェストで固定されている(Community では、正確なバージョンタグ
X.Y.Zのダイジェスト)。 - 各リリースの前に、CI で
os doctorがクリーンである。
本番稼働の完全なチェックリストは本番環境への準備を参照してください。