AI Security
·IdenticAPI

Designing Allow, Review and Block Security Decisions

Design allow, review, and block security decisions — why ternary verdicts beat binary flags for high-impact operations and human review.

Binary allow/deny security APIs force a false choice: block too much and users revolt; allow too much and incidents happen. Production AI systems need a ternary modelallow, review, and block — mapped from detector verdicts to application actions with explicit precedence and audit trails.

This guide explains why three states beat boolean flags, how IdenticAPI verdicts map to each action, and how to design review workflows that reduce both false positives and false negatives.

Related: Block vs Review for AI Output, AI Agent Policy Decisions, False Positives vs False Negatives.

Why binary models break down

Binary approachFailure mode
Block on any signalBenign security docs, quoted attacks, technical HTML → guardrail fatigue
Allow unless certainParaphrased injection, subtle PII, borderline phishing → silent incidents
"Score > 0.7 = block"No buffer for ambiguous cases; threshold wars between teams

Security operations already use quarantine states — email spam folders, WAF challenge pages, fraud holds. LLM products need the same middle state for medium-confidence signals.

IdenticAPI expresses this as:

  • Single detectors: safe / suspicious / unsafe
  • Unified Guard per-check: allow / review / block
  • Aggregated decision with block > review > allow priority

The three actions defined

Allow

Meaning: Proceed with the normal pipeline — call the model, deliver output, execute the tool.

Typical detector mapping: safe / allow with low risk and no blocking categories.

Requirements:

  • Downstream controls still apply (sanitization, CSP, authorization)
  • Log request_id and metadata for sampling

Allow is not "trust the content" — it means automated policy permits this step.

Review

Meaning: Hold for human or secondary automated adjudication before proceeding.

Typical detector mapping: suspicious / review, or medium risk with non-blocking categories.

Requirements:

  • End users see a neutral holding message — not flagged content
  • Queue stores context access-controlled for reviewers
  • SLA and escalation paths defined
  • Reviewer outcome logged (true positive / false positive) for tuning

Review absorbs ambiguity — the primary false-positive and false-negative mitigation. See AI guardrails false positives.

Block

Meaning: Stop the pipeline; do not call the model, deliver output, or execute the tool.

Typical detector mapping: unsafe / block, high risk, secrets, executable markup, destructive agent actions.

Requirements:

  • Static pre-approved fallback message to users
  • Do not echo flagged text in errors or client responses
  • Log request_id, verdict, categories — minimize raw content in production logs

Block is for high-confidence harm where exposure is unacceptable.

Verdict mapping reference

Input and output text (injection, PII, output safety)

VerdictRisk (typical)Suggested defaultOverride when
safelowAllow
suspiciousmediumReviewHigh-trust internal tools may allow specific categories
unsafehighBlockNever allow secrets or executable markup to users

PII nuance:

  • Secrets (unsafe) → almost always block, never redact-and-forward without rotation policy
  • PII (suspicious) → review or redact-then-allow per privacy policy

Agent actions

VerdictSuggested default
allowExecute tool with normal authorization
reviewQueue for human approval (HITL)
blockReject proposal; return safe failure to agent loop

Agent Action Guard evaluates structured tool_name, action, and arguments — not chat prose alone.

Unified Guard aggregation

When multiple checks run in one POST /api/v1/guard call:

{
  "decision": "block",
  "checks": [
    { "check": "prompt_injection", "verdict": "allow", "risk": "low", "findings": [] },
    { "check": "pii_secrets", "verdict": "block", "risk": "high", "findings": [{ "category": "api_key" }] }
  ],
  "usage_units": 2,
  "request_id": "req_abc123"
}

One block check forces decision: block regardless of other results. Your middleware should persist per-check findings for incident analysis.

Decision matrix by finding category

Use findings[].category — not verdict alone:

Category (illustrative)VerdictAction
api_key, private_key, bearer_tokenunsafeBlock
instruction_overrideunsafeBlock on public chat; review on internal docs search
unsafe_htmlunsafeBlock before DOM render
email, phonesuspiciousReview or redact-then-allow
phishing_patternunsafeBlock
policy_topic_medicalsuspiciousReview for regulated products

