Security hardening
Complete production hardening guidance for secrets, policy, network boundaries, sandboxes, HTTP ingress, builds, snapshots, and audit evidence.
This is the complete public hardening guide. Review it with the deployment-specific security controls for your runtime before promoting an agent.
Secrets and redaction
Never place credentials in agent definitions, serializable workflow inputs, prompts, session artifacts, checkpoints, generated files, or error messages. Use secret references and resolve them at the narrowest trusted runtime boundary.
import { redactError, redactJson, redactText, resolveSecret, secret } from '@fabric-harness/sdk';
const tokenRef = secret('PROVIDER_TOKEN');
const token = await resolveSecret(tokenRef, runtimeResolver);The central redaction helpers cover common secret-shaped keys and values including API keys, tokens, passwords, authorization headers, private keys, and certificate fields. Apply them before untrusted errors or environment-derived metadata enter logs, events, traces, or approval requests.
FabricError exposes separate toPublicJSON() and toDeveloperJSON() serializers. Public
serialization is suitable for production responses. Developer serialization contains more
diagnostics but remains redacted. In production mode, default JSON serialization uses the public
audience.
Capability policy
- Declare only the tools and commands the workload needs.
- Prefer narrow filesystem scopes such as
/workspace/src/**, not/workspace/**. - Treat definition policy as a security floor; invocation policy may narrow it but must not replace its allowlists.
- Gate destructive or externally visible actions such as
git push,npm publish, data mutation, and infrastructure changes with durable approvals bound to the exact operation and actor. - Validate tool arguments and typed results. Model and tool output is untrusted input.
- Use governed Fabric Platform actions for application mutations rather than bypassing the application's mutation boundary.
Skills add instructions, not capabilities. Loading a skill must never grant filesystem, shell, network, credential, or connector authority.
Network enforcement
Default to allowlist egress, but do not confuse application policy with a universal network
firewall. policiedFetch() checks supported HTTP calls routed through it. Global fetch, Axios,
third-party SDKs, raw sockets, DNS, and subprocess traffic are not automatically intercepted.
import {
assertEnforceableNetworkPolicy,
policiedFetch,
type CapabilityPolicy,
} from '@fabric-harness/sdk';
const policy: CapabilityPolicy = {
network: {
mode: 'allowlist',
protocols: ['https:'],
hosts: ['api.example.com'],
resolveDns: true,
},
};
const safeFetch = policiedFetch(fetch, policy);
await safeFetch('https://api.example.com/status');
assertEnforceableNetworkPolicy(policy, sandbox, {
deployment: 'production',
});For production, enforce egress again outside the process with a Docker network, Kubernetes NetworkPolicy plus proxy, private VNet, or provider firewall. The assertion validates a sandbox's declared boundary; it does not provision that boundary. Test that an allowed proxied request succeeds and a direct or non-allowlisted request fails. See private networking and egress.
Sandbox selection
There is no single security ranking that applies to every backend. Choose based on the workload's required capabilities and the isolation boundary you can verify:
| Backend | Appropriate use | Security boundary |
|---|---|---|
empty | Model calls and custom tools with no shell or filesystem | No shell/filesystem surface |
virtual | Deterministic tests and lightweight in-memory work | Process-level; not for untrusted code |
docker or provider container/microVM | Untrusted shell, package installs, generated code, uploaded data | Separate container or managed isolation boundary |
local | Trusted repository automation that intentionally needs host tools | Host files, processes, environment, and credentials may be reachable |
| host execution outside a Harness sandbox | Only when the application owns equivalent controls | No Harness isolation boundary |
For untrusted workloads, prefer Docker or a certified provider container/microVM over local.
local may be operationally convenient, but it is not more isolated than Docker.
The Docker sandbox defaults to:
- network disabled with
--network none; - read-only root filesystem;
- writable
/tmptmpfs; - bounded stdout and stderr capture.
Review CPU, memory, PID, timeout, mount, output, cleanup, and network limits explicitly for production. Never mount credential directories or a Docker socket into an untrusted session.
Sandbox-layer policy
init({ policy }) wraps the session sandbox so direct sandbox.exec, readFile, and writeFile
calls honor command and filesystem policy. Avoid bypassPolicyEnforcement: true unless a stronger,
tested enforcement layer replaces it.
Approval-required operations should run through session.shell() or typed tools, where the session
can create and consume durable approvals. A low-level sandbox call can report that approval is
required, but it cannot safely resolve one without session identity and history.
HTTP ingress
Generated Node and Cloudflare servers support baseline hardening:
export FABRIC_HARNESS_API_TOKEN='resolve-this-from-a-secret-manager'
export FABRIC_HARNESS_MAX_BODY_BYTES=1048576
export FABRIC_HARNESS_RATE_LIMIT_MAX=60
export FABRIC_HARNESS_RATE_LIMIT_WINDOW_MS=60000
export FABRIC_ENV=production- Require authentication on all non-health routes.
- Set body-size and per-client rate limits.
- In production, expose only definitions with explicit webhook triggers.
- Require tenant identity and reject cross-tenant reads.
- Verify channel/webhook signatures before dispatch.
- Put internet-facing deployments behind an identity-aware gateway, WAF, and distributed rate limiter. The built-in in-memory limiter is not a shared multi-instance control.
The local server exposes equivalent flags:
fabric-harness dev \
--auth-token-env FABRIC_HARNESS_API_TOKEN \
--max-body-bytes 1048576 \
--rate-limit-window-ms 60000 \
--rate-limit-max 60Durable execution and identity
- Bound model turns, tool calls, retries, tokens, wall-clock duration, command timeouts, and concurrency.
- Propagate cancellation through sessions, models, tools, sandboxes, workflows, and deployment adapters. Never convert cancellation into an unbounded retry.
- Keep Temporal workflow code deterministic; put model calls, network I/O, clocks, and other nondeterministic effects in activities.
- Use stable idempotency keys for retryable external operations.
- Isolate persistent-agent configuration, state, and credentials by tenant and addressed identity.
- Keep terminal, exhausted, cancelled, retryable, and permanent failures distinguishable.
Temporal credentials remain runtime-only. Durable configuration serializes the environment-variable reference, not the secret value.
Build and supply-chain integrity
- Generate SBOMs for package and image builds.
- Emit provenance and attestations.
- Sign provenance with a protected key or keyless workload identity.
- Verify provenance and attestation before deployment.
- Pin reviewed action and provider generations.
- Scan packed packages and images for secret patterns and incompatible licenses.
pnpm check:release
pnpm check:supply-chain
fh verify-attestation BUILD_DIRECTORY_OR_ATTESTATION
fh verify-provenance BUILD_DIRECTORY_OR_PROVENANCESnapshots, stores, and audit evidence
Local and Docker snapshots include a manifest with per-file byte counts and SHA-256 hashes; restore verifies the manifest before replacing workspace contents. Apply retention and deletion policies to snapshots, session stores, submissions, attachments, and artifacts.
import { pruneSnapshots } from '@fabric-harness/sdk';
await pruneSnapshots(snapshotRoot, { keep: 10 });
await pruneSnapshots(snapshotRoot, { olderThanMs: 7 * 24 * 60 * 60 * 1000 });Keep durable stores enabled for production. Retain enough active history to meet audit needs before compaction, and correlate actor/tenant identity, approval records, effects, artifacts, costs, lineage, and terminal state. Test tenant deletion and disaster recovery rather than assuming store availability implies recoverability.
Production review checklist
- Authentication, tenant binding, webhook signatures, body limits, and distributed rate limiting are verified.
- Secrets remain references until a trusted runtime boundary and are absent from logs, model context, durable state, and build output.
- Definition policy is the security floor; tools, commands, mounts, and connectors use least privilege.
- Custom HTTP clients cannot bypass egress controls because an external network boundary is active.
- Untrusted execution uses a verified container or microVM boundary, not
local. - Cancellation, timeout, retry, idempotency, cleanup, and crash recovery tests pass.
- SBOM, provenance, signatures, vulnerability checks, and license review pass.
- Audit retention, tenant deletion, backup, restore, and incident procedures have named owners.