Skip to content

Payload Inspection

A backend MCP server returns text that goes straight into a model’s context. If that text contains instructions, the model may follow them. If it contains a credential, the credential is now in the transcript.

The Gateway inspects what passes through it: tool arguments on the way to a backend, and tool responses on the way back.

Every setting on this page lives in the Inspection group on your gateway pool, in the Britive tenant portal. Changes reach a running Gateway on its next sync - there is nothing to restart.

Audit First, Then Enforce

Inspection has three modes, and the order you adopt them in matters.

inspection.modeBehaviour
auditFindings are recorded in the audit trail. The call proceeds unchanged. Default.
enforceMatching content is blocked or redacted.
offInspection does not run.

There is no separate on/off switch: off is what that switch used to mean, and one field that says whether inspection is running beats two that can disagree about it.

Begin in audit mode. The recorded verdicts show exactly what enforcement would have done to your real traffic, which is the only practical way to confirm a detector suits your backends before it starts refusing calls.

Inspection runs in audit mode by default, so you get the findings without any behaviour change until you decide otherwise.

Inspection Is Best Effort

Treat inspection as a safety net, not a boundary. The detectors are pattern-based and run locally with no model, so they catch known shapes of attack - not every possible one. A novel phrasing, an encoding nobody has characterised yet, or a payload crafted against these specific detectors can pass.

It is worth running because it catches real problems cheaply and tells you what your traffic actually contains. It is not worth treating as proof that what reached the model was safe.

The controls that are boundaries are the ones either side of it: Britive policy decides which tools an identity may call at all, and credentials are scoped and temporary, so what a compromised call can reach is bounded regardless of what any detector missed.

What Enforcement Actually Does

In enforce mode, the action depends on the highest severity finding in the payload:

Highest severityAction in enforce mode
criticalBlock - the call fails
highRedact - the offending content is removed
medium, low, infoAllowed; recorded only

In audit mode every severity is allowed and recorded, including critical.

A blocked call fails with an INSPECTION_BLOCKED error that names the phase, the deciding detector, its category and severity, and the finding’s label - “AWS access key id”, for instance - along with prose telling the model this is a policy decision and not to retry. The matched snippet and its position stay in the audit sink you control rather than travelling back out through the model.

inspection.silentRedact is false by default, which means redactions and blocks are visible to the caller. Set it to true to redact without indicating that anything was removed.

The Detectors

inspection.detectors is the list of built-in detectors that run. All three are selected by default, and the list is the whole answer - naming one turns it on, and an unrecognised name is rejected rather than silently disabling inspection.

DetectorWhat it looks for
promptInjectionInstructions aimed at the model rather than the user - attempts to override its task, exfiltrate context, or issue new directives from inside tool output.
secretScannerCredential material in arguments or responses: keys, tokens, and similar.
obfuscationAttempts to evade the other two - invisible Unicode tag characters, bidirectional override sequences, zero-width characters inserted into keywords, base64-encoded instruction blocks, and homoglyph or full-width look-alikes.

All of them run locally. There is no model call and no outbound request.

The URL blocklist

A fourth detector blocks domains you name. It has no entry in the detectors list because it runs whenever either of these is non-empty:

SettingPurpose
inspection.urlBlocklistDomainsDomains to block on sight, for example paste.example.net.
inspection.urlBlocklistFeedUrlA feed of blocked domains, merged with the list above and de-duplicated.

The feed is either a JSON array of strings or one domain per line, where # starts a comment. Each Gateway fetches it when it starts and again whenever the address changes - not on every settings save, so editing an unrelated setting does not call out to the feed’s host.

If a fetch fails, the Gateway keeps the domains it last retrieved and logs a warning. An outage at the feed cannot quietly shrink your blocklist.

Timeouts

Inspection is bounded so it cannot become a latency problem. Both live in the Advanced group:

SettingDefault
inspection.requestTimeoutMs250
inspection.responseTimeoutMs500

Enforce mode fails closed on timeout. An oversized payload that stalls the detectors is blocked rather than passed through unchecked. In audit mode a timeout is recorded at info severity and the call proceeds, since audit mode never blocks.

Seeing What Triggered a Decision

Response bodies are not stored, because they may contain secrets or personal data. When you need to see what a detector matched, turn on inspection.debugCaptureResponses (“Capture blocked responses”).

This copies the response body - up to inspection.debugResponseMaxChars, 10000 by default - into the audit event for calls that were blocked or redacted only. It never appears in the stdout line, only in the durable sinks you control.

This is a diagnostic setting. Turning it on means captured response bodies are written to your audit sinks, and forwarded to your tenant if audit.platform.includeContent is also on. Turn it off when you’re done.

Findings appear in the admin console in the expanded audit row: the decision and phase, then each finding’s severity, detector, message, and matched snippet, ordered worst-first. Inspection events are recorded under the tools.call.inspect action, so filtering the audit log by that action shows every verdict on its own.

Forwarding those verdicts into your tenant’s audit history is not on by default - add tools.call.inspect to audit.platform.events if you want them there as well as in the Gateway’s own log and your SIEM.

Rolling It Out

Run in audit mode

Leave Mode on its default of audit and let real traffic flow for a week.

Review the findings

In the admin console, filter the audit log for inspection events and look at what matched. You are answering two questions: is anything being flagged that is actually fine, and is the severity right for your traffic?

Switch to enforce

Set Mode to enforce on the pool. Every gateway in it picks the change up on its next sync, within five minutes by default.

Critical findings now block and high findings redact. Watch for tools.call.inspect events with a block decision - those are calls that would previously have succeeded.

Verify

  • A tool call with an innocuous payload produces no findings and is unaffected.
  • In audit mode, a response containing an obvious injection string produces a tools.call.inspect event with findings, and the call still succeeds.
  • In enforce mode, the same call is blocked, and the audit row shows the decision, the phase, and each finding worst-first.

Next Steps

Last updated on