カスタマーサポートのチャットボットは、暴力犯罪やヘイトスピーチに関するプロンプトには応答しないようにします。この カスタムルール はリクエストをブロックし、アプリケーションが解析してユーザーへ表示できる JSON レスポンスを返します。
-
受信リクエストが次に一致する場合:
フィールド 演算子 値 LLM の不安全トピックカテゴリ is in S1: Violent CrimesS10: Hateエディターを使う場合の式:
(any(cf.llm.prompt.unsafe_topic_categories[*] in {"S1" "S10"})) -
アクション: ブロック
-
レスポンスタイプ: カスタム JSON
-
レスポンス本文:
{ "error": "content_policy", "message": "Your message could not be processed because it touches on a topic outside this assistant's scope. Please rephrase your question." }
アプリケーションは 200 以外のレスポンスを確認し、ユーザーへ message フィールドを表示できます。生のブロックページではなく、会話の流れを保てます。
このルールは、AI Security for Apps の インジェクションスコア と Bot Management、リクエストの国を組み合わせ、自動送信からの確度の高い攻撃に絞ります。シグナルを 1 つだけ使うより、誤検知を大きく減らせます。
-
受信リクエストが次に一致する場合:
エディターに次の式を入力します。
(cf.llm.prompt.injection_score lt 25 and cf.bot_management.score lt 10 and ip.geoip.country ne "US") -
アクション: ブロック
このルールが対象にするのは、次を同時に満たすリクエストです。
- プロンプトインジェクションの可能性が高い(スコアが 25 未満)。
- 実際のブラウザーではなく、自動ツールからの送信である(ボットスコアが 10 未満)。
- 米国以外からの送信である。国コードは、ユーザーがいる地域に合わせて変更してください。
シグナルが 1 つだけだと、それぞれ誤検知が出ることがあります。組み合わせると、自動送信によるプロンプトインジェクション攻撃と強く結びつくパターンを特定できます。
金融サービスアプリは、社内エージェントからのクレジットカード番号や銀行口座番号は正当に扱いますが、外部ユーザーからの同じ種類の PII はブロックすべきです。このルールは、リクエストの 自律システム番号(ASN) で、社内トラフィックと公開トラフィックを区別します。
-
受信リクエストが次に一致する場合:
エディターに次の式を入力します。
(any(cf.llm.prompt.pii_categories[*] in {"CREDIT_CARD" "BANK_ACCOUNT"}) and ip.src.asnum ne 13335)13335は、自組織の ASN に置き換えてください。 -
アクション: ブロック
-
レスポンスタイプ: カスタム JSON
-
レスポンス本文:
{ "error": "pii_blocked", "message": "Financial account information cannot be submitted from external networks. If you are an internal agent, connect to the corporate network and try again." }
社内ネットワーク上の社内エージェント(ASN で識別)は、業務の一環として金融系 PII を AI アシスタントへ送信できます。外部ユーザーはブロックされます。より強い本人確認として、Access のサービストークンや mTLS を組み合わせてさらに絞り込めます。
WAF ルールがリクエストをブロックすると、Cloudflare はブロックレスポンスをエンドユーザーではなく、アプリケーションへ返します。アプリケーションはそのレスポンスを扱い、何を表示するかを決める必要があります。エラー処理がないと、ユーザーに生の HTML エラーページや壊れた UI が見えることがあります。
体験を滑らかに保つためにできることは、次の 2 つです。
成功以外のレスポンスを受け取ったときにアプリケーションが表示する、わかりやすい既定メッセージを定義します。ブロックルールの設定方法に関係なく使えます。既定の Cloudflare ブロックページは HTML を返すため、JSON ベースのチャット UI が壊れることがあります。
// Define a user-friendly fallback message. This is what the user will see
// any time the request is blocked or something unexpected happens.
const FALLBACK = "Sorry, I can't process that request. Please try rephrasing.";
const resp = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt: userMessage }),
});
// If the response is not 2xx, show the fallback instead of trying to parse
// the body. This safely handles the default Cloudflare block page (which is
// HTML) without breaking your UI.
if (!resp.ok) {
await resp.text(); // consume the body so the connection is released
showError(FALLBACK);
return;
}
const data = await resp.json();
showMessage(data.message);より細かく制御するには、ブロックルールに カスタム JSON レスポンス を設定します。例: { "message": "That question is outside this assistant's scope." }。アプリケーションはレスポンスを解析し、カスタムメッセージがあればそれを表示し、なければ既定へフォールバックできます。
const FALLBACK = "Sorry, I can't process that request. Please try rephrasing.";
const resp = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt: userMessage }),
});
if (!resp.ok) {
// Check the content type to determine if the response contains a custom
// JSON error from your WAF rule, or something else (like the default
// Cloudflare HTML block page, or a DDoS / Bot Management challenge).
const ct = (resp.headers.get("content-type") || "").toLowerCase();
if (ct.includes("application/json")) {
// The WAF returned your custom JSON response. Parse it and show the
// message you configured in the rule. Fall back to the default if the
// field is missing or empty.
const data = await resp.json();
showError(data.message || FALLBACK);
} else {
// The response is not JSON — most likely the default Cloudflare HTML
// block page. Discard the body and show the friendly fallback.
await resp.text();
showError(FALLBACK);
}
return;
}
const data = await resp.json();
showMessage(data.message);