Model Armor Tightens Prompt Injection Checks for Workspace
An attacker doesn't need access to your prompt box. They only need to email someone whose inbox your agent reads. On October 9, 2026, Google Cloud added enhanced Model Armor prompt injection and jailbreak protection for Workspace data such as emails, documents and files. It only reaches templates on filter version v3 or later, and filter versions v1 and v2 retire on December 17, 2026.
What changed in Model Armor prompt injection detection
Model Armor is Google Cloud's service for screening LLM prompts and responses. The release notes carry two changes that belong together:
- Oct 9: Enhanced prompt injection and jailbreak protection for Workspace data. Google says it improves detection accuracy and reduces false positives. It applies to templates and floor settings (baseline rules set at project, folder or organization level) on filter version v3 or later, Stable and Latest aliases included, on the
usandeumulti-region endpoints. - Sep 18: Filter version v4 shipped and became the default for the Latest alias. v3 was promoted to Stable in all supported regions except
asia-northeast3(where v1 stays Stable) andaustralia-southeast2(where it follows on Sep 25). v1 and v2 moved to Legacy. - Retirement: v1 and v2 retire on December 17, 2026. Earlier entries (Aug 3 and Sep 2) said November 29. The Sep 18 entry supersedes them, and the filter version page lists December 17 too.
The note scopes the Workspace protection to v3 or later, so a template pinned to v1 or v2 sits outside it. It doesn't describe how Workspace content reaches Model Armor, so that part stays your integration's job.
Why this matters when agents read other people's content
Indirect prompt injection means the hostile instructions arrive inside content the model reads, not in what the user typed. Emails and shared documents are the textbook delivery route, because anyone can send one. Detectors tuned on short chat messages meet long quoted threads and boilerplate here, which is why the false-positive claim matters: a filter that blocks legitimate invoices gets switched off by an annoyed team.
Retirement won't be an outage. Per the filter version page, a template pinned to a retired version is sanitized with the Stable version until you migrate it. The risk is a detector that changes under you on Google's schedule instead of yours.
Audit templates pinned to v1 or v2 on Monday
The Model Armor page in the Console lists a project's templates. For each one, read templateMetadata.filterVersionSelector through the REST API. No selector means the template defaults to Stable.
PROJECT_ID=<your-project-id>
LOCATION=us # repeat with eu
for TEMPLATE_ID in <template-id-1> <template-id-2>; do
printf '%s: ' "$TEMPLATE_ID"
curl -s \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://modelarmor.${LOCATION}.rep.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/templates/${TEMPLATE_ID}" \
| jq -c '.templateMetadata.filterVersionSelector // "none (defaults to Stable)"'
done
Anything printing "version":"v1" or "version":"v2" is on the clock. Migrate it with a PATCH. Set either version or alias, never both.
curl -X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d '{"templateMetadata":{"filterVersionSelector":{"version":"v3"}}}' \
"https://modelarmor.us.rep.googleapis.com/v1/projects/<your-project-id>/locations/us/templates/<your-template-id>?updateMask=templateMetadata.filterVersionSelector"
Pin v3 if you want change control. Swap the selector for {"alias":"FILTER_VERSION_ALIAS_STABLE"} if you'd rather follow promotions: Stable keeps its detection logic fixed, but the alias moves when Google promotes a newer version.
To try v4, point a staging template at FILTER_VERSION_ALIAS_LATEST. The docs describe Latest as the newest protections with stability that can vary between versions, so keep it out of production. It is also v3 or later, so staging gets the Workspace enhancement.
Run inspect-only before you block
Inspect-only logs violations to Cloud Logging and blocks nothing. Model Armor's docs recommend starting there, reading the logs, then switching to inspect-and-block. The sanitize API returns a verdict and your calling service enforces it, so the switch can be a flag. This wrapper needs roles/modelarmor.user and prints the verdict with the filter version that produced it.
import os
import google.auth
from google.auth.transport.requests import AuthorizedSession
PROJECT = '<your-project-id>'
LOCATION = 'us' # or 'eu'
TEMPLATE = '<your-template-id>'
BLOCK = os.environ.get('MODEL_ARMOR_MODE', 'inspect') == 'block'
credentials, _ = google.auth.default(scopes=['https://www.googleapis.com/auth/cloud-platform'])
session = AuthorizedSession(credentials)
URL = (
f'https://modelarmor.{LOCATION}.rep.googleapis.com/v1/projects/{PROJECT}'
f'/locations/{LOCATION}/templates/{TEMPLATE}:sanitizeUserPrompt'
)
def allow(text: str) -> bool:
"""Screen one piece of untrusted text. True means it may reach the model."""
resp = session.post(URL, json={'userPromptData': {'text': text}})
resp.raise_for_status()
result = resp.json()['sanitizationResult']
pi = result.get('filterResults', {}).get('pi_and_jailbreak', {})
matched = pi.get('piAndJailbreakFilterResult', {}).get('matchState') == 'MATCH_FOUND'
version = result.get('sanitizationMetadata', {}).get('filterVersionConfig', {})
print({'matched': matched, 'version': version.get('filterVersion'),
'alias': version.get('filterVersionAlias'), 'warnings': version.get('messageItems')})
return not (matched and BLOCK)
Replay a week of real emails and documents in inspect mode, read the matches, then set MODEL_ARMOR_MODE=block.
Gotchas
- The prompt injection filter screens up to 65,536 tokens (262,144 characters), per the Aug 25 note. Chunk long documents under that limit instead of guessing what happens above it.
- Sanitize responses carry a retirement warning in
messageItems30 days before a version retires. Treat it as a tripwire, not a plan. - Template exclusion rules (dictionary and regex) arrived in Preview on Sep 28 to cut false positives. Try them before loosening anything else.
If your agent reads other people's email, treat the filter version on every template as production config with an owner, because Google just put a date on it.