Every security-tool invocation passes through one auditable boundary.
SaintScan is BleedWatch's MCP gateway for sandboxed active validation. It routes CLI tools through allowlists, tenant scope checks, argv sanitization, digest-pinned images, policy decisions, circuit breakers, and immutable audit records before any process can run.
Three properties CISOs ask about.
Agent-driven pentest and validation platforms introduce new failure modes. The gateway makes the execution path reviewable, bounded, and reconstructable.
Single chokepoint for tool execution
Every invocation of nuclei, sqlmap, naabu, httpx, katana, and future active-validation tools routes through one auditable boundary. There are no ad-hoc execFile calls and no shadow tool paths.
SOC 2-grade cryptographic audit trail
Every execution produces an append-plus-one-finalize row in saintscan_mcp_audit. Immutability is enforced at the PostgreSQL level with REVOKE plus trigger protections.
PostgreSQL-level tenant isolation
Audit and kill-switch tables run under row-level security. Gateway-side tenant-tier allowlisting and per-(scanId, tool) circuit breakers isolate tenant risk from the shared execution fleet.
One gateway, seven enforced layers.
An agent request reaches a tool binary only after every layer approves the same tenant, target, image, policy, and audit context. If any layer rejects the request, no container is spawned.
Agent requests traverse allowlist, scope validator, argv sanitizer, digest resolver, policy gate, circuit breaker, and pre-exec audit insert before the docker-socket-proxy launches a digest-pinned non-root container.
Fail closed before execution.
The pipeline is deliberately redundant. Tool, target, argument, image, policy, rate, and audit checks each catch different classes of agent and tool-execution failure.
1. Tool allowlist
The requested binary must exist in the compiled SaintScan allowlist. Unknown tools, shell paths, absolute paths, aliases, and runtime-provided executables are rejected before argument parsing.
2. Scope validator
The target is matched against the tenant's approved scan scope: domain, host, repository, package, registry artifact, or explicitly authorized validation target.
3. Argv sanitizer
Arguments are represented as arrays, not shell strings. Dangerous flags, output redirects, file-system writes, shell expansion, nested commands, and unbounded concurrency are blocked.
4. Digest-pinned image resolver
Tool containers are resolved to immutable SHA-256 image digests. Tags alone are not accepted, and the digest must match the approved registry manifest before execution.
5. Policy gate
Tenant tier, authorization mode, tool risk level, expected duration, target class, and active-validation opt-in are evaluated before a process can be created.
6. Circuit breaker
Per-(scanId, tool) counters enforce max attempts, backoff, timeout, and kill-switch state so a single scan cannot create a runaway validation loop.
7. Audit insert
The gateway synchronously inserts an audit row before execution. If the insert fails, the tool does not run. Finalization may update only the allowed outcome fields.
The request is admitted before the proxy sees it.
const admission = await gateway.admit({
tenantId,
scanId,
tool,
target,
argv,
});
// Pipeline:
// allowlist -> scope validator -> argv sanitizer -> digest resolver
// -> policy -> circuit breaker -> audit insert -> docker-socket-proxy
if (!admission.allowed) {
return deny(admission.reason);
}
return dockerProxy.run({
image: admission.imageDigest,
user: 'nonroot',
network: admission.networkPolicy,
argv: admission.sanitizedArgv,
timeoutMs: admission.timeoutMs,
});What the gateway is designed to prevent.
No shell expansion
SaintScan never constructs a shell command from user input. Commands are spawned as binary plus argv array after allowlist and sanitizer checks.
No mutable tool tags
Tool containers must be digest-pinned. Mutable tags such as latest are rejected in production policy.
No unscoped validation
Active validation requires approved tenant scope and explicit opt-in. OSINT-only scans cannot silently promote themselves to probing.
No silent audit gaps
Execution depends on a pre-exec audit insert. Missing audit storage fails closed instead of allowing unaudited tool execution.
No cross-tenant audit reads
RLS policies filter audit rows by tenant. Support review uses controlled break-glass paths, not broad application queries.
No app-layer-only immutability
The database rejects mutation of immutable fields even if an application credential is compromised.
Risks and controls.
The gateway assumes agent output may be adversarial, scanner targets may be hostile, tool containers may need rapid revocation, and application credentials may be less trusted than database policy.
| Threat | Control |
|---|---|
| Prompt injection asks an agent to run an unsafe tool | The tool name must clear the allowlist, tenant tier, scope validator, policy gate, and circuit breaker. Unknown binaries never reach spawn. |
| Argument injection turns a benign tool into an exploit path | Arguments are parsed as structured arrays. Shell metacharacters, nested commands, output redirects, write paths, and dangerous flags are rejected. |
| A mutable container tag is replaced upstream | Images are resolved and executed by approved digest. Tag drift is visible before rollout and cannot silently change production tools. |
| One tenant creates a runaway validation loop | Per-(scanId, tool) circuit breakers and kill switches isolate the scan. Shared workers do not keep retrying blindly. |
| Application credentials are compromised | PostgreSQL RLS and audit-table triggers enforce tenant filtering and immutable fields below the API layer. |
| Auditors cannot reconstruct what happened | The audit row records tenant, scan, tool, image digest, argv hash, target hash, start time, final status, duration, and policy decision. |
Append plus one finalize.
The audit table records a pre-execution row, then permits a single finalization update for outcome fields. Immutable fields such as tenant, scan, tool, target hash, argv hash, image digest, and policy version cannot change after insert.
tenant_idscan_idtooltarget_hashargv_hashimage_digestpolicy_versiondecisionstarted_atfinalized_atduration_msexit_codestdout_refstderr_referror_classcreate table saintscan_mcp_audit (
id uuid primary key default gen_random_uuid(),
tenant_id uuid not null,
scan_id uuid not null,
tool text not null,
target_hash text not null,
argv_hash text not null,
image_digest text not null,
policy_version text not null,
decision text not null check (decision in ('allow', 'deny')),
started_at timestamptz not null default now(),
finalized_at timestamptz,
duration_ms integer,
exit_code integer,
stdout_ref text,
stderr_ref text,
error_class text,
created_by text not null default 'saintscan-mcp-gateway'
);
alter table saintscan_mcp_audit enable row level security;
create policy saintscan_mcp_audit_tenant_isolation
on saintscan_mcp_audit
using (tenant_id = current_setting('app.tenant_id')::uuid);
revoke update on saintscan_mcp_audit from app_runtime;
create trigger saintscan_mcp_audit_immutable
before update on saintscan_mcp_audit
for each row execute function enforce_mcp_audit_finalize_only();How the gateway maps to your controls.
Each mapping references the gateway control that can be reviewed in auditor language. Full clause-to-evidence crosswalks are available in the enterprise security review package.
Cybersecurity supply-chain management
Digest-pinned tool container images, gateway-side binary allowlist, and full audit trail of third-party tool invocations address supply-chain management obligations for external tooling.
Secure development lifecycle
Tool-execution code paths are centralized, reviewed, policy-gated, and validated before any binary is spawned.
Maintain secure systems and software
Tool binaries are pinned, vulnerability-reviewed before rollout, invoked through one controlled entry point, and insulated from shell expansion.
System operations and monitoring
mcp_client_* and mcp_exec_* metrics, synchronous audit insert, append-plus-one finalize semantics, and kill-switch logs support operational monitoring evidence.
Operational resilience
Circuit breakers, kill switches, incident runbooks, and deterministic execution logs help reconstruct and contain validation incidents.
Security of processing
Tenant-scoped execution logs, data minimization, RLS, immutable audit rows, and active-validation opt-in support appropriate technical controls.
Contain by tenant, tool, or scan.
The incident runbook is shaped around the gateway boundary. Operators can revoke a tool, pause a tenant, stop a scan, or block a digest without disabling the whole platform.
Detect
Alert triggers on mcp_exec_failures_total, circuit-breaker open events, unexpected tool decision rates, image digest mismatch, or audit insert failures.
Contain
Open the per-tool or per-tenant kill switch. Existing containers are stopped through the proxy path and new admissions fail closed.
Preserve
Export audit rows, policy versions, digest manifests, metrics, and gateway logs. Do not mutate audit records.
Eradicate
Patch policy, sanitizer, image digest, or scope logic. Add regression coverage for the exact admission path.
Recover
Re-enable the specific tool or tenant only after replaying a dry-run decision, verifying audit inserts, and confirming breaker counters.
Notify
If customer data or availability was affected, notify through email, status page, and in-app banner according to the incident policy.
Evaluating BleedWatch for regulated workloads?
Prospects in banking, healthcare, public sector, and critical infrastructure can request the full security review package, including the MCP audit schema, rollback runbook, and control evidence crosswalk for NIS2, ISO 27001, PCI-DSS, DORA, GDPR, and SOC 2.
PACKAGE CONTENTS
- MCP gateway architecture brief
- Audit table schema and invariants
- Kill-switch and revocation runbook
- Digest-pinning and image review policy
- Clause-to-evidence control mapping