Add draft project security threat-model document#2575
Conversation
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>
sruehl
left a comment
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
| *(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. |
| 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. |
| | 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. | |
| 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. |
| **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)* |
| ## §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 | ||
|
|
|
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? |
Summary
This PR adds an initial draft of a project-level security
threat-model document (
draft-THREAT-MODEL.md) so that automatedsecurity 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:
the project website), cited inline.
knowledge; the PMC has not confirmed.
to this draft. (Zero in this initial draft.)
Draft stats:
§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.mdrather thanSECURITY-THREAT-MODEL.mdbecause this is a proposal for thePMC 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.md→SECURITY.md→ the model) added soscanners 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
replaces the inferred claim with the correct one.
dispositions) — those govern how a vulnerability report would
be triaged.
Reply edits / corrections inline on the PR, or to the original
security@apache.orgthread, whichever fits the PMC's workflow.🤖 Generated with Claude Code