
NocoDBの共有ベースリンクは、実際のベースメンバーを招待でき、共有の取り消し後も存続する可能性がある
NocoDBの共有ベースリンクが実際のベースメンバーを招待し、共有取り消し後も存続する可能性
NocoDBをレビュー中に、シンプルなセキュリティの疑問を抱いてこの問題を見つけました。
公開共有ベースリンクが、一時的な共有アクセスから実際の認証済みベースメンバーシップへと境界を越えることができるか?
このケースでは、答えはイエスでした。
xc-shared-base-idのみで認証された共有ベースセッションは、ACLの目的上、通常のベースビューアとして扱われました。ビューアの権限が依然としてメンバー管理エンドポイントに到達できたため、共有ベースUUIDのみを持つユーザーは、既存のベースメンバーを列挙し、任意のメールアドレスを実際のメンバーとしてベースに招待することができました。
その招待されたユーザーは、通常のサインアップフローを通じて招待を受け入れ、標準の認証済みアカウントを取得し、所有者が共有ベースリンクを無効にした後でもベースへのアクセスを維持できました。
その問題がCVE-2026-46552となりました。
プロジェクト: NocoDB
確認された影響バージョン: 0.301.3
これはNocoDBに影響を与えました。公式サイトでは、NocoDBは35,000以上の組織に信頼され、2000万以上のダウンロードがあるとされています。 また、サイトにはAccenture、Western Digital、Hyundai、Walmart、PwC、Bosch、American Expressなどの企業も掲載されています。
public shared-base link -> xc-shared-base-id treated as normal base viewer -> viewer ACL reaches member-management endpoints -> attacker lists base users and invites arbitrary email -> invited user redeems normal signup token -> durable authenticated base access survives shared-link revocation
NocoDBは、ブラウザベースのベースアクセス、共有、メタデータ管理、ユーザーメンバーシップワークフローを提供するデータベース指向のコラボレーションプラットフォームです。
つまり、その共有モデルは実際のセキュリティ境界です。
ここで重要なのは、共有ベースリンクが共有コンテンツを読み取れるかどうかではありませんでした。
本当の質問はこうでした。
公開共有プリンシパルが、認証されたベースメンバーのみに属するべきアクションを実行できるか?
このケースでは、実行できました。
公開共有機能は過小評価されがちです。
それは間違いです。
アプリケーションが以下をサポートすると、
主なリスクはデータ露出だけではありません。
より深刻なリスクは境界の崩壊です。
これが本当の問題でした。
これはログイン検証のバグではありませんでした。 トークン偽造の問題ではありませんでした。 パスワードリセットの欠陥でもありませんでした。
これは古典的な認可境界の失敗でした。
私はランダムにエンドポイントをプローブして興味深い応答を期待する方法ではアプローチしませんでした。
より強力な方法は、最初に最も価値の高い信頼境界を特定することでした。
NocoDBの場合、それは以下の境界でした。
これらの2つの状態は交換可能であるべきではありません。
共有ベースリンクは、スコープが限定され、取り消し可能なリンクベースのアクセスを表すものとされています。 ベース内で新しい長期間有効なプリンシパルを作成できるべきではありません。
これがまさにここで破られた境界です。
脆弱性は、共有ベースアクセスが通常のACLパスにどのように統合されたかに起因しています。
共有ベースのフロントエンドフローでは、通常の認証ヘッダーが削除される一方でxc-shared-base-idが注入されました。
その後、バックエンドでBaseViewStrategyがxc-shared-base-idを受け入れ、共有リンクを共有ベース構成から派生した通常のroles / base_rolesに直接変換しました。
それが最初の問題でした。
2番目の問題は、ビューアレベルの権限にまだメンバー管理アクションが含まれていたことです。
ACLレイヤーでは、ProjectRoles.VIEWERが以下に到達できました。
baseUserListuserInviteこれらの権限は通常のメタルートを保護していました。
GET /api/v2/meta/bases/:baseId/usersPOST /api/v2/meta/bases/:baseId/usersそのため、公開共有セッションは実質的に、実際のベース参加者向けのメンバーシップエンドポイントにアクセスすることが許されていました。
最後のステップは招待フロー自体にありました。
BaseUsersService.userInvite()はロールの権限をチェックし、その後以下を作成しました。
invite_tokenを持つ実際のユーザー行そして共有ベースセッションの場合:
invited_byはnullになりましたなぜならリクエストの背後に実際の認証された招待者IDがなかったからです。
これがバグの全チェーンです。
共有ベースリンクを所有していれば十分だったからです。
攻撃者は以下を必要としませんでした。
xc-auth悪用チェーンは単純でした。
これにより、取り消し可能なリンク共有が永続的なメンバーシップに変換されます。
重要な違いは、取り消し後も持続することです。
これは単に次のようなものではありませんでした。
「ビューアがビューアエンドポイントを呼び出せる」
脆弱なプリンシパルは通常の認証されたビューアではありませんでした。
それは公開共有セッションでした。
それが重要なのは、アプリケーションが一時的なリンクスコープのプリンシパルを、以下のことを行うのに十分信頼できるかのように扱ったからです。
本当の質問はこうではありませんでした。
「共有ユーザーは共有データを読み取れるか?」
本当の質問はこうでした。
「公開共有アクセスを、共有取り消し後も存続する永続的な認証アクセスに変換できるか?」
答えはイエスでした。
だからこそ、これは単なる驚くべきアプリケーションの動作ではなく、実際の認可の脆弱性なのです。
これをローカルで以下の環境で検証しました。
0.301.3dac49b0122c5ee655fb8f46a1b6e42dfeec1f3adhttp://127.0.0.1:8080再現は単純でした。
まず、通常の所有者アカウントとしてサインインし、新しいベースを作成し、テーブルを作成し、viewerとして共有ベースアクセスを有効にしました。
PATCH /api/v2/meta/bases/<baseId>/shared
Content-Type: application/json
{
"roles": "viewer"
}
これにより共有ベースUUIDが返されました。
その後、xc-authを送信せずに、以下のみを使用しました。
xc-shared-base-id: <sharedBaseUuid>
そのヘッダーのみを使用して、以下を呼び出しました。
GET /api/v2/meta/bases/<baseId>/users
これにより200 OKが返され、メールアドレスを含む実際のベースメンバーが露出しました。
引き続きxc-shared-base-idのみを使用して、以下を呼び出しました。
POST /api/v2/meta/bases/<baseId>/users
Content-Type: application/json
{
"email": "[email protected]",
"roles": "viewer"
}
これも200 OKを返しました。
メール配信なしのローカルラボ検証として、SQLiteメタデータベースで直接以下を確認しました。
nc_users_v2に招待されたユーザーが非NULLのinvite_tokenで含まれていたnc_base_users_v2に対象ベースの実際のメンバーシップ行が含まれていたinvited_byがNULLだった次に、通常のサインアップフローを通じて招待を受け入れました。
POST /api/v2/auth/user/signup
Content-Type: application/json
{
"email": "[email protected]",
"password": "Password123.",
"token": "<invite_token>"
}
返されたxc-authを使用して、以下を呼び出しました。
GET /api/v2/meta/bases/<baseId>/tables
これにより200 OKが返されました。
最後に、所有者として共有ベースリンクを無効にしました。
DELETE /api/v2/meta/bases/<baseId>/shared
その後:
xc-shared-base-idによる共有リンクアクセスは401で失敗xc-authを使用した招待アカウントは依然として200で成功200200200200200401200これにより中心的なセキュリティ主張が確立されました。
共有ベース招待が1回成功しただけで、認可の失敗を示すには十分だったでしょう。
しかし、完全な検証チェーンが重要だった理由は2つあります。
これは単なるエンドポイントの露出ではなかったことを示しました。
公開共有セッションは単に制限されたAPIに到達しただけではありませんでした。 特権変換の完全なチェーンを完了しました。
これが自己取り消しではないことを証明しました。
より深刻な影響は共有リンク無効化後に現れました。
それが一時的なリンクアクセスを永続的なアクセス持続に変えたのです。
この脆弱性により、共有ベースリンクを持つ誰でも以下が可能になります。
主な影響は機密性です。攻撃者は通常の認証アカウントを通じて共有ベースデータへの長期的な読み取りアクセスを維持できるためです。
また、完全性への影響もあります。公開共有プリンシパルがベースに新しいメンバーを追加することでアクセス制御状態を変更できるためです。
これは通常のデータ漏洩よりも深刻な結果です。 匿名共有と認証メンバーシップの間の特権境界の破綻です。
この問題は、機密性への影響を伴うクロススコープ認可の欠陥として適切に分類されます。
CVSS:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
このベクトルはここでの核となる動作に適合します。
修正の方向性は単純です。
共有ベースセッションはメンバー管理機能を継承すべきではありません。
最低限:
xc-shared-base-idを通じて到達可能なすべての権限からbaseUserListとuserInviteを削除するGETやPOST /api/v2/meta/bases/:baseId/usersなどのベースメンバーシップエンドポイントを呼び出せないように明示的なブロックを実施するこの問題は、コミットdac49b0122c5ee655fb8f46a1b6e42dfeec1f3ad上のNocoDB 0.301.3に対してローカルで検証されました。
報告書は以下を示しました。
xc-shared-base-idから通常のベースロールへのACLマッピングこの問題には次のIDが割り当てられました。
CVE-2026-46552
ここでの重要な教訓は単純です。
共有リンクアクセスは信頼されたメンバーシップと同じではない。
多くのシステムは、これら2つの概念を同じロールモデルに統合してしまうことで問題に陥ります。
共有リンクは運用上はビューアアカウントと似ているように見えるかもしれませんが、信頼の前提は異なります。
その低い保証のプリンシパルが管理アクションを実行したり新しい永続的IDを作成したりできる場合、共有境界はすでに破られています。
それが本当の教訓です。
この脆弱性は、認証を完全にバイパスすることに関するものではありませんでした。
それは、分離されたままであるべきだった2つの信頼レベルを統合することに関するものでした。
NocoDBでは、共有ベースリンクは共有コンテンツへの一時的で取り消し可能なアクセスを提供することを意図されていました。 その代わりに、メンバーの列挙、実際のユーザーのベースへの招待、および共有取り消し後も存続する永続的な認証メンバーシップへの公開共有アクセスの変換に使用される可能性がありました。
だからこそ、これがCVE-2026-46552となったのです。