The Google Model Armor policy sends request prompts and model responses to
Google Cloud Model Armor
and applies the verdict at the gateway. One call covers five filters: sensitive
data, Responsible AI categories, prompt injection and jailbreak, malicious URLs,
and CSAM.
It either blocks the request, or rewrites it in place — replacing
detected sensitive data with the de-identified text Model Armor itself returns,
before the request reaches the model. The model never sees the original.
This page covers the whole setup, from an empty Google Cloud project to a
verified policy. No prior Model Armor experience is assumed.
This policy puts a synchronous call in front of every request. How much that
costs depends on your region, your template and the size of the prompt, so
measure it in your own environment rather than assuming. Enable the request leg
first, measure, and only then decide about the response leg — it adds a second
call per turn.
Part 1 — Build the template in Google Cloud
Everything in this part happens in your own Google Cloud project. TrustGate
never creates or changes anything there.
Choose a region and enable the API
Model Armor has no global endpoint. It is reachable only through regional
hosts, and the gateway derives the host from the Location you will enter in
the policy. Pick a region close to your gateway: every request makes this round
trip.Enable the API in the project that will own the template:Every resource below must be created in that same project and that same
region. A template created in a different region is invisible to the gateway
and calls fail with a template-not-found error. Create the inspection template (only if you want masking)
Skip this step and the next one if you only want to block sensitive data and
never rewrite it.In the Google Cloud console go to Security → Sensitive Data Protection →
Configuration → Templates → Create template.Click Create and copy the template’s full resource path — you will paste it
into the Model Armor template: Create the de-identify template (this is what makes masking work)
Return to Create template and this time choose De-identify (remove
sensitive data).Click Create and copy its resource path:Without a de-identify template there is no masking, and the request is blocked
instead. An inspect-only configuration reports what it found but returns no
rewritten text, so the gateway has nothing to put back. Rather than forward the
original, it refuses the request. Choosing Anonymize in TrustGate without this
template turns the policy into a blocking one.
Create the Model Armor template
Go to Security → Model Armor → Create template.Then enable the detections you want:CSAM detection is always on in Google’s template and cannot be turned off.Click Create.You now have the three values the policy needs: the project, the region,
and the template ID.
Part 2 — Grant the gateway access
TrustGate must prove to Google that it may call Model Armor in your project.
There are three ways, and the first is the one to prefer.
Method A — Impersonation (recommended)
The keyless path. You create a service account in your project, give it access to
Model Armor, and allow the gateway’s identity to borrow it for a few minutes at a
time. No secret of yours is ever stored, because an email address is useless
without the grant you control.
Create a service account and give it Model Armor access
roles/modelarmor.user is not part of Editor or Owner. Granting it needs the
resourcemanager.projects.setIamPolicy permission, which project editors do not
have. If the second command is refused, a project administrator has to run it.
Let the gateway borrow that service account
Ask your NeuralTrust contact for the gateway’s service account identity, then
grant the token-creator role on the service account you just created — not on
the project:This is the gateway’s only access, it is scoped to that one service account, and
removing this single binding cuts it off without touching anything else in your
project.IAM changes take a minute or two to propagate. A permission error on the first
call right after granting is expected — retry before changing anything. Keep the email
model-armor-caller@YOUR_PROJECT.iam.gserviceaccount.com is what goes into the
policy. Nothing else.
Method B — Service account key
Create a key for the service account from Method A and paste the JSON into the
policy.
The key is stored as provided and is shown again whenever the policy is
reopened. Treat it like any other credential: prefer impersonation where it is
available, rotate the key on your normal schedule, and delete it once
impersonation becomes possible.
Method C — Workload Identity
Leave both credential fields empty and the gateway calls Model Armor as its own
ambient identity. That identity needs roles/modelarmor.user on your project.
This only fits a self-hosted, single-tenant deployment: on a shared deployment
every policy would call as the same identity, which would need a grant in every
tenant’s project.
Fill in at most one credential field. A policy with both the email and the
key is rejected on save.
Open Policies → Catalog → Google Model Armor.
Google Cloud connection
Block on
Five toggles — Sensitive data, Responsible AI, Prompt injection &
jailbreak, Malicious URIs, CSAM. All five are active when none are
selected.
These decide what the gateway acts on, and are separate from what the Google
template detects. CSAM, for instance, is always detected by Model Armor; turning
the toggle off means the gateway records the finding without refusing the
request.
These toggles decide what is evaluated, not only what is blocked. Turning
off Sensitive data also turns off masking: the Sensitive data action below
has no effect unless that toggle is on.
Sensitive data
Sensitive data action — Block request (the default) or Anonymize.
Anonymize reinjects the de-identified text and lets the request continue; it
requires the de-identify template from Part 1.
When content is blocked
Block message — an optional message returned to the caller. The response
always names the filter that fired, with or without this.
Stage, mode and scope
The request leg is always evaluated. Add the response leg only if you need it —
it means a second call to Model Armor on every turn.
Start in Observe, which records every decision without blocking anything, and
switch to Enforce once the decisions look right.
How the decision is made
Blocking filters are checked first
If any enabled filter matches and calls for a block, the request is refused and
never reaches the model. The caller gets 403 and a body naming the filter: Masking applies only if nothing blocked
With Anonymize, the de-identified text replaces the original and the request
continues to the model.
Otherwise the request passes through untouched
A block anywhere discards the masking. If sensitive data would be masked but
another filter blocks the same request, the block wins and nothing is sent.This has a practical consequence worth knowing before you demonstrate the
feature: Responsible AI classifies some sensitive data — a bare payment card
number, for instance — as dangerous content. With Responsible AI enabled, a
prompt you expected to be masked is refused instead. If you want masking rather
than refusal for that content, turn off Responsible AI or raise its
confidence thresholds in the Model Armor template.
Modes and failures
In Enforce this policy fails closed, and there is no setting to change that.
If Model Armor cannot be reached, requests are refused rather than forwarded
unscreened. Validate in Observe, and account for this when sizing availability.
Limits
- Streaming responses are not inspected. They pass through untouched — apply
the policy on the request leg for enforcement.
- Text only. Files, images, and audio are not sent to Model Armor.
- LLM traffic only. The policy does not apply to MCP tool calls.
Verify the policy
Open the Playground, pick the application the policy applies to, and send
these three prompts in this order. Starting with the control means a failure
tells you something specific.
Control — the path works at all
Expect a normal reply and the decision allowed. If this fails, the problem
is the application, the model or the provider — not the guardrail. Fix it before
going on. Sensitive data — masking works
With Anonymize, expect the decision anonymized.Read the reply, not just the status. It must not contain the email address.
That is what proves the model never received it.Use an email address rather than a payment card number — see the warning above
about Responsible AI. Prompt injection — blocking works
Expect the decision block, and Provider 0 ms in the timing
breakdown. That zero is the evidence that matters: the request never reached the
model.
Every decision is emitted as a metadata event, in Observe mode too, where
nothing is blocked. See the event schema for the
fields recorded.
Troubleshooting