Skip to content
Cisco AI Defense logo
CiscoAI Security

Inspection pipeline — DefenseClaw

Overview

The inspection pipeline is the heart of the guardrail. This page documents its stages, what each stage is allowed to do, and the guarantees the pipeline promises its callers.

Stages

Rendering diagram…

Stage contracts

Each stage has an input type, an output type, and a maximum latency budget. The pipeline enforces these.

StageInputOutputBudget
NormalizeRaw InspectInputNormalizedInput (UTF-8 safe, bounded size)1 ms
Verdict cacheNormalizedInputcached verdict or miss0.1 ms
Regex triageNormalizedInput[]Finding10 ms
LLM judgeNormalizedInput + regex findings[]Finding1500 ms (budget; default timeout)
CombineTwo finding setsMerged + deduped0.1 ms
SuppressionFindings + contextPossibly-reduced findings0.5 ms
RegoFindings + mode + directionAction + reason1 ms
Post-hooksVerdict(side effects)async

Exceeding a budget does not fail the pipeline — it records a slow event. But consistent breaches are a signal that a rule pack or a judge has regressed.

Invariants

  • Every input produces exactly one verdict, even on error. Errors become action=allow (fail-open) or action=block (fail-closed) based on guardrail.fail_mode.
  • Verdicts are idempotent. The same input (content hash + direction + strategy + pack_version) always produces the same verdict, barring judge non-determinism (which is handled by the judge client retry + sampling policy).
  • Decisions never depend on time of day. No stage reads the wall clock for decision-making; only for timestamps in the resulting event.
  • The pipeline never stores request bodies persistently. Only hashes and (optionally, redacted) fingerprints go to disk.
  • No stage can mutate policy. Policy is read-only during inspection; hot-reloads land between inspections.

Concurrency

The pipeline is embarrassingly parallel across requests. Per-request it's single-threaded through regex and judge stages (both internally batched), then fans out on the post-hooks.

The sidecar runs one pipeline per incoming HTTP handler goroutine. Backpressure is applied at the proxy level (see guardrail.max_in_flight).

Extensibility points

HookWhenSignature
BeforeNormalizeFirstfunc(ctx, *InspectInput) error
AfterTriageAfter regex triagefunc(ctx, *InspectInput, *[]Finding) error
BeforeJudgeBefore judge (can suppress the judge)func(ctx, *InspectInput, []Finding) (skip bool, err error)
AfterCombineAfter combinefunc(ctx, *Verdict) error
OnVerdictFinalfunc(ctx, *Verdict)

Hooks are registered at sidecar startup and are the extension surface for in-tree scanners.

Observability

Every stage produces an OTel span with the stable name guardrail.<stage>. Span attributes include correlation_id, direction, strategy, and pack_version. Metrics emit per-stage latency histograms under defenseclaw_guardrail_stage_duration_seconds{stage="..."}.

Related