メインコンテンツへスキップ

[Brazil調査] 列単位の query_range ACL と全文検索:Restricted Search の Enabled で結果が変わる


    ロールを持たない利用者には、項目の値を表示しない設定にしてあるとします。それでも全文検索の入力欄に語を打つと、その項目にだけ含まれる語でレコードがヒットする場合があります。ヒットしたという事実だけで、見えないはずの値を言い当てられるのです。

    Brazil では、全文検索エンジン Zing が列単位の query_range ACL を守るようになりました。確認用の新ツール Text Search Query Range ACL Checker も入っています。Australia から Brazil へメジャーアップグレードした PDI で、検索がどう変わるかを実際に試しました。

    検証環境:Brazil PDI(Australia からメジャーアップグレード)/ OOTB / 2026-10-09 確認

    画面で確かめた要点

    • Brazil の Zing は、インデックスに含まれる列の query_range ACL を検索時にも評価する

    • v3 形式のインデックスでは、Restricted Search が Enabled の場合、権限のない列が1つでもあると、その利用者の検索結果は0件になる

    • v4 形式のインデックスでは、権限のない列だけを照合から外し、ほかの列で検索結果を返す

    • v3 形式の36個のインデックスのうち、アップグレード時に Restricted Search が Enabled になっていたのは17個。残りは Disabled のまま

    • Checker は /ts_query_range_acl_checker.do で開く。実際に試したところ、列ACLを足すとブロックされるロール・列・ACLを一覧にして出した

    Checker の場所

    公式ドキュメントでは、Brazil の変更点を次のように説明しています。

    Improve security for search with Zing's support for column-level query_range read ACLs on table columns that are indexed for search. When searching tables with legacy v3 format text indexes, Zing only displays search results if the current user's role has access to all of the table's indexed columns. For tables with v4 format text indexes, Zing only displays search matches in indexed columns accessible by the user's role.

    (訳:検索用にインデックス化された列に対する、列単位の query_range 読み取りACLをZingが扱えるようになった。旧来のv3形式のインデックスでは、利用者のロールが表のインデックス列すべてにアクセスできる場合に限り、検索結果を表示する。v4形式では、利用者のロールがアクセスできる列の一致だけを表示する)

    引用元:Combined Zing text indexing and search engine release notes for upgrades from Australia to Brazil

    手順は別のページにまとまっています。ロールは ts_admin、URL は /ts_query_range_acl_checker.do です。Australia のリリースノートには、この件の記載がありません。

    引用元:Verify that user roles have access to your searchable tables

    アップグレードした PDI では、System Diagnostics アプリケーションに「TS Query Range ACL Checker」というモジュールが追加されていました(2026-03-23 付けのレコード)。裏には次の4つがあります。

    • UI ページ ts_query_range_acl_checker

    • Script Include TSQueryRangeACLChecker と TSQueryRangeACLAjax(呼び出しは ts_admin ロールだけ)

    • システムプロパティ glide.ts.acl_checker.debug(デバッグログ)と glide.ts.query_acl_checker_debug_raw_json(生の JSON 表示)

    • Checker の Feature Property 欄に出るプロパティ glide.ts.restrict_search_calgary(true (default) と表示。sys_properties に行はなく、既定値の表示です)


    画像

    画像の見方です。①の説明文は、Brazil 以前は表単位の読み取りACLしか見ていなかったことと、今回の変更が Blind Query Attacks(検索結果の有無から値を推測する攻撃)の緩和策であることを述べています。②は機能のプロパティです。③の列が、インデックスごとに列単位の評価が有効かどうかを示します。

    関連記事との関係

    query_range ACL が「絞り込みと並び替えで値が漏れる抜け道」を塞ぐ仕組みであることは、ServiceNowのquery_range ACLとは? 自動ロードで何が変わるかをAustralia実機で確認で扱いました。Zing の位置づけはZingの正体に書いています。

    Brazil では、この query_range ACL が全文検索の経路にも効くようになりました。Australia までは、一覧の絞り込みで拒否される列でも、全文検索なら値を含む語でヒットする経路が残っていました。

    結果を決める2つの設定

    結果の分かれ方を先に図にします。


    画像

    起点は全文検索、緑は結果が返る経路、赤は0件になる経路、橙は列ACLが効かない経路です。

    • v3以前:権限のない列があると、Enabled の表は0件を返します

    • v3以前で Disabled の表:列ACLを評価しないため、従来どおり結果が返ります

    • v4:権限のない列を照合から外し、ほかの列で結果を返します

    Restricted Search は表ごとの属性(ts_v3_unrestricted_search_table)で切り替えます。Checker の「Enable Restricted Search」ボタンは、この属性を表の辞書レコードに書き込みます。属性を false にした表が Enabled です。

    テストユーザーでの検索結果

    cmn_location(拠点)の street 列で試しました。v3 形式のインデックスで、Brazil へのアップグレード時に Enabled になった表です。使ったものは次のとおりです。

    • ロールを持たないテストユーザー(kiji_test_zing)

    • 検証用の拠点レコード1件。street にだけ Zephyrquartz という語を入れ、名前には入れていない

    • cmn_location.street への一時的な列単位 query_range ACL。必要ロールは、テストユーザーが持たない一時ロール

    背景スクリプトでテストユーザーの検索を実行し、結果の件数を数えました。

    • ACLなし:Zephyrquartz で1件、kijiloc(名前の語)で1件ヒット

    • 列ACLを追加して Enabled:Zephyrquartz・kijiloc・Baltimore(既存の別拠点の語)がすべて0件。street の絞り込みは403

    • 同じ状態で Disabled に切り替え:Zephyrquartz で1件ヒット。street の絞り込みは403のまま

    • 一時ロールを付与して Enabled:Zephyrquartz で1件ヒット。絞り込みも通る

    • ロールを外して Enabled:再び0件


    画像

    表の内容を文字でも書き出します。

    • ACLなし:street の絞り込みは通り、全文検索はヒット

    • 列ACLあり・Enabled:絞り込みは403、全文検索は0件

    • 列ACLあり・Disabled:絞り込みは403、全文検索はヒット

    • ロール付与・Enabled:絞り込みは通り、全文検索もヒット

    Disabled の行が、冒頭の問いへの答えです。street の絞り込みは拒否されるのに、全文検索には street だけに含まれる語でヒットします。語を変えながら試せば、値の中身を少しずつ特定できる状況です。Enabled にすれば、この経路は塞がります。

    引き換えに、Enabled では street に権限のない利用者の検索が、拠点の名前で探すときも含めて0件になります。ACLを足した列が1つあるだけで、その表を検索するロール全体が影響を受けます。

    Checker の評価結果

    列ACLを足した状態で、Checker の Evaluate を押しました。


    画像

    結果は次のとおりです。

    • ①止まるのは、ロール public と sn_walkup.walkup_login の2つ。列は street、ブロックしているACLは追加した1件

    • ②の対処は、列の辞書に ts_v3_unrestricted_search_col を true で付ける案。画面には、その列が権限に関係なく検索できるようになる警告が出る

    • 対処案の2つ目は、ブロックしているACLにロールを足す案

    • ③の対処は、インデックスを v4 に上げる案。表の行数が100万行未満なら出る(cmn_location は428行)

    対処案を足した後は、同じ Evaluate をもう一度押して、列が一覧から消えることを確認します。ACLを削除した直後に再評価すると、ACLの sys_id が空のまま IMPACTED と出る瞬間がありました。ACLを消した直後は、再評価までに少し間を置いたほうが安全です。

    インデックスの評価結果

    Checker と同じ API(getQueryRangeAclEvaluationResultForIndexes)で、v3 形式のインデックスを評価しました。ts_index_name の形式は、v3 が37個(sys_metadata を除くと36個)、v4 が4個です。評価できたのは32個で、sys_app_version・sys_package・sys_import_set_row・task は評価が終わらず、確認できていません。

    評価できた32個の内訳です。

    • 影響あり(IMPACTED):11個。すべて Disabled のままで、public ロールが止まる表が多い

    • 影響なし:21個。うち15個が Enabled、6個が Disabled

    • 影響ありの例:sys_user_group(止まる列は roles・sys_tags・default_assignee など)、kb_knowledge_base、sla(asset ロール)、ci_diagnostic_category(maint ロール)

    Enabled の表は17個あり、アップグレードの途中(2026-10-08 15:51〜16:31)にシステムが属性を false で書き込んでいました。影響のなかった表を Enabled にして、影響のあった表を Disabled のままにする作りと読み取れます(私の推測です)。

    実務では、影響ありの11個を一覧にして、止まるロールと列を確認するところから始めます。そのまま Enabled にすると、該当ロールの検索が0件になります。

    Query ACL の目的

    Query ACL の公式ページには、使いどころが具体例で書かれています。

    Query ACLs are powerful tools against blind query attacks, where an attacker blindly queries the data to extract information from results, even when they can't see the values.

    (訳:Query ACL は、ブラインドクエリ攻撃への有効な手段になる。攻撃者は値が見えなくても、問い合わせの結果から情報を引き出す)

    引用元:Query ACLs

    同じページには、給与テーブルの例があります。自分の行は見えても、給与が2つの境界の間にある利用者を探す範囲検索を打つ理由がありません。salary に query_range ACL を置けば、その検索を止められます。HR の例では、自分の社会保険番号しか見えない利用者が、他人の番号を探る検索を打てないように ACL を置きます。

    公式の説明は一覧の絞り込みが中心です。Brazil の変更は、この考え方が全文検索の経路にも広がったことを意味します。表示の制御だけで守れていると考えていた表は、全文検索の経路も棚卸しの対象になります。

    v4 への上げ方と注意点

    公式の「Configure a table for indexing and searching」には、インデックス形式を上げる手順があります。要点は次のとおりです。

    • 複数テーブルをまたぐ検索や、BM25 というスコアリングを使いたい表は、v4 へ上げる

    • Format が灰色の表(すでにインデックス済み)は、いったん Submit して Text Index Configurations でその表を開き、Related Links の Show index name record を経由してから Upgrade to V4 を選んで Submit する。Format が灰色でなければ v4 を選んで Submit する

    • 上げた後は、その表を複数テーブルのインデックスグループに入れられる

    引用元:Configure a table for indexing and searching

    Checker の説明には、v4 へ上げると索引の容量が増え、順位づけも変わりうると書かれています。検索結果の並び順を業務で使っている表は、上げる前後で同じ語の結果を比べておく必要があります。複数テーブルの検索には、次の公式手順があります:Configure a text index group to search across multiple tables。

    対象の表が多いときの進め方

    表ごとに確認する項目は、表名、Enabled か Disabled か、IMPACTED か NOT_IMPACTED か、止まるロール、止まる列の5つです。

    • Checker の結果から、まず IMPACTED かつ Disabled の表を洗い出します。ここが、列ACLがあるのに全文検索で漏れる可能性のある表です

    • 次に NOT_IMPACTED かつ Disabled の表を確認します。今は影響がなくても、あとから列ACLを足した時点で漏れる側に回ります

    • 最後に、Enabled の表で止まっている利用者から問い合わせがないかをヘルプデスクに確認します

    Checker 自体は ts_admin ロールだけが呼べます。権限のないユーザーで開くと、Ajax 側がエラーを返す作りです。

    実務での確認手順

    1. Checker を開き、Query Range ACL enforced が Disabled の表を絞り込みます

    2. 重要な表から Evaluate を押し、止まるロールと列をメモします

    3. 止まる列ごとに、次の3案から選びます

    • 列の query_range ACL にロールを足す(その列の検索を許可してよいロールに限って追加します。検索停止は解消しますが、検索できる範囲は広がります)

    • 列を unrestricted にする(その列は権限に関係なく検索できるため、機密列には使えません)

    • インデックスを v4 に上げる(権限のない列だけが照合から外れます。ストレージ増と順位の変化に注意)

    1. 対処後に Evaluate を再実行し、列が一覧から消えたら Enable Restricted Search を押します

    2. 権限の違う2つのテストユーザーで、同じ語の検索結果を比べます


    画像

    表の内容を文字でも書き出します。

    • v3(cmn_location):権限のない列の語も、別の列の語も0件

    • v4(sys_user):権限のない列の語は0件、別の列の語はヒット

    v4 の挙動は sys_user で確かめました。city にだけ含まれる語(Qzvortown)と、title にだけ含まれる語(Zephyrtitle)を持つテスト利用者を作り、sys_user.city に一時ACLを足して検索しています。結果は、city の語が0件、title の語が1件でした。

    実機で気づいたこと

    Disabled の表では効かない

    Disabled の表では、列ACLを足しても全文検索は従来どおり結果を返しました。ACLを足せば守られているつもりでも、Checker の Enabled 列を見ないと、守られているかが分かりません。今回の cmn_location は Enabled だったため効きましたが、影響の出た11個は Disabled のままです。

    1列のACLが表全体に効く

    v3 形式では、street にACLを足しただけで、拠点名や別の拠点の語でも0件になりました。検索の使い勝手を優先する表は、v4 への移行か、列を unrestricted にするかを先に決めておきます。

    ACLの件数

    query_range ACLの総数は約1万件です。2026-10-01以降に作成された ACL は31件で、Targeted Communications 系は非アクティブ、MID Server Infrastructure と ServiceNow IDE 系は有効でした。今回の変更はACLの数ではなく、既存の列ACLを全文検索が見るようになった点にあります。

    検証範囲とおことわり

    • 検証した環境は Australia から Brazil(Patch 0)へアップグレードした PDI です。新規インスタンスの挙動は確かめていません

    • 影響の評価ができたのは v3 の32個です。task など4個のインデックスは確認できていません

    • v4 の挙動の確認は sys_user の1表、v3 の確認は cmn_location の1表だけです

    • 「列を unrestricted にする」案と、Upgrade to V4 のボタンは押していません。効果は公式ドキュメントの記述にもとづきます

    • 検証で作成したテストユーザー2件、拠点1件、一時ロール1件、一時ACL2件は、すべて削除して確認しました。cmn_location の Restricted Search は元の Enabled に戻しました

    • Brazil のドキュメントに記載のあるロール ts_admin の権限は、Checker の Script Include の記述でも確認しました

    公式ドキュメント

    付録:引用した説明を実機で確認する方法

    • Checker のページ:/ts_query_range_acl_checker.do

    • インデックスの形式:/ts_index_name_list.do

    • 関連プロパティ:/sys_properties_list.do?sysparm_query=nameLIKEglide.ts.acl_checker^ORnameLIKEquery_acl_checker

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