Epic: Dynamic PLC testing via ephemeral soft-PLC (deploy control logic → ICS + DAST) #183

Open
opened 2026-07-16 21:23:22 +00:00 by sharang · 1 comment
Owner

Motivation

Dynamic testing of a customer's PLC currently assumes we can reach the running
device over the network (a modbus:// / http:// live URL). For a real
customer that device sits on their OT network behind a firewall — our cloud
agent cannot reach it. The live-probe mode therefore only works with an
on-prem/edge agent (a separate deployment story) or a co-located lab (our
Demo C setup).

Provision-and-test removes the reachability requirement entirely: we
already ingest the control-logic artifact for SAST, so instead of reaching
their device we instantiate their logic ourselves in-cluster, start it,
and run dynamic tests against our own instance. No customer network access,
sandboxed, reproducible, and destructive tests become safe.

Model

control-logic artifact (ST / PLCopen XML / .projectarchive)
  → compile/load into an ephemeral soft-PLC container (in-cluster)
  → start the runtime (Modbus/TCP + WebVisu HTTP come up)
  → run ICS probe (Modbus/OPC-UA/EtherNet-IP) + DAST against the WebVisu
  → collect findings
  → tear the instance down

Substrate (decision: OpenPLC first)

  • OpenPLC (phase 1) — runs generic IEC 61131-3 (ST / a PLCopen-XML subset
    via MatIEC) and accepts a program upload through its web UI. No licensing.
    Won't run a real CODESYS .projectarchive (CODESYS vendor libs + runtime),
    but proves the deploy→run→probe→DAST loop end-to-end for generic ST.
  • CODESYS Control for Linux SL (phase 2, follow-up) — runs actual customer
    .projectarchive logic at high fidelity, but is licensed (free runtime stops
    after ~2h; needs a runtime license for continuous use). Track separately.

Scope / sub-tasks

  1. Ephemeral runtime provisioning — spin up an OpenPLC container per scan,
    isolated per tenant, with resource caps + guaranteed teardown (timeout).
  2. Artifact → program load — extract ST / PLCopen XML from the control-logic
    artifact and push it to OpenPLC (compile via MatIEC, start the PLC).
  3. Orchestrator wiring — new dynamic phase: for a PlcSps target that has a
    control-logic artifact (and no reachable live URL), provision → probe → DAST
    the provisioned WebVisu → tear down. Reuses run_ics_probe + the DAST path
    against an internally-generated http:// endpoint.
  4. Findings mapping — WebVisu app vulns (XSS/auth-bypass), runtime CVEs,
    default creds, exposed-variable / protocol-auth weaknesses.
  5. Safety & lifecycle — timeouts, teardown guarantees, per-tenant isolation,
    no host exposure.

Non-goals / caveats

  • Virtual I/O only (no physical sensors/actuators) — fine for the security
    surface we care about, but behavioural coverage is partial.
  • OpenPLC cannot execute CODESYS-specific libraries — that fidelity is the
    CODESYS-runtime follow-up.

Related

  • The scheme-aware DAST fix (#182) is the guardrail that makes DAST light up
    cleanly on the provisioned http:// WebVisu and stay blocked on a raw
    modbus:// endpoint.
  • Live-probe / edge-agent reachability mode is complementary and out of scope
    here (would need an on-prem sensor deployment).
## Motivation Dynamic testing of a customer's PLC currently assumes we can reach the running device over the network (a `modbus://` / `http://` live URL). For a real customer that device sits on their OT network behind a firewall — our cloud agent cannot reach it. The live-probe mode therefore only works with an on-prem/edge agent (a separate deployment story) or a co-located lab (our Demo C setup). **Provision-and-test** removes the reachability requirement entirely: we already ingest the control-logic artifact for SAST, so instead of reaching their device we **instantiate their logic ourselves** in-cluster, start it, and run dynamic tests against our own instance. No customer network access, sandboxed, reproducible, and destructive tests become safe. ## Model ``` control-logic artifact (ST / PLCopen XML / .projectarchive) → compile/load into an ephemeral soft-PLC container (in-cluster) → start the runtime (Modbus/TCP + WebVisu HTTP come up) → run ICS probe (Modbus/OPC-UA/EtherNet-IP) + DAST against the WebVisu → collect findings → tear the instance down ``` ## Substrate (decision: OpenPLC first) - **OpenPLC (phase 1)** — runs generic IEC 61131-3 (ST / a PLCopen-XML subset via MatIEC) and accepts a program upload through its web UI. No licensing. Won't run a real CODESYS `.projectarchive` (CODESYS vendor libs + runtime), but proves the deploy→run→probe→DAST loop end-to-end for generic ST. - **CODESYS Control for Linux SL (phase 2, follow-up)** — runs actual customer `.projectarchive` logic at high fidelity, but is licensed (free runtime stops after ~2h; needs a runtime license for continuous use). Track separately. ## Scope / sub-tasks 1. **Ephemeral runtime provisioning** — spin up an OpenPLC container per scan, isolated per tenant, with resource caps + guaranteed teardown (timeout). 2. **Artifact → program load** — extract ST / PLCopen XML from the control-logic artifact and push it to OpenPLC (compile via MatIEC, start the PLC). 3. **Orchestrator wiring** — new dynamic phase: for a PlcSps target that has a control-logic artifact (and no reachable live URL), provision → probe → DAST the provisioned WebVisu → tear down. Reuses `run_ics_probe` + the DAST path against an internally-generated `http://` endpoint. 4. **Findings mapping** — WebVisu app vulns (XSS/auth-bypass), runtime CVEs, default creds, exposed-variable / protocol-auth weaknesses. 5. **Safety & lifecycle** — timeouts, teardown guarantees, per-tenant isolation, no host exposure. ## Non-goals / caveats - Virtual I/O only (no physical sensors/actuators) — fine for the security surface we care about, but behavioural coverage is partial. - OpenPLC cannot execute CODESYS-specific libraries — that fidelity is the CODESYS-runtime follow-up. ## Related - The scheme-aware DAST fix (#182) is the guardrail that makes DAST light up cleanly on the provisioned `http://` WebVisu and stay blocked on a raw `modbus://` endpoint. - Live-probe / edge-agent reachability mode is complementary and out of scope here (would need an on-prem sensor deployment).
Author
Owner

Licensing decision + procurement open questions (from cost review)

Decision — evaluate on the free tier only (for now)

We are not selling this as a SaaS yet, so all dynamic-PLC work stays on free
runtimes until we productize:

  • Phase 1 substrate = OpenPLC (GPLv3, $0) — build and prove the
    deploy → run → ICS + DAST-the-WebVisu loop here. No licensing at all.
  • Any CODESYS-fidelity experiments use the free 2-hour demo runtime,
    which is fully functional; our scans finish in minutes, so the 2h limit is
    never hit during evaluation.
  • No CODESYS license purchase until we're productizing/selling. At that
    point, size a floating pool to peak concurrency and resolve the two questions
    below first.

Cost shape (for when we do productize)

  • Per-runtime license is application-based, from ~$35 (Basic S:
    ≤64 I/O, ≤512 kB app)
    ; step up to Basic M/L only if a customer app exceeds
    the 512 kB size cap. CODESYS LicenseServer for Linux SL is free (€0).
  • Count = peak concurrent runtime instances, not total scans. With
    Virtual Control SL + the free License Server (network mode), buy a
    floating pool of N licenses; each ephemeral container checks one out on start
    and returns it on teardown. Modest bench (2–3 concurrent) ≈ $70–105 to start.

Open questions to resolve before any CODESYS spend (do NOT block Phase 1)

  1. Container network-licensing validation. Soft-container / USB-dongle
    binding does not work in Docker; the only supported container path is
    Virtual Control SL + License Server in network mode. This is recent —
    validate end-to-end that an ephemeral container can check out a license on
    start and return it on teardown, and that a pool floats cleanly across
    short-lived, churny instances.
  2. Demo-mode / evaluation terms with 3S/CODESYS sales. The container
    runtime runs fully-functional for 2h without a license, so demo mode may
    cover the technical need at ~$0 — but it is intended for evaluation, and
    running a commercial SaaS on it likely violates the EULA. Confirm whether our
    short-lived security-testing use qualifies, and ask about a test-lab / OEM
    arrangement.
## Licensing decision + procurement open questions (from cost review) ### Decision — evaluate on the free tier only (for now) We are **not selling this as a SaaS yet**, so all dynamic-PLC work stays on free runtimes until we productize: - **Phase 1 substrate = OpenPLC** (GPLv3, $0) — build and prove the deploy → run → ICS + DAST-the-WebVisu loop here. No licensing at all. - Any **CODESYS-fidelity** experiments use the **free 2-hour demo runtime**, which is fully functional; our scans finish in minutes, so the 2h limit is never hit during evaluation. - **No CODESYS license purchase** until we're productizing/selling. At that point, size a floating pool to peak concurrency and resolve the two questions below first. ### Cost shape (for when we do productize) - Per-runtime license is **application-based**, from **~$35 (Basic S: ≤64 I/O, ≤512 kB app)**; step up to Basic M/L only if a customer app exceeds the 512 kB size cap. **CODESYS LicenseServer for Linux SL is free (€0).** - **Count = peak concurrent runtime instances, not total scans.** With **Virtual Control SL + the free License Server** (network mode), buy a floating pool of N licenses; each ephemeral container checks one out on start and returns it on teardown. Modest bench (2–3 concurrent) ≈ $70–105 to start. ### Open questions to resolve before any CODESYS spend (do NOT block Phase 1) 1. **Container network-licensing validation.** Soft-container / USB-dongle binding does **not** work in Docker; the only supported container path is Virtual Control SL + License Server in network mode. This is recent — validate end-to-end that an *ephemeral* container can check out a license on start and return it on teardown, and that a pool floats cleanly across short-lived, churny instances. 2. **Demo-mode / evaluation terms with 3S/CODESYS sales.** The container runtime runs fully-functional for 2h without a license, so demo mode may cover the technical need at ~$0 — but it is intended for *evaluation*, and running a commercial SaaS on it likely violates the EULA. Confirm whether our short-lived security-testing use qualifies, and ask about a test-lab / OEM arrangement.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sharang/compliance-scanner-agent#183