Skip to content

Threat Model

Scope and Methodology

  • Scope: Cloud-Native DCS platform deployed on Kubernetes for pharmaceutical batch manufacturing
  • Methodology: STRIDE (per-element analysis) with MITRE ATT&CK for ICS mapping
  • Alignment: IEC 62443-3-2 (security risk assessment for IACS), IEC 62443-3-3 (system security requirements)
  • Last updated: 2026-03-24
  • Review cadence: Annually, or after major architecture changes, new component additions, or significant security incidents

This threat model covers the Cloud-Native DCS application layer. Kubernetes control plane security, underlying OS hardening, and physical site security are out of scope but noted as assumptions.

BPCS-layer protection — not a safety-rated system

Cloud-Native DCS is a Basic Process Control System. It is not a Safety Instrumented System under IEC 61508 / IEC 61511 and is not rated for SIL 1, SIL 2, SIL 3, or SIL 4 functions. Security hardening protects the process-control plane against cyber threats. It does not turn it into a safety-rated shutdown system. Its interlocks and alarms are BPCS-layer protection functions. Whether a given hazard (emergency shutdown, overpressure trip, burner management, LEL/gas trip) requires an independent SIS is a process-hazard-analysis (PHA/LOPA) decision, and any function assigned to an SIS lives on independent, separately certified safety-PLC or hardwired-trip hardware that this software does not control.

System Description

Cloud-Native DCS is an ISA-88 compliant Distributed Control System that runs on Kubernetes. It manages pharmaceutical batch manufacturing processes through a hierarchy of CRDs representing physical equipment, procedural sequences, recipes, and batch executions. Operators reconcile CRDs into runtime state, unit runtimes execute control logic on edge devices, and a centralized gateway provides API and UI access for plant operators and engineers.

Component Inventory

Component Function Runs On Exposed Interfaces
Gateway REST API, Web UI Control plane node HTTP :8090
Physical Operator Manages equipment hierarchy CRDs Control plane node Metrics :8080, Health :8081
Procedural Operator Manages procedural sequence CRDs Control plane node Metrics :8080, Health :8081
Batch Operator Manages batch execution and recipe CRDs Control plane node Metrics :8080, Health :8081
Control Operator Deploys control programs to unit runtimes Control plane node Metrics :8080, Health :8081
MQTT Broker Pub/sub for telemetry, commands, events Control plane node MQTTS :8883 (prod), WS :9443
Unit Runtime Executes FB networks, drives I/O on edge devices Edge device node (hostNetwork: true) HTTP :61152 bound on the host network; hostPath volume for FB-state persistence
IO-Probe Per-Controller I/O connectivity health check Edge device node None (reports via CRD status)
Historian MQTT subscriber, writes telemetry to PostgreSQL Control plane node HTTP :8092
Audit Archiver CronJob: archives AuditRecords to PostgreSQL Control plane node None (batch job)

Deployment Topology

A typical pharmaceutical deployment consists of a Kubernetes cluster (e.g., k3s) with control plane nodes running operators, gateway, MQTT broker, and historian. Edge device worker nodes join the cluster at the deployment layer (e.g., Talos machine config, per ADR 0004), are registered as Controller resources, and run unit runtimes pinned via nodeSelector with dcs.io/device=<unit-name> labels.

Edge devices communicate with field I/O modules (e.g., WAGO 750-series couplers, Turck TBEN modules) over Modbus TCP, EtherNet/IP, or OPC UA on a dedicated field bus network segment. Network segmentation follows IEC 62443 zone/conduit principles with Kubernetes NetworkPolicies enforcing boundaries between Control Zone, Field Zone, External Zone, and Field Bus Zone.

Key configuration surface areas are centralized in the Helm chart (Helm values.yaml), including security toggles for mTLS (mtls.enabled), NetworkPolicies (networkPolicies.enabled), MQTT security profile (mqtt.securityProfile), OIDC authentication (gateway.auth), and rate limiting (gateway.rateLimit).

Existing Security Controls

The following controls are implemented and referenced as mitigations throughout this threat model:

