#2044·Guardrails

is_content_safe verdict parser fails OPEN, bypassing self-check / content-safety / fact-checking rails

Author: AUTHENSORCreated Jun 18, 2026Updated Sep 19, 2026

Summary

nemoguardrails/llm/output_parsers.py is_content_safe() (~:119-141) decides whether a check-LLM's verdict means the content is unsafe by inspecting only the first two words of the response for the bare tokens {safe, unsafe, yes, no}. When none of those tokens appears in the first two words, it returns [False] (= not unsafe). The consuming rails (self_check_input/output, content_safety, self_check_facts) map that to score = 1.0 and do not block. So any verdict phrased in natural language — which is exactly how an LLM judge tends to answer — fails open: the unsafe/hallucinated content is delivered.

Reproduction (deterministic)

self_check_facts (hallucination rail) — a verdict that clearly means ungrounded is allowed:

verdict (means HALLUCINATED -> should block)              score  decision
"The response is not supported by the evidence."          1.0   ALLOWED
"This claim is not grounded in the provided context."     1.0   ALLOWED
"Incorrect - the evidence does not mention this."         1.0   ALLOWED
"Hallucinated."                                           1.0   ALLOWED
sanity: "No" -> 0.0 blocked ; "Yes" -> 1.0 not blocked

The same parser underlies content_safety input/output and self_check input/output; a "not safe" / misspelled / multi-word verdict bypasses each.

Expected vs actual

  • Expected: a verdict that means unsafe / ungrounded blocks; an ambiguous / empty / unparseable verdict fails closed (a guardrail should not pass content it could not evaluate).
  • Actual: any verdict without a leading bare keyword -> treated as safe -> content delivered.

Why it matters

These rails are the guardrail people deploy in front of an LLM. A judge model answering in ordinary prose ("This is not grounded...", "The user's request is not safe because...") is the common case, and it silently disables the rail.

Proposed direction (for maintainer input)

  1. Parse the whole verdict (not just the first two words), negation-aware, and recognize natural phrasings — or constrain the check prompt to a strict, parseable token and validate it.
  2. Fail CLOSED when the verdict is empty / unparseable / ambiguous (block or surface an error), rather than defaulting to allow. Happy to send a focused PR for whichever direction you prefer.