Store matrices in version-controlled policy config — not scattered if statements.

Precedence rules

When multiple signals exist in one request:

  1. Any block → block (secrets beat benign injection allow)
  2. Else any review → review
  3. Else → allow

Same precedence as Unified Guard decision aggregation. Apply consistently across input, output, and agent stages.

Anti-pattern: letting the "most permissive" check win because it ran last.

Review queue design

Effective queues include:

FieldPurpose
request_idTrace to scanner
User / tenant IDAuthorization for reviewer
Surface (chat, RAG, agent)Context for policy
findings[].category + reasonsWhy it flagged
Proposed action (for agents)Structured tool call
SLA timerPrevent stagnation

Reviewer actions:

  • Approve — deliver or execute (possibly edited)
  • Reject — block with template message
  • Escalate — security or legal
  • Mark false positive — feeds metrics

Users never see pending flagged model text. See moderate AI chatbot responses.

Block workflow essentials

  1. Return pre-approved fallback — no model echo
  2. Log correlation IDs
  3. Optional session abuse counters
  4. For secrets: trigger rotation runbook

Example fallback:

"I can't process that request. Please rephrase or contact support."

Fail-open vs fail-closed on API errors

Scanner unavailability is not a verdict:

PolicyBehaviorWhen
Fail closedBlock or review queueHigh-assurance, regulated, public HTML
Fail openAllow with alertLow-risk internal prototypes only

Document explicitly — do not conflate outage with allow verdict. See fail-open vs fail-closed.

Surface-specific policies

One global map rarely fits:

SurfaceBlockReviewAllow bias
Public support chatunsafesuspiciousStrict
Internal code copilotunsafe secretssuspicious injectionLooser on jargon
Agent with email toolunsafe + external sendambiguous writesStrict on egress
Read-only FAQunsafe outputrareModerate

Document overrides; audit changes.

Measuring the model

Track per action:

MetricSignal
Block rateUser friction; sudden drops may mean bypass
Review rateStaffing needs
Review override rate (approved as safe)False positive indicator
Blocked-then-reported incidentsFalse negative indicator

Tune policy when override rate spikes — not by disabling guardrails.

Implementation sketch

type Action = "allow" | "review" | "block";

function routeVerdict(verdict: string, categories: string[]): Action {
  if (categories.some((c) => BLOCKING_CATEGORIES.has(c)) || verdict === "unsafe") {
    return "block";
  }
  if (verdict === "suspicious") return "review";
  return "allow";
}

Prefer category-aware rules over verdict-only switches. Align BLOCKING_CATEGORIES with your threat model.

Summary

  • Allow — automated proceed; downstream controls still required
  • Review — human or secondary adjudication; users never see raw flagged content
  • Block — hard stop for high-confidence harm
  • Map IdenticAPI safe/suspicious/unsafe (or allow/review/block) through category-aware policy
  • Aggregate with block > review > allow precedence
  • Measure override and incident rates to tune — not binary threshold guessing

The ternary model is how production teams ship guardrails users tolerate without giving attackers a wide allow path.

Frequently asked questions

What is the allow, review, block security model?

It is a ternary policy mapping detector verdicts to three application actions: allow (proceed), review (human or secondary adjudication), and block (hard stop). It reduces both false-positive user friction and false-negative exposure compared to binary allow/deny.

How do IdenticAPI verdicts map to allow, review, and block?

Common mapping: safe or allow → allow; suspicious or review → review queue; unsafe or block → block with static fallback. Secrets and executable markup should almost always block regardless of surface.

Should end users see content pending review?

No. Show a neutral holding message while reviewers adjudicate. Never display flagged model text with a warning banner — that still exposes harmful or executable content.

What is the precedence when multiple checks disagree?

Use block > review > allow — matching Unified Guard decision priority. One blocked check forces block even if other checks returned allow.

When should I block instead of review?

Block on unsafe verdicts, high risk, detected secrets, instruction overrides on public surfaces, unsafe HTML, and destructive agent actions. Reserve review for suspicious verdicts and context-dependent policy topics where false positives are likely.

Related reading