Control Scope Configuration
mTLS (cert-manager) All inter-component HTTP mtls.enabled in Helm values
MQTT TLS + auth + ACLs Broker connections mqtt.securityProfile: production
OIDC authentication Gateway API/UI gateway.auth.oidc in Helm values
Kubernetes RBAC Operator CRD access Generated RBAC ClusterRoles
NetworkPolicies Zone/conduit boundaries networkPolicies.enabled
Pod hardening All containers, including unit-runtime (which keeps hostNetwork + hostPath by design — see UR-E-01) Distroless, non-root, no caps
Immutable audit trail AuditRecord CRD Webhook + RBAC create-only
Electronic signatures Recipe approval, batch HMAC-SHA256
Rate limiting Gateway API gateway.rateLimit in Helm values
Image signing + SBOM Release pipeline Cosign + syft in CI
Vulnerability scanning Release pipeline Trivy + govulncheck in CI

Data Flow Diagram

flowchart TD
    Users[Operators<br/>Engineers, QA] -->|HTTPS / OIDC Bearer<br/>TB1| Ingress
    Ingress --> GW[Gateway<br/>REST :8090]
    GW -->|TB2| K8s[(k8s API / CRDs)]
    GW -->|MQTTS :8883<br/>TB3| MQTT[MQTT Broker]
    K8s --> Ops[Physical / Procedural / Batch / Control Operators]
    Ops -->|pub/sub| MQTT
    MQTT -->|sub only| Hist[Historian]
    Hist --> PG[(PostgreSQL / TimescaleDB)]
    MQTT -->|TB4| RT[Unit Runtime<br/>:61152]
    RT -->|Modbus / EtherNet/IP / OPC UA<br/>TB5| IO[I/O Modules<br/>field]

Legend: TB = Trust Boundary (dashed lines), arrows = data flow direction.

Trust Boundaries

ID Boundary Side A Side B Protocol Protection
TB1 External Network / Gateway End users (browser, CLI) Gateway pod HTTPS TLS termination at ingress, OIDC JWT authentication
TB2 Gateway / Kubernetes API Server Gateway pod kube-apiserver HTTPS ServiceAccount RBAC, least-privilege ClusterRole
TB3 Control Zone / MQTT Broker Operators, Gateway MQTT Broker MQTTS :8883 TLS + per-role credentials + topic ACLs
TB4 MQTT Broker / Field Zone MQTT Broker Unit Runtimes MQTTS :8883 TLS + dcs-runtime credentials + restricted ACLs
TB5 Unit Runtime / Field Bus Unit Runtime pod I/O Modules (Modbus/EIP) Modbus TCP, EtherNet/IP Protocol-native; physical network isolation
TB6 Historian / PostgreSQL Historian pod TimescaleDB (CNPG) PostgreSQL wire protocol Database credentials via Kubernetes Secret

Legacy Plaintext Field Protocols (TB5 Compensating Controls)

Modbus TCP (and EtherNet/IP) carry no authentication and no encryption. The protocols themselves define none, so the drivers (pkg/driver/modbus/) have none to offer. Any host with network reachability to an I/O module can read coils and write registers. For IEC 62443-3-3 SR 3.1 (communication integrity) the conduit between the unit-runtime node and the I/O modules therefore relies entirely on compensating controls, all of which are required in production:

  1. Layer-2 segmentation of the field bus. I/O modules live on a dedicated OT VLAN or physically separate switch fabric reachable only from the unit-runtime device nodes. No route exists from the IT network, the cluster pod network, or the internet to the field bus segment. See the reference architectures for the wiring this assumes.
  2. NetworkPolicy scope. networkPolicies.fieldBusCIDRs restricts which workloads may egress to the field bus CIDR: only unit-runtime pods (hostNetwork: true on the device nodes) and the node-pinned io-probe pods at the zone edge.
  3. Physical security of the conduit. Switches, cabling, and I/O modules are inside locked cabinets/rooms. An attacker with physical access to the field bus defeats segmentation (see Residual Risks).

Zone/conduit summary: the field bus is a separate IEC 62443 zone whose only conduit is the unit-runtime node itself. Isolation provides that zone's security level, and the protocol provides none of it.

Prefer OPC UA where the hardware supports it. The OPC UA driver is secure-by-design here: sessions default to Sign and can be raised to SignAndEncrypt per Unit serviceBinding (or per IOModule), and gateway.opcua.allowInsecure stays false. Plaintext Modbus/EtherNet/IP should be reserved for devices that offer nothing better.

STRIDE Analysis

Gateway

ID Cat Description Impact Likelihood Mitigation Status
GW-S-01 S Spoofed user identity via stolen or forged OIDC token Major Unlikely OIDC JWT validation with provider key rotation; short-lived tokens Implemented
GW-S-02 S Bypass auth on exempt routes to access sensitive data Moderate Unlikely Exempt routes limited to health, static assets, auth config Implemented
GW-T-01 T Tampered API requests modifying batch parameters Catastrophic Unlikely OIDC auth + RBAC group checks; ControlRecipe immutability Implemented
GW-T-02 T Tampered recipe approval to bypass quality review Major Unlikely Electronic signatures (HMAC-SHA256) bind signer, timestamp, meaning Implemented
GW-R-01 R Operator denies performing a critical action Major Possible Immutable AuditRecords with user attribution; webhook enforcement Implemented
GW-I-01 I Recipe IP or process parameters leaked via API Major Unlikely OIDC auth required for API; NetworkPolicy restricts ingress sources Implemented
GW-I-02 I Session token leaked in logs or error responses Moderate Rare Structured logging without token values; no token echo in responses Implemented
GW-T-03 T Replay of captured mutating request (e.g. Start batch) Major Unlikely Anti-replay middleware requires unique X-DCS-Nonce on POST/PUT/DELETE; in-memory nonce store rejects duplicates within configurable window (default 10 min); IEC 62443 SR 3.8. Constraint: the nonce store is per-replica, so the guarantee holds only with a single gateway replica — the Helm chart refuses to render gateway.replicas > 1 while anti-replay is enabled (#468); a shared nonce store is future work gated on an HA-gateway requirement Implemented
GW-D-01 D API flooding causes gateway unavailability Major Possible Per-IP rate limiting (configurable read/write limits in Helm values) Implemented
GW-D-02 D WebSocket exhaustion from excessive connections Moderate Unlikely Per-source-address ceiling on concurrent live streams, counting WebSocket and SSE together (gateway.streamLimits.maxConnectionsPerIP, default 10); a connect over it is refused with 429 + Retry-After and counted in dcs_gateway_stream_connections_refused_total. There is no setting that removes the ceiling. Resource limits on the gateway pod (CPU/memory) bound what the admitted connections can cost. Constraint: the count is per source address, so consumers behind one NAT share an allowance and the ceiling has to be sized for them (#1447) Implemented
GW-E-01 E Operator escalates to admin functions Major Unlikely OIDC group-based authorization (dcs-admin group check) Implemented
GW-E-02 E Setup token reuse after initial configuration Threat retired: the setup-token bootstrap and the /api/v1/setup* endpoints it authenticated were removed (ADR 0004, #487) — the asset no longer exists. ID kept for audit traceability of historical InvalidateSetupToken records Retired

Operators (Physical, Procedural, Batch, Control)

ID Cat Description Impact Likelihood Mitigation Status
OP-S-01 S Unauthorized pod impersonates an operator Catastrophic Rare ServiceAccount per operator; RBAC restricts CRD access Implemented
OP-S-02 S Spoofed operator identity on MQTT Major Unlikely Per-role MQTT credentials (dcs-operator); topic ACLs Implemented
OP-T-01 T Tampered CRD specs (recipe parameters, FB networks) Catastrophic Unlikely Kubernetes RBAC; AuditRecord on all changes; spec hash verification Implemented
OP-T-02 T Phantom stale FB networks persist after pod restart Major Possible Garbage collection of orphaned networks on reconcile Implemented
OP-R-01 R Configuration change without audit attribution Major Unlikely Audit recorder creates AuditRecords for CRD mutations Implemented
OP-I-01 I Metrics endpoint exposes internal state Minor Unlikely NetworkPolicy restricts metrics access to monitoring namespace Implemented
OP-D-01 D Leader election disruption causes reconciler outage Major Rare Leader election via controller-runtime; PDB available in Helm Implemented
OP-D-02 D etcd storage exhaustion from excessive CRDs Major Unlikely Audit archiver moves old records to PostgreSQL; resource limits Implemented
OP-E-01 E RBAC escalation to modify resources beyond scope Major Rare Least-privilege ClusterRole; separate ServiceAccount per operator Implemented

MQTT Broker

ID Cat Description Impact Likelihood Mitigation Status
MQ-S-01 S Unauthorized client connects to broker Major Unlikely TLS + per-role authentication; anonymous connections rejected Implemented
MQ-S-02 S Credential theft enables impersonation of a role Major Unlikely Credentials stored in Kubernetes Secrets; passwords auto-generated Implemented
MQ-T-01 T Tampered telemetry data on MQTT topics Major Unlikely TLS encryption in transit; per-role topic ACLs limit write access Implemented
MQ-T-02 T Injected control commands on equipment command topics Catastrophic Unlikely Runtime role restricted to read-only on command topics; ACL enforce Implemented
MQ-R-01 R Unattributed message publishing Moderate Possible MQTT username logged per connection; Mosquitto auth logging enabled Implemented
MQ-I-01 I Eavesdropping on telemetry topics Major Unlikely TLS encryption (port 8883); plaintext port 1883 disabled in prod Implemented
MQ-D-01 D Broker resource exhaustion from message flood Major Possible Resource limits on broker pod; persistence volume size limits Partial
MQ-D-02 D Broker unavailability disrupts telemetry pipeline Major Unlikely Runtime store-and-forward queue buffers messages during outage Implemented
MQ-E-01 E Topic ACL bypass allows cross-role access Major Rare ACL file generated from Helm values; tested via helm template Implemented

Unit Runtime

ID Cat Description Impact Likelihood Mitigation Status
UR-S-01 S Spoofed control commands to runtime HTTP API Catastrophic Unlikely mTLS on HTTP API; fail-closed bearer token auth (unitRuntime.auth) Implemented
UR-T-01 T Tampered function block network deployed to runtime Catastrophic Unlikely mTLS authenticates control-operator; spec hash verification Implemented
UR-T-02 T Tampered I/O values via compromised runtime binary Catastrophic Rare Distroless image; cosign-signed images; enforced read-only root filesystem Implemented
UR-I-01 I Process data leaked from runtime HTTP API Moderate Unlikely mTLS restricts API access; NetworkPolicy limits ingress to control Implemented
UR-I-02 I Persisted FB network on host disk read by attacker Moderate Rare Host path restricted to runtime pod; physical device security Partial
UR-D-01 D Runtime crash or hang affects physical process Catastrophic Possible Liveness/readiness probes; Kubernetes auto-restart; local autonomy Implemented
UR-D-02 D Resource exhaustion from runaway control program Major Unlikely Pod resource limits (CPU/memory) in Helm values Implemented
UR-E-01 E Container escape from runtime pod to host Catastrophic Rare Enforced securityContext (runAsNonRoot, no privilege escalation, all capabilities dropped, seccomp RuntimeDefault, read-only root FS); hostNetwork + hostPath still widen the host surface by design Partial

IO-Probe

ID Cat Description Impact Likelihood Mitigation Status
IP-S-01 S Spoofed IO-Probe reports false connectivity status Moderate Rare IO-Probe deployed by physical-operator; ServiceAccount scoped Implemented
IP-T-01 T Tampered probe results hide I/O module failures Major Rare Probe writes to Controller CRD status; RBAC restricts access Implemented
IP-D-01 D Probe failure leaves stale connectivity information Moderate Unlikely Kubernetes restarts failed probe pods; status age visible in UI Implemented

Historian and Audit Archiver

ID Cat Description Impact Likelihood Mitigation Status
HI-S-01 S Spoofed MQTT telemetry data ingested as genuine Major Unlikely MQTT per-role auth; historian uses dcs-historian read-only role Implemented
HI-T-01 T Tampered historical records in PostgreSQL Major Rare Database credentials via Kubernetes Secret; CNPG manages access Partial
HI-I-01 I Historical process data disclosed to unauthorized Major Unlikely NetworkPolicy restricts historian ingress; DB credentials in Secret Implemented
HI-D-01 D Database storage exhaustion from telemetry volume Major Possible Configurable retention (default 365 days); buffer flush interval Implemented
AA-T-01 T Audit records modified during archival Major Rare Idempotent archival; webhook enforces immutability; archive flag Implemented
AA-D-01 D Archiver job failure leaves stale records in etcd Moderate Unlikely CronJob retry policy; idempotent operation; monitoring via metrics Implemented

MITRE ATT&CK for ICS Mapping

Technique Name Component Threat ID Mitigation
T0819 Exploit Public-Facing App Gateway GW-D-01, GW-E-01 Rate limiting; OIDC auth; RBAC groups; input validation (gap)
T0886 Remote Services Gateway, Runtime GW-S-01, UR-S-01 OIDC JWT; mTLS on runtime API; fail-closed bearer token auth
T0859 Valid Accounts Gateway, MQTT GW-S-01, MQ-S-02 OIDC token expiry; auto-generated MQTT passwords; Secrets
T0862 Supply Chain Compromise All UR-T-02 Cosign image signing; SBOM (syft); Trivy scanning; govulncheck
T0821 Modify Controller Tasking Control Operator OP-T-01, UR-T-01 RBAC on ControlProgram CRDs; mTLS deploy; spec hash verify
T0836 Modify Parameter Batch Operator GW-T-01, GW-T-03, OP-T-01 ControlRecipe immutability; e-signatures; anti-replay nonce
T0855 Unauthorized Command Message MQTT Broker MQ-T-02 Topic ACLs restrict command topic write to operator role
T0831 Manipulation of Control Unit Runtime UR-T-01, UR-T-02 mTLS; distroless images; read-only FS; no shell in container
T0882 Theft of Operational Information Gateway, MQTT GW-I-01, MQ-I-01 OIDC auth on API; TLS on MQTT; NetworkPolicy segmentation
T0880 Loss of Safety Unit Runtime UR-D-01 Liveness probes; auto-restart; SIS assumed independent (IEC 61511)
T0826 Loss of Availability Gateway, MQTT GW-D-01, MQ-D-01 Rate limiting; pod resource limits; store-and-forward queue
T0832 Manipulation of View Historian HI-S-01, HI-T-01 MQTT auth prevents spoofed writes; DB credentials in Secrets
T0856 Spoof Reporting Message MQTT Broker MQ-T-01, HI-S-01 Per-role MQTT auth; TLS; topic ACLs; Mosquitto logging
T0830 Man in the Middle All MQ-I-01, UR-I-01 mTLS for HTTP; TLS for MQTT; cert-manager certificate mgmt

Risk Assessment Matrix

Rating scale:

Likelihood \ Impact Negligible Minor Moderate Major Catastrophic
Almost Certain Low Medium High Critical Critical
Likely Low Medium High Critical Critical
Possible Low Low Medium High High
Unlikely Low Low Medium Medium High
Rare Low Low Low Medium Medium

Risk Ratings

Threat ID Description Likelihood Impact Risk
GW-S-01 Spoofed OIDC token Unlikely Major Medium
GW-T-01 Tampered batch parameters via API Unlikely Catastrophic High
GW-T-02 Tampered recipe approval Unlikely Major Medium
GW-T-03 Replay of captured mutating request Unlikely Major Medium
GW-R-01 Repudiated operator action Possible Major High
GW-I-01 Recipe IP leaked via API Unlikely Major Medium
GW-D-01 API flooding Possible Major High
GW-D-02 WebSocket exhaustion Unlikely Moderate Medium
GW-E-01 Operator privilege escalation Unlikely Major Medium
OP-S-01 Unauthorized operator pod Rare Catastrophic Medium
OP-T-01 Tampered CRD specs Unlikely Catastrophic High
OP-T-02 Phantom stale FB networks Possible Major High
OP-R-01 Unattributed config change Unlikely Major Medium
OP-D-01 Leader election disruption Rare Major Medium
OP-D-02 etcd storage exhaustion Unlikely Major Medium
OP-E-01 RBAC escalation Rare Major Medium
MQ-S-01 Unauthorized MQTT client Unlikely Major Medium
MQ-T-01 Tampered telemetry data Unlikely Major Medium
MQ-T-02 Injected control commands Unlikely Catastrophic High
MQ-R-01 Unattributed MQTT publish Possible Moderate Medium
MQ-D-01 Broker resource exhaustion Possible Major High
MQ-D-02 Broker unavailability Unlikely Major Medium
MQ-E-01 Topic ACL bypass Rare Major Medium
UR-S-01 Spoofed commands to runtime Unlikely Catastrophic High
UR-T-01 Tampered FB network deployment Unlikely Catastrophic High
UR-T-02 Tampered I/O via compromised binary Rare Catastrophic Medium
UR-I-01 Process data leak from runtime API Unlikely Moderate Medium
UR-I-02 Persisted FB network read from disk Rare Moderate Low
UR-D-01 Runtime crash affecting process Possible Catastrophic High
UR-D-02 Runaway control program resource exhaustion Unlikely Major Medium
UR-E-01 Container escape to host Rare Catastrophic Medium
IP-S-01 Spoofed IO-Probe connectivity report Rare Moderate Low
IP-T-01 Tampered probe hides I/O failures Rare Major Medium
IP-D-01 Stale probe data from pod failure Unlikely Moderate Medium
HI-S-01 Spoofed telemetry ingested Unlikely Major Medium
HI-T-01 Tampered historical records Rare Major Medium
HI-D-01 Database storage exhaustion Possible Major High
AA-T-01 Audit record modification during archival Rare Major Medium

Mitigations Summary

Threat ID Mitigation Status Evidence
GW-S-01 OIDC JWT validation with key rotation Implemented gateway.auth.oidc in Helm values
GW-T-01 OIDC auth + RBAC group checks Implemented OIDC auth middleware with group-based authorization
GW-T-02 HMAC-SHA256 electronic signatures Implemented Electronic signatures bind signer, timestamp, and meaning
GW-T-03 Anti-replay nonce on mutating requests Implemented gateway.antiReplay in Helm values; X-DCS-Nonce header required; single-replica constraint enforced at chart render
GW-R-01 Immutable AuditRecords, webhook enforcement Implemented Validating webhook enforces create-only on AuditRecords
GW-I-01 OIDC auth on all API routes; NetworkPolicy Implemented Helm NetworkPolicy for gateway; OIDC auth on all API routes
GW-D-01 Per-IP rate limiting (read/write configurable) Implemented gateway.rateLimit in Helm values
GW-D-02 Per-IP live-stream connection ceiling + pod limits Implemented gateway.streamLimits.maxConnectionsPerIP and gateway.resources in values.yaml
GW-E-01 OIDC group-based authorization Implemented dcs-admin group check via OIDC claims
OP-S-01 Per-operator ServiceAccount + RBAC Implemented Helm ServiceAccount templates; generated RBAC ClusterRoles
OP-T-01 RBAC + audit trail + spec hash verification Implemented Spec hash verification on FB network deployment
OP-T-02 Phantom network garbage collection Implemented Orphaned FB network cleanup during reconciliation
OP-R-01 Audit recorder on all CRD mutations Implemented Audit recorder creates AuditRecords for all CRD mutations
OP-D-01 controller-runtime leader election; PDB Implemented leaderElect: true in Helm values; PDB templates
OP-D-02 Audit archiver CronJob Implemented historian.audit.archival in Helm values
OP-E-01 Least-privilege ClusterRole per operator Implemented Generated RBAC ClusterRoles with least-privilege scoping
MQ-S-01 TLS + per-role authentication Implemented Helm MQTT auth secret template; mqtt.securityProfile
MQ-T-01 TLS encryption; topic ACLs Implemented mqtt.tls and mqtt.auth in Helm values
MQ-T-02 Runtime ACL restricted to read on command topics Implemented Helm MQTT auth secret template with topic ACLs
MQ-R-01 Mosquitto connection and auth logging Implemented mqtt.securityProfile: production enables logging
MQ-D-01 Pod resource limits; persistence volume sizing Partial mqtt.resources and mqtt.persistence.size in Helm values
MQ-D-02 Runtime store-and-forward queue Implemented --mqtt-queue-size flag on unit runtime
MQ-E-01 ACL file generated from Helm templates Implemented Helm MQTT auth secret template
UR-S-01 mTLS on HTTP API; fail-closed bearer token auth Implemented unitRuntime.auth in Helm values (runtime refuses to start without a token unless --insecure-no-auth); mTLS via cert-manager
UR-T-01 mTLS + spec hash verification on deploy Implemented Spec hash verification on FB network deployment
UR-T-02 Cosign-signed images; distroless; SBOM Implemented Release pipeline: Cosign signing, syft SBOM, Trivy scanning; read-only root filesystem enforced on the runtime pod (#722)
UR-I-01 mTLS + NetworkPolicy Implemented Helm NetworkPolicy for runtime; mTLS via cert-manager
UR-I-02 Host path restricted to runtime pod Partial Pod-level volume mount; no encryption at rest
UR-D-01 Liveness probes; auto-restart; local autonomy Implemented Helm deployment templates; local persistence for autonomy
UR-D-02 Pod CPU/memory limits Implemented unitRuntime.resources in Helm values
UR-E-01 Enforced non-root securityContext Partial Distroless nonroot image (UID 65532) with enforced runAsNonRoot, allowPrivilegeEscalation=false, all capabilities dropped, seccomp RuntimeDefault, and read-only root FS (#722); still runs hostNetwork with a hostPath volume by design. A short-lived root init container (capabilities bounded to CHOWN/DAC_OVERRIDE/FOWNER, privileged: false) chowns the kubelet-created hostPath to the runtime UID (#731)
HI-S-01 MQTT per-role auth; historian read-only Implemented mqtt.auth.users.historian in Helm values
HI-T-01 Database credentials via Kubernetes Secret Partial CNPG manages credentials; no application-level record signing
HI-D-01 Configurable retention; buffer flush interval Implemented historian.retention.days, historian.buffer in Helm values
AA-T-01 Idempotent archival; webhook immutability Implemented Idempotent archival with webhook-enforced immutability
IP-S-01 IO-Probe deployed by physical-operator Implemented Physical-operator manages IO-Probe pod lifecycle
IP-T-01 RBAC restricts Controller status updates Implemented Generated RBAC ClusterRoles restrict status update access
IP-D-01 Kubernetes auto-restarts failed probe pods Implemented Probe pod managed by physical-operator reconciler

Residual Risks and Accepted Assumptions

  • Kubernetes control plane integrity is assumed. Cluster-admin responsibility includes securing kube-apiserver, etcd, and kubelet. This threat model does not cover control plane compromise.

  • etcd encryption at rest is assumed. Enabling EncryptionConfiguration for Secrets and CRDs is a cluster-level configuration outside the application scope.

  • Physical security of edge devices is out of scope. An attacker with physical access to a Raspberry Pi or similar edge node can extract persisted FB networks, MQTT credentials, or TLS certificates from disk. Physical access controls are a site-level responsibility.

  • Safety-instrumented systems (SIS) are independent per IEC 61511. The DCS is a BPCS. It is not a safety-rated system. Where a process hazard analysis (PHA/LOPA) assigns a function to an SIS, that SIS is independent per IEC 61511, on separate hardware this software does not control, and is therefore outside this threat model's boundary.

  • OIDC provider security is delegated. Token issuance, revocation, password policies, and MFA are the responsibility of the configured identity provider (Keycloak, Azure AD, Okta, etc.).

  • Field bus protocol security depends on device vendor capabilities. Modbus TCP, EtherNet/IP, and OPC UA connections to field I/O modules use protocol-native security (or none). Network isolation via networkPolicies.fieldBusCIDRs is the primary mitigation.

  • No protection against insider threats with valid admin credentials. A user with dcs-admin group membership and cluster-admin Kubernetes access can bypass all application-level controls. Organizational policies (separation of duties, access reviews) are required.

  • Container runtime (containerd/CRI-O) integrity is assumed. Container escape vulnerabilities in the runtime itself are outside application scope.

  • DNS resolution integrity within the cluster is assumed. CoreDNS poisoning could redirect inter-component traffic. DNSSEC or DNS-over-TLS within the cluster is not implemented.

  • Gateway input validation is incomplete. The REST API lacks comprehensive request validation and sanitization beyond CRD schema validation (OpenAPI). This is an identified gap (IEC 62443-3-3 SR 3.5).

  • No intrusion detection system (IDS). Anomalous network traffic or API usage patterns are not detected. Prometheus metrics provide operational monitoring but not security analytics. This is a planned SL 4 capability.

  • Historical record integrity relies on database access controls. No application-level cryptographic signing of historian records. Tamper detection depends on PostgreSQL access restrictions.