Skip to content

Add draft project security threat-model document#2575

Open
potiuk wants to merge 2 commits into
apache:developfrom
potiuk:asf-security/draft-threat-model-2026-05-30
Open

Add draft project security threat-model document#2575
potiuk wants to merge 2 commits into
apache:developfrom
potiuk:asf-security/draft-threat-model-2026-05-30

Conversation

@potiuk
Copy link
Copy Markdown
Member

@potiuk potiuk commented May 30, 2026

Summary

This PR adds an initial draft of a project-level security
threat-model document (draft-THREAT-MODEL.md) so that automated
security scanners running against this repository have a
maintainer-facing reference for which classes of findings are
in-scope vs. out-of-scope for the project.

The document follows the rubric format used by several other ASF
projects piloting improved security-model discoverability for
agentic scanners. Every claim carries a provenance tag:

  • (documented) — paraphrased from public artefacts (this repo or
    the project website), cited inline.
  • (inferred) — synthesised from code structure or domain
    knowledge; the PMC has not confirmed.
  • (maintainer) — confirmed by a PLC4X PMC member in response
    to this draft. (Zero in this initial draft.)

Draft stats:

  • ~50 documented claims
  • ~45 inferred claims (each maps to a §14 question)
  • 31 open questions for maintainers in §14

§14 is the highest-leverage section: answering each question
either promotes one (inferred) tag to (maintainer) or corrects
the underlying claim.

Why "draft-" prefix?

The file is named draft-THREAT-MODEL.md rather than
SECURITY-THREAT-MODEL.md because this is a proposal for the
PMC to review — please correct, reject, or discuss as needed.

Once the PMC ratifies (or substantially edits) the content, the
file can be renamed in a follow-up PR and a discoverability
scaffold (AGENTS.mdSECURITY.md → the model) added so
scanners can mechanically follow the chain.

What this is, and what it is not

This is not a security audit. It is a working triage document
— the reference a triager holds against an inbound report to
decide whether the report is about a PLC4X vulnerability or
about caller misuse / operator misconfiguration / an out-of-scope
concern.

The draft was generated by an automated agentic security scan
being piloted by the ASF Security team; the discoverability work
is independent of any specific scan run.

How to review

  1. §14 first. Each answer either confirms one (inferred) tag or
    replaces the inferred claim with the correct one.
  2. After that, please skim §3 (out-of-scope) and §13 (triage
    dispositions) — those govern how a vulnerability report would
    be triaged.

Reply edits / corrections inline on the PR, or to the original
security@apache.org thread, whichever fits the PMC's workflow.

🤖 Generated with Claude Code

Adds a draft project-level security threat-model document
(draft-THREAT-MODEL.md) at repo root, improving discoverability
for automated security scanners running against this repository.
The file follows the rubric format used by several other ASF
projects piloting security-model discoverability.

The "draft-" prefix signals this is a proposal for the PMC to
review, correct, or reject — not a finalised maintainer-blessed
model. Every claim carries a provenance tag (documented /
inferred / maintainer) so reviewers can see where each claim
originates; §14 collects open questions for the maintainers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@sruehl sruehl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, also it emphasizes PlcAuthentication quite often whereas at this point I don't even know what it is used by. OT Stuff is usually open like a barn door

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 1 out of 1 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread draft-THREAT-MODEL.md
Comment on lines +35 to +59
*(maintainer: Chris Dutz, 2026-05-29 16:06Z)* and will be modelled
separately if and when it is brought into the program.
- **Version / commit**: drafted against the default branch (`develop`),
HEAD `32b4f0c` ("build(deps): bump jackson.version from 2.21.3 to 2.21.4"
as of draft time). A vulnerability report against PLC4X release *N* is
triaged against the model as it stood at *N*, not at HEAD.
- **Date**: 2026-05-30.
- **Authors**: ASF Security team draft, awaiting PLC4X PMC review.
- **Status**: draft — under maintainer review.
- **Reporting cross-reference**: vulnerabilities that may violate a §8
property should be reported to the Apache Security Team
(`security@apache.org`) per
`website/asciidoc/modules/users/pages/security.adoc`; reports that fall
under §3, §9, or §11a will be closed by PLC4X triagers citing this
document.
- **Provenance legend** —
*(documented)* = drawn from in-repo docs, the website asciidoc tree, or
on-the-wire protocol specifications, with citation;
*(maintainer)* = stated by a PLC4X maintainer (PMC chair Chris Dutz or
another committer) in response to this draft;
*(inferred)* = synthesized by the producer from code structure, the
protocol's published specification, or general OT-protocol domain
knowledge, awaiting PMC ratification — every *(inferred)* tag has a
matching §14 question.
- **Draft confidence**: 50 documented / 3 maintainer / 45 inferred.
Comment thread draft-THREAT-MODEL.md
Comment on lines +32 to +36
The separately-released `plc4x-extras` repository (OPC-UA Server, PLC4X
Server, Calcite / Camel / Kafka-Connect / Karaf / NiFi integrations,
Connection-Cache, OPM, Scraper) is **out of scope** of this document
*(maintainer: Chris Dutz, 2026-05-29 16:06Z)* and will be modelled
separately if and when it is brought into the program.
Comment thread draft-THREAT-MODEL.md
| OPC UA `security-policy` | `NONE` *(documented: `plc4j/drivers/opcua/.../config/OpcuaConfiguration.java`)* | **maintainer ruling required** — is "no encryption" a supported production posture, or dev-default? *(inferred — §14 Q14)* | If `NONE`, the OPC UA channel runs unencrypted and unauthenticated; B2-OPCUA collapses to B2 (cleartext). |
| OPC UA `message-security` | `SIGN_ENCRYPT` *(documented)* | hardened default | When the security policy is not `NONE`, this forces sign-and-encrypt; flipping to `SIGN` (signed-cleartext) or `NONE` weakens the channel. |
| OPC UA `trust-store-file` | **unset** *(documented: `website/.../protocols/opcua.adoc` — "Unless explicitly disabled through configuration of `trust-store-file` all server certificates will be accepted without validation"; `plc4j/drivers/opcua/.../security/PermissiveCertificateVerifier.java`)* | **The OPC UA driver defaults to `PermissiveCertificateVerifier` — server certificates are accepted without validation**. This is **the single highest-priority maintainer ruling** in the document. *(inferred — §14 Q15)* | Without a trust store, an MITM attacker on the OT network can present any certificate and the driver will trust it. Even with the security policy at `Basic256Sha256` and `SIGN_ENCRYPT`, the encryption peer is unauthenticated. |
| OPC UA `key-store-file` / `key-store-password` | unset *(documented)* | operator must supply for mutual-TLS-like client auth | If unset and a security policy ≠ `NONE` is configured, the driver auto-generates a self-signed client certificate *(documented: `website/.../protocols/opcua.adoc`)*. Auto-generated certs are not recoverable across restarts; they cannot satisfy a peer that requires a known client identity. |
Comment thread draft-THREAT-MODEL.md
Comment on lines +245 to +247
10. **Supply-chain / build / release hygiene** — Maven action pinning,
Maven Central signing, Jenkins build configuration, dependency
freshness, reproducible builds. Out of model per the SKILL.
Comment thread draft-THREAT-MODEL.md
Comment on lines +1119 to +1124
**Q28.** Is there an existing threat-model document (Confluence wiki,
internal note) that this should reconcile against rather than
supersede? The website `security.adoc` page is process-only (where
to report); the `developers/maturity.adoc` page references the
security process but has no threat-model content. *(meta — §3.1a
of the rubric)*
Comment thread draft-THREAT-MODEL.md
Comment on lines +948 to +954
## §14 Open questions for the maintainers

Every *(inferred)* tag in the body maps to one of these. Proposed
answers are inline; please confirm, correct, or strike.

### Wave 1 — scope, intended use, the OPC UA defaults

@potiuk
Copy link
Copy Markdown
Member Author

potiuk commented Jun 3, 2026

Thanks @sruehl. Fair point — you're right that in practice a lot of OT/PLC deployments run unauthenticated, and the draft over-weights PlcAuthentication. It's the driver-layer credential abstraction for the few protocols that do carry auth (e.g. OPC UA user/password, TLS client certs), but if it's rarely used in the field I'm happy to demote it from a primary boundary to a "where present" note and lead instead with the unauthenticated-by-default reality as the modeled baseline. I'll push that revision — does that match how you'd frame it?

Copy link
Copy Markdown
Contributor

@chrisdutz chrisdutz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks good to me.

Comment thread draft-THREAT-MODEL.md
profiles. Anything marked **out** below reappears in §3 with the
reason.

| Family | Representative entry point | Touches outside the process? | In this model? |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table will change with the merging of the SPI3 rewrite branch, however it's more or less what was initially one "spi" module will become a set of different sub-modules each with it's own set of functionality. But in general: the architecture of Java drivers will greatly change with the removal of Netty as a base.

Comment thread draft-THREAT-MODEL.md
Comment on lines +235 to +244
9. **TLS / VPN / IPSec tunnels that the integrator may layer underneath.**
Most cleartext OT protocols are operated in production behind some
form of point-to-point tunnel (a VPN concentrator at the OT/IT
boundary, an IPSec link to a remote pumping station, a TLS-tunneling
proxy in front of a Modbus device). PLC4X has **no built-in TLS or
tunneling layer** for the cleartext protocols *(inferred from
transport inventory — §14 Q8)*. Reports of the shape "Modbus-TCP
should run over TLS" describe an integrator deployment choice; the
driver does not block such a deployment but does not provide it
either. → `BY-DESIGN: property-disclaimed`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the new SPI3 we will have the ability to use a "tls" or "tls-psk" transport instead of "tcp" which will add a tls protection layer to the driver (if it's supported by the target PLC or Gateway)

Comment thread draft-THREAT-MODEL.md
Comment on lines +398 to +402
The OPC UA driver's **defaults are dev/lab-grade, not production-grade**:
`security-policy=NONE`, `trust-store-file` unset, `discovery=true` over an
unencrypted channel. Each of these defaults voids a §8 property the
driver could otherwise provide. The §14 Q14, Q15, Q16 questions ask
the maintainer to choose, per knob, between:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the SPI3 branch I think I have changed that the insecure path needs to be enabled explicitly and the secure path is now the new default. If this hasn't happened, this is worth reporting as we must follow "secure per default" approach as much as possible with respect to new CRA requirements.

Comment thread draft-THREAT-MODEL.md
| OPC UA server certificate (presented during handshake) | full DER bytes | **yes** | when `trust-store-file` is set: X.509 chain validation per JCE rules; when not set (default): **none** *(documented: §5a)* |
| Serial-line frames | every byte | yes if the serial channel is attacker-reachable | memory safety on malformed framing *(inferred — §14 Q11)* |
| libpcap capture / replay frames | every byte | yes if the capture file is attacker-controlled | the pcap-replay transport is a **dev/test tool**; if it's running in production, the integrator has put it there |
| ETS `.knxproj` XML | as XML | yes if the file is attacker-supplied | XXE disabled *(documented)*; ZIP slip protection — *(inferred — §14 Q18)* |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the SPI3 branch the ets parser related issues have been addressed and xml parsing has been hardened.

Comment thread draft-THREAT-MODEL.md
Comment on lines +446 to +451
- PLC4X drivers **stream individual request/response frames**; there is
no documented per-call cap on response size beyond what the protocol
itself bounds (Modbus PDUs are spec-bounded, S7 PDU size is
negotiated, OPC UA chunk size is negotiated) *(documented: per
protocol page; `S7Configuration.pduSize`,
`OpcuaConfiguration.limits.encoding.{send,receive}-buffer-size`)*.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the new SPI3 in contrast to the current one, per connection a ring-buffer is allocated with a fixed length which differs from protocol to protocol. This prevents many issues related to huge fake messages making the system allocate huge buffers.

Comment thread draft-THREAT-MODEL.md
wrap a cleartext protocol in TLS, VPN, IPSec, or Wireguard. If the
integrator wants encrypted-on-the-wire Modbus, they must run Modbus
inside an integrator-provided tunnel *(inferred — §14 Q8)*.
- **No replay-protection on cleartext protocols.** A request the driver
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some protocols have these nonces, if the protocol uses them, PLC4X provides them but doesn't add any beyond the protocol specified ones.

Comment thread draft-THREAT-MODEL.md
Comment on lines +620 to +621
- **No authorization over which tags an embedding application reads or
writes.** The embedding application owns that decision. See §3 items 3, 4.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a protocol supports this, PLC4X will defer such access permissions check to the target PLC and report any permission-related errors back to the client, however it doesn't provide such a permission system itself, it's more just a proxy to an existing one on the target PLC.

Comment thread draft-THREAT-MODEL.md
Comment on lines +629 to +630
- **No data-at-rest encryption.** PLC4X does not persist anything to
disk on its own at runtime.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new SPI3 will have an Audit-Log feature for logging information important for providing support for issues. In this case we will be writing data to a file-system. However this is just intended for debugging and not for running permanently. So we have not implemented any security or encryption features.

Comment thread draft-THREAT-MODEL.md
reader who knows OPC UA has "Secure: encryption, authentication, and
auditing" in its spec slogan
*(`website/.../protocols/opcua.adoc` line 264)* would assume the
PLC4X OPC UA driver provides those properties by default. **It does
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be secure per default with the option to disable.

Comment thread draft-THREAT-MODEL.md
Comment on lines +854 to +858
- **"OPC UA driver accepts any server certificate."** True by default
(`PermissiveCertificateVerifier`); the §10 item 3 contract requires
the operator to set `trust-store-file`. **Pending §14 Q15
maintainer ruling**; if the maintainer chooses stance (b) — default is
dev-only — this is `OUT-OF-MODEL: non-default-build`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed and reported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants