{"record":{"id":"dfd20f39fa8fa5f2","repo":"googleworkspace/cli","slug":"content-blocked-by-model-armor","errorCode":null,"errorMessage":"Content blocked by Model Armor","messagePattern":"Content blocked by Model Armor","errorType":"exception","errorClass":"GwsError","httpStatus":null,"severity":"error","filePath":"crates/google-workspace-cli/src/executor.rs","lineNumber":278,"sourceCode":"            let text_to_check = serde_json::to_string(&json_val).unwrap_or_default();\n            match crate::helpers::modelarmor::sanitize_text(template, &text_to_check).await {\n                Ok(result) => {\n                    let is_match = result.filter_match_state == \"MATCH_FOUND\";\n                    if is_match {\n                        eprintln!(\"⚠️  Model Armor: prompt injection detected (filterMatchState: MATCH_FOUND)\");\n                    }\n\n                    if is_match && *sanitize_mode == crate::helpers::modelarmor::SanitizeMode::Block\n                    {\n                        let blocked = serde_json::json!({\n                            \"error\": \"Content blocked by Model Armor\",\n                            \"sanitizationResult\": serde_json::to_value(&result).unwrap_or_default(),\n                        });\n                        println!(\n                            \"{}\",\n                            serde_json::to_string_pretty(&blocked).unwrap_or_default()\n                        );\n                        return Err(GwsError::Other(anyhow::anyhow!(\n                            \"Content blocked by Model Armor\"\n                        )));\n                    }\n\n                    if let Some(obj) = json_val.as_object_mut() {\n                        obj.insert(\n                            \"_sanitization\".to_string(),\n                            serde_json::to_value(&result).unwrap_or_default(),\n                        );\n                    }\n                }\n                Err(e) => {\n                    eprintln!(\n                        \"⚠️  Model Armor sanitization failed: {}\",\n                        sanitize_for_terminal(&e.to_string())\n                    );\n                }\n            }","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/googleworkspace/cli/blob/a3768d0e82ad83cca2da97724e46bea4ff0e6dbd/crates/google-workspace-cli/src/executor.rs#L260-L296","documentation":"When Model Armor sanitization is configured (--sanitize or GOOGLE_WORKSPACE_CLI_SANITIZE_TEMPLATE) and the mode is Block (GOOGLE_WORKSPACE_CLI_SANITIZE_MODE=block), every API response is inspected. If inspection finds a match (PII, secrets, harmful content per the template), the CLI prints a JSON object with the full sanitizationResult, then aborts the command with this error instead of letting the flagged content through.","triggerScenarios":"Response body contains data matching a Model Armor template filter (e.g. an email/phone PII detector or a content classifier) while mode=block; the template was tightened after workflows were written, so previously-fine outputs now match; broad filter templates matching innocuous fields.","commonSituations":"Security policy requires block mode in shared environments; a template with overly broad regex/PII rules flags common content; listing operations (users, messages) returning personal data that triggers PII detectors.","solutions":["Read the printed sanitizationResult JSON — it names the filter type and match details that caused the block","If the content is legitimately safe, adjust the Model Armor template (narrow the detector) in GCP","For warn-and-continue behavior, unset the block mode: GOOGLE_WORKSPACE_CLI_SANITIZE_MODE=warn (the default) — matches then annotate output with _sanitization instead of failing","Otherwise rewrite the query/response handling to avoid retrieving the flagged content"],"exampleFix":"# before: hard stop on matches\n$ export GOOGLE_WORKSPACE_CLI_SANITIZE_MODE=block\n$ gws gmail users getProfile --params '{\"userId\":\"me\"}'\nError: Content blocked by Model Armor\n\n# after: annotate instead of block\n$ export GOOGLE_WORKSPACE_CLI_SANITIZE_MODE=warn\n$ gws gmail users getProfile --params '{\"userId\":\"me\"}'   # output carries _sanitization field","handlingStrategy":"validation","validationCode":"// Decide policy up front: only fail hard when block mode is explicitly required\nfn sanitize_policy() -> SanitizePolicy {\n    match std::env::var(\"GOOGLE_WORKSPACE_CLI_SANITIZE_MODE\").as_deref() {\n        Ok(\"block\") => SanitizePolicy::Block,\n        _ => SanitizePolicy::Warn, // default: annotate, do not abort\n    }\n}","typeGuard":null,"tryCatchPattern":"match run_with_sanitization().await {\n    Ok(v) => { /* proceed */ }\n    Err(GwsError::Other(e)) if e.to_string() == \"Content blocked by Model Armor\" => {\n        // parse the printed sanitizationResult JSON, decide: transform data, narrow the query, or escalate\n    }\n    Err(e) => { /* unrelated failure */ }\n}","preventionTips":["Use warn mode (the default) while developing templates; enable block only once rules are tuned","Print and inspect the sanitizationResult before changing policy — it names the exact matching filter","Narrow list queries (fields, pageSize) so responses contain less PII likely to trip detectors","Keep the Model Armor template ID in version control alongside the app that depends on it"],"tags":["model-armor","sanitization","content-policy","security"],"backgroundTag":"content-policy-blocked","analyzedSha":"a3768d0e82ad83cca2da97724e46bea4ff0e6dbd","analyzedAt":"2026-08-16T19:51:46.516Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}