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
Ephemeral runtime provisioning — spin up an OpenPLC container per scan,
isolated per tenant, with resource caps + guaranteed teardown (timeout).
Artifact → program load — extract ST / PLCopen XML from the control-logic
artifact and push it to OpenPLC (compile via MatIEC, start the PLC).
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.
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).
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)
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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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 realcustomer 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
Substrate (decision: OpenPLC first)
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.
.projectarchivelogic at high fidelity, but is licensed (free runtime stopsafter ~2h; needs a runtime license for continuous use). Track separately.
Scope / sub-tasks
isolated per tenant, with resource caps + guaranteed teardown (timeout).
artifact and push it to OpenPLC (compile via MatIEC, start the PLC).
control-logic artifact (and no reachable live URL), provision → probe → DAST
the provisioned WebVisu → tear down. Reuses
run_ics_probe+ the DAST pathagainst an internally-generated
http://endpoint.default creds, exposed-variable / protocol-auth weaknesses.
no host exposure.
Non-goals / caveats
surface we care about, but behavioural coverage is partial.
CODESYS-runtime follow-up.
Related
cleanly on the provisioned
http://WebVisu and stay blocked on a rawmodbus://endpoint.here (would need an on-prem sensor deployment).
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:
deploy → run → ICS + DAST-the-WebVisu loop here. No licensing at all.
which is fully functional; our scans finish in minutes, so the 2h limit is
never hit during evaluation.
point, size a floating pool to peak concurrency and resolve the two questions
below first.
Cost shape (for when we do productize)
≤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).
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)
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.
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.