Skip to content

Security

Authentication

The WorkManager gRPC and HTTP endpoints accept connections authenticated via Dapr's service-to-service mTLS. All inter-service calls between the API Gateway, WorkManager, and WebSocketManager are secured by Dapr's built-in mutual TLS.

For external client access, authentication should be handled at the API Gateway layer. See API Gateway Security for JWT bearer token and role-based authorization configuration.

Code Execution Safety

Python Workers

Python workers execute in a persistent sandboxed subprocess with the following protections:

  • Launched with -E -s flags (disables PYTHON* environment variable injection and user site-packages)
  • Configurable blocked module list (blocks subprocess, os, socket, requests, and other I/O modules by default)
  • Configurable package allow-list via PYTHON_ALLOWED_PACKAGES environment variable
  • Code is injected directly via stdin — no temporary files written to disk
  • Stderr output is captured as warning-level logs, not treated as errors

The subprocess communicates with the host via a JSON-line message loop over stdin/stdout and stays alive for the worker's lifetime (no per-message process spawn overhead).

C# Workers

C# workers run in-process within the WorkManager host. They share the host process's permissions. For maximum safety, use Python workers with the module blocklist or consider containerizing C# workers as sidecar containers in Kubernetes.

URL Validation

When loading worker code from a URL, the WorkManager validates:

  • The URL host is in the ALLOWED_CODE_SOURCE_HOSTS list (if configured)
  • The URL does not resolve to a private/internal IP address (blocking SSRF attacks against 10.x, 172.16.x, 192.168.x, 127.x, ::1, fc00::/7, fe80::/10)
  • Optional SHA-256 content integrity verification via ContentSha256 field

Dapr Component Security

The WorkManager relies on Dapr for state storage and pub/sub messaging. Ensure Dapr components are configured with:

  • State store: Authentication enabled (Redis password for Valkey)
  • Pub/sub: Authentication enabled on the message broker
  • mTLS: Enabled in Dapr configuration (default since Dapr 1.0)

Configuration & Secrets

The WorkManager reads its configuration from the standard .NET configuration sources (in order: appsettings.json, environment variables, command-line). The following keys control runtime behavior and are the only ones that carry security-sensitive values:

Key Default Security role
AllowedCodeSourceHosts (empty) Host allow-list for worker code loaded from a URL. If empty, all hosts are allowed. Always set explicitly in production to prevent SSRF.
ALLOWED_CODE_SOURCE_HOSTS (empty) Environment-variable equivalent of the above (used by Program.cs:57).
Logging:LogLevel:Default Information Set to Warning or higher in production to avoid leaking sensitive worker code or input data into logs.

Worker Dapr component values (Redis password, broker credentials) are mounted at runtime via Dapr's secret management component (secretstores/kubernetes) — never commit them to source control. Dapr resolves them by key (e.g., stateStore.password) and the application reads them via DaprClient.GetSecretAsync.

Audit & Logging

The WorkManager emits structured logs for every state-mutating operation (CreateWorker, StartWorker, StopWorker, LoadCodeFromContent, LoadCodeFromUrl, DeleteWorker, RecoverWorkers) and every worker lifecycle event. Each log record includes the worker ID, the engine MIME type, and a correlation ID derived from the incoming gRPC request.

Fire-and-forget logging calls (sweeper events, completion continuations) are wrapped in try/catch and downgrade to LogLevel.Warning if the underlying stream write fails — this prevents observability failures from cascading into service failures.

Reporting Issues

Report security concerns to the Virtufin security team.