Skip to content

Production hardening and security recovery

Production hardening and security recovery

Section titled “Production hardening and security recovery”

This checklist is for deployment/security administrators and project owners. Do not execute live changes solely because they appear here. All command/config examples in this manual are unexecuted; production credential rotation, account resets, network changes and deletion need explicit approval. See security settings for exact defaults/parsers.

Viat executes developer-supplied code. Distinct worker UID, cleared environments and resource brokers reduce exposure; they are not a guarantee that hostile code cannot use the network, consume resources or read every granted resource credential. Some database/cache/AMQP/S3 objects still project credentials to scripts in 1.1.0. Therefore:

  • Give code-authoring access only to trusted authors for the resources they can access; use separate instances/accounts/networks for mutually untrusted tenants/workloads.
  • Keep resource database/service accounts least-privilege. A resource with broad production credentials expands the authority of scripts, regardless of log masking.
  • Keep container memory/PID limits, syscall confinement and host patching. Do not mount Docker socket, host root, platform key directories or unrelated backups into script-visible trees.
  • Enforce egress with network controls. VIAT_OUTBOUND_DENY_PRIVATE is a selected save-time host check, not complete DNS-rebinding protection or arbitrary-code firewall.
  • Treat Rust compile permission as privileged code execution on the builder: Cargo dependencies/build scripts can execute before runtime worker UID drop.
  1. Pin an approved 1.1.0 image/digest and record server/client versions separately. Use a supported host/container runtime and maintain security updates; old bullseye images are a transition path, not an evergreen security recommendation.
  2. Set independent strong master/JWT values, keep the original master key in separate recovery custody, and verify no built-in development JWT warning appears at startup. The binary does not fail closed on the known JWT default.
  3. Keep public registration disabled unless deliberately required; confirm a working Owner before removing bootstrap credentials. Bootstrap password changes do not reset existing accounts.
  4. Restrict management ingress, serve HTTPS, set a trusted VIAT_PUBLIC_URL, and only trust forwarded IP headers behind controlled proxies. An API-only node can disable console/docs, but the API still needs authentication/network policy.
  5. Check worker identity startup logs: Docker parent is root to launch uid/gid 10001 children. Missing account, malformed explicit UID or disabled drop may keep workers at server identity. Running the parent unprivileged does not somehow preserve a distinct child UID.
  6. Limit file/watch/SQLite roots and mount only approved directories. VIAT_WORKER_DATA_DIRS changes ownership recursively; never point it at broad host trees or the platform spool.
  7. Enable suitable MFA policy after enrollment/recovery preparation, use least-privilege PAT scopes, and review actual operator/developer/admin/owner project assignments. Platform roles and project membership differ.
  8. Protect /metrics with a random token and monitoring-only network access; protect remote log/trace stores and payloads as sensitive data. Do not disable TLS verification to get private-CA integrations working.
  9. Back up platform data, master key, external secrets/business stores/file bytes consistently and validate an isolated restore.
ItemSupported operational approachHazard
Platform JWT secretApproved coordinated restart of all nodes, then reauthenticate/reissue affected credentialsInvalidates signed tokens; inconsistent nodes cause intermittent failures
Master keyPreserve existing key; any re-encryption/migration needs a separately designed, verified procedureReplacing env value alone strands AES ciphertext; not an automatic rotation feature
Resource credentialUpdate using authorized resource API/console, validate controlled target, coordinate published/live behaviorSome objects are readable in scripts; old credentials need explicit provider revocation
Vault token/AWS identityRotate scoped provider identity, keep historical-reference read access; restart static-config clients as requiredVault token is not renewed by Viat; changing backend selector does not migrate blobs
TLS certificateAtomically replace matched PEM pair; direct TLS polls mtimes every 60sBad reload keeps previous cert; monitor expiry/served fingerprint externally
CLI/MCP session/PATRevoke server-side session/token using actual auth controls, remove local copy under policyDeleting .viat/config.yaml alone is not proof every server credential was revoked

Do not forward secrets via broad VIAT_RUNTIME_ENV_PASSTHROUGH rules. The denylist protects specific core names and Cargo/SSH families, not every possible application secret. Package-registry tokens in default forwarded namespaces can be visible to workers. Validate custom passthrough with harmless markers, not real credentials in script output.

  1. Record UTC interval, affected identities/projects, request/run IDs and node/image versions. Preserve privately scoped logs/audit/backend events; avoid copying live secrets into incident tickets.
  2. Fence malicious ingress/producers and isolate affected nodes under the incident plan. Cancelling a run may not cancel already-committed external work; killing every container may destroy useful volatile evidence.
  3. Revoke affected sessions/PATs/resource/provider credentials through the correct control plane. Review project permissions, published snapshots, shared modules, alert destinations and external account bindings. A restored old backup can resurrect queued work/credentials.
  4. Determine exposure using control/business audit, provider logs and resource permissions. Absence of a row is not proof of no activity: anonymous noise, some reads and best-effort sink failures have documented gaps.
  5. Rebuild from approved artifacts and restore known-good data into isolation. Do not blindly copy compromised caches/binaries or replay queued side effects.
  6. Prove recovery with known fixtures, correct worker identity, activation, probes and external monitoring; reopen in stages, record residual unvalidated dependencies and review root cause.

Business postgresql resource ssl is currently ignored; MySQL ssl=true means Preferred and can fall back. Enforce required transport at a validated database/proxy/network boundary and verify it, rather than treating resource save as proof. See database configuration.

In-process alerts cannot guarantee notification during process/DB/egress failure; provider acceptance is not recipient delivery. Audit tables are not independent WORM storage against a DBA. Leases/advisory locks and idempotency records are not blanket exactly-once/HA guarantees. Explicitly document any compensating controls needed by your risk/compliance requirements.