Add a draft threat model and wire it for discoverability - #3478
Conversation
### Motivation The Pekko PMC asked the ASF Security team for a draft threat model to refine, as preparation for a Claude security scan. Pekko documents its security posture well in remote-security.md, serialization.md and remoting.md, but that material is spread across the docs and states the trust model implicitly rather than in a form a triager (or a scanning agent) can cite when classifying a finding. Separately, the AGENTS.md -> SECURITY.md chain a scanning agent follows to locate a project's model does not currently resolve: there is no SECURITY.md in the repo. ### Modification - THREAT_MODEL.md: a v0 draft following the Scovetta rubric. Every claim is tagged (documented) with a citation, or (inferred) with a matching open question in §14. 40 documented / 0 maintainer / 14 inferred. - SECURITY.md: reporting policy pointing at security@apache.org, plus a link to the threat model and the two assumptions that catch most reporters. - AGENTS.md: a Security section pointing at both. Nothing the existing docs assert has been dropped or weakened; §15 is a back-map from each existing statement to the section that now carries it. ### Result The discovery chain AGENTS.md -> SECURITY.md -> THREAT_MODEL.md resolves on main, and triagers have a citable document with a closed set of dispositions (§13). §14 holds 13 questions for the PMC, each stated as a proposed answer to confirm or correct. The highest-value ones are Q1 (is the plaintext `transport = tcp` default the supported production posture, given the documented network-isolation assumption?) and Q4 (are untrusted-mode and the deployment allow list security boundaries, or hardening?). The document is not ready to be treated as canonical until those are answered. ### Tests Not run - docs only ### References None - requested by the Pekko PMC chair on the ASF security scan thread
283901d to
4de7f97
Compare
### Motivation Review of the v0 draft found the component-scope tables understate Pekko's network surface, and two cited claims are documented only on the 2.0 line. ### Modification - §2/§4/§5/§6 - `pekko-actor` ships `org.apache.pekko.io.Tcp`/`Udp`/`Dns` and `pekko-stream` ships `Tcp`, `TLS`, `FileIO`, `Framing`, so the "actor core is purely in-process" claim and the "streams leave the process only via connectors the app supplies" row were both wrong. Added the matching input rows so a framing defect routes to a §13 disposition. - §2 - added `protobuf-v3`; listed `plugins`, `bill-of-materials` and `scala-nightly` as out of scope. - §5a - added the classic-remoting knobs, which are deprecated but shipped and CI-gated, and were previously absent. - §5a/§15 - `serialize-messages` is documented as test-only in reference.conf, so Q13 is answered; reused the slot for classic remoting's scope. - §8 P7 and §9 - flagged the cert-rotation and service-mesh citations as 2.0+ and linked the snapshot docs, since neither is in the released 1.x docs. - §1 - added the heading §15 already back-mapped to. - SECURITY.md - `remote-security.html` 404s on `current`; pointed at `remoting-artery.html#remote-security`, which resolves on both lines. - security/index.md - named `security@apache.org` to match SECURITY.md, and linked both new documents so the docs site closes the same chain. ### Result Scope tables match the code, every citation resolves for the version it claims, and §14 still holds 13 questions. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation The previous commit corrected §2/§5 to record that `pekko-actor` ships `org.apache.pekko.io.Tcp`/`Udp` and `pekko-stream` ships `Tcp`, `TLS`, `FileIO` and `Framing`. It also added a §4 sentence declaring parsing and framing defects reachable from an application-bound socket to be in model. That second part is a scope ruling, not a factual correction, and it was neither tagged `(inferred)` nor raised as a §14 question, so it entered the document without maintainer sign-off. It was also too broad: it asserted such bytes are attacker-controlled when the application may bind localhost, it did not distinguish Pekko's transport plumbing from the application's own protocol, and it swept in `stream.TLS`, which delegates to the JDK's JSSE. ### Modification - §4 - removed the exception sentence. - §6 - the application-bound socket rows now describe the inputs without asserting an obligation on Pekko; attacker-controllability is stated as conditional on where the application exposes the socket. ### Result §2, §5 and §6 describe the surface accurately, and §4 makes no scope claim about it either way. Whether defects in Pekko's own transport and framing code are in model is left open for the maintainers. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation An earlier review commit rewrote the upstream-coordination paragraph on the assumption that the draft had dropped a statement from the docs. It had not: `docs/src/main/paradox/security/index.md` on `main` already carries the same generic wording, so the draft was faithful to it and the rewrite was unnecessary. Restoring the sentence alongside the rewrite left the same claim stated twice in consecutive paragraphs. ### Modification Removed the added paragraph, leaving the original sentence in place. `SECURITY.md` now differs from the draft only in the Remote Security link, which pointed at a page that does not exist on the released docs. ### Result No duplicated statement, and the file matches the wording already published on the documentation site. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation The draft left the §5a defaults marked UNRESOLVED and carried no maintainer provenance at all. Pekko's position is that it is a hardening toolkit rather than a secure-by-default one: its deployment base is inherited from Akka, and operators there have already been tasked with securing the network Pekko runs on and controlling who may reach a deployed system. Tightening a default breaks those deployments on upgrade. That position needs stating, because the rest of the model depends on it and because a threat model claiming Pekko is secure by default would not survive contact with `reference.conf`. ### Modification - **§5b** - new section stating the posture: defaults are compatibility choices, not security claims; a request to tighten one is a change request rather than a vulnerability report; such proposals are welcome on the development list and weighed in good faith; and a control that does not do what it documents once enabled is a defect Pekko fixes. - **§13** - new `BY-DESIGN: default-configuration` disposition, which closes a report while pointing at the route to propose the change. - **§14** - Q1, Q3 and Q4 answered and retained in place so cross-references still resolve. Two proposed dispositions are corrected as they did not fit §13's own definitions: Q1 routed an unassociated attacker to `adversary-not-in-scope`, which §13 reserves for an associated peer, a PKI certificate or in-JVM execution, and which §7 contradicts by listing that attacker as in scope; Q4 routed a bypass of an enabled control to `VALID-HARDENING`, which §13 defines as violating no §8 property, though such a bypass violates P5 or P4. - **§5a, §7, §9, §11a** - stance cells filled in and the claims that were inferred pending these questions retagged `(maintainer)`. ### Result Provenance moves from 42/0/14 to 41/12/9, the §5a table has no unresolved cells, and §14 holds ten open questions rather than thirteen. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q2 asked how a deserialization finding that requires `allow-java-serialization = on` should be triaged. The draft proposed `OUT-OF-MODEL: non-default-build` but left unstated what an operator who enables the flag is then responsible for, which matters because Pekko provides nothing to help them: `JavaSerializer.fromBinary` performs an unfiltered `ObjectInputStream.readObject` and there is no `ObjectInputFilter` integration anywhere in the project. ### Modification - **§14 Q2** - answered. Findings requiring the flag are out of model, gadget chains included. Two carve-outs are stated explicitly, per §5b.4: a serious defect in Pekko's own serialization implementation remains in scope and may warrant a CVE, and Java deserialization occurring despite the flag being `off` violates §8 P1 and is valid at Critical. - **§9** - records that Pekko integrates no serialization filter, cites the call site, and names the JVM-level levers an operator has instead. - **§10.3** - the operator responsibility now says to maintain a gadget-chain allow list via `-Djdk.serialFilter` or a process-wide `ObjectInputFilter`. - **§5a** - stance cell updated. ### Result §14 holds nine open questions. Provenance moves to 41 documented / 16 maintainer / 9 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q5 asked whether replay should treat journal and snapshot bytes as untrusted. It should not. Securing the database or persistence store belongs to whoever administers it, and Pekko does not take responsibility for treating persisted values as potentially compromised. ### Modification - **§14 Q5** - answered. A finding whose precondition is write access to the journal or snapshot store is `OUT-OF-MODEL: trusted-input`. The answer is scoped to the store: a defect in Pekko's own replay handling stays in scope per §5b.4. - **§4, §6, §9** - the storage-trust question is replaced by the ruling. - **§13** - journal and snapshot contents named in the `trusted-input` disposition. - **§10** - new item 9, since §5b makes this list the operator contract and it carried nothing about the persistence store. Also corrected a cross-reference: §4's PKI bullet cited §14 Q5, which is the persistence question. PKI material is stated as trusted in §6. ### Result §14 holds eight open questions. Provenance moves to 41 documented / 21 maintainer / 9 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q6 asked two things about the §2 module split: whether `kubernetes/` is supported code, and whether `osgi` should stay in model given its classloading surface. The `osgi` half is settled: it is a barely used feature and the project may eventually remove it rather than carry the maintenance overhead, but while it ships, security reports against it are accepted. ### Modification - **§14 Q6** - marked partly answered. `osgi` stays in model and a finding there is not `OUT-OF-MODEL: unsupported-component`. The `kubernetes/` question and the rest of the split remain open. - **§2** - the `osgi` row and the table footnote record the ruling. - **§12** - the list of conditions that would change the model covered only promotion of a module into the supported surface. Removal is now named too, since `osgi` is a candidate and dropping it would change how findings there are triaged. ### Result §14 holds seven fully open questions and one partly answered. Provenance moves to 41 documented / 23 maintainer / 10 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q6's remaining half asked whether `kubernetes/` is supported code. It is not a module at all: four files that provision a GKE test cluster, with no build definition. The Kubernetes functionality people would report against - discovery, bootstrap, lease - is not in this repository; it ships from Apache Pekko Management. That exposed a larger gap. Nothing in the document said which repository it covers. Outside the header's "core toolkit", a triager had no way to tell where a Pekko Management or Pekko HTTP finding belongs, and §13 offered no routing for one. ### Modification - **§14 Q6** - answered. `kubernetes/` stays out of scope as build tooling, and the Kubernetes implementation is recorded as living in a separate deliverable. - **§3** - new non-goal stating that this document covers `apache/pekko` only. Add-on deliverables are named, with the routing made explicit: out of model *for this document* is not a dismissal, reports go to the same address, and they are triaged on the same terms - an implementation defect is Pekko's to fix, a request to change a default is a §5b change request. - **§2** - the build row says what `kubernetes/` actually contains. ### Result §14 holds seven open questions. Provenance moves to 41 documented / 26 maintainer / 10 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation The previous commit sent a finding in another Apache Pekko repository to `OUT-OF-MODEL: unsupported-component`. That is wrong. §13 defines that disposition as landing in a §3 component - test kits, benchmarks, build tooling - and applying it to code that simply ships from a different repository reads as a dismissal of a report that is in fact accepted normally. Pekko Management issues are reported the same way core issues are. The repository differs; the process does not. ### Modification Reworded the §3 entry so it limits coverage rather than standing: this document enumerates the core toolkit's surfaces and does not enumerate the other deliverables', but reporting, triage, the address and the §5b posture are identical across all of them. States explicitly that such a finding is not `OUT-OF-MODEL: unsupported-component`, so the disposition is not misapplied. §14 Q6 follows the same correction. ### Result No disposition implies a report is out of scope purely because of which Pekko repository it lands in. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q7's §5 negative claims were written as bare assertions with nothing a reviewer could check, and one of the five had already proved wrong. Q8 asked for a categorical line on resource growth driven by a remote peer. ### Modification **Q8 - answered.** Super-linear in message size is a bug and is valid; constant-factor is not. Two caveats recorded: artery already bounds message size by configuration, so the rule's input is bounded on the remoting path; and the rule speaks to size, leaving exhaustion driven by message volume from an associated peer subject to §7. **Q7 - partly answered.** Environment variables are read during configuration startup and never modified. Pekko calls neither `System.getenv` nor `sys.env` anywhere in the main sources; values arrive only through HOCON substitution when `ConfigFactory.load` resolves the configuration, which is the documented way to supply passwords. The remaining §5 claims now carry citations, and two were narrower than written: `CoordinatedShutdown` registers a JVM shutdown hook, and `StandardOutLogger` prints to stdout during early startup, bounded by `pekko.stdout-loglevel`. Verified absent from the main sources: `sun.misc.Signal`, `SignalHandler`, `Runtime.exec`, `ProcessBuilder`, `System.setProperty`, `Locale.setDefault`, `TimeZone.setDefault`. ### Result §14 holds five open questions. Provenance moves to 41 documented / 29 maintainer / 10 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q9 asked whether §7's no-Byzantine-peer conclusion, reached from the remoting documentation, generalises to cluster membership, sharding, singleton and `distributed-data`. It does, and for a stronger reason than the draft gave: Pekko has no guarantee of being able to recognise a compromised node at all. ### Modification - **§14 Q9** - answered. No subsystem claims resilience against a misbehaving member. A finding whose precondition is "a cluster member misbehaves" is `OUT-OF-MODEL: adversary-not-in-scope`, and so is one that assumes Pekko should have detected the compromise. - **§7** - the generalisation is now stated rather than inferred, with the reason: failure detection is heartbeat-based (`PhiAccrualFailureDetector.scala`), so it identifies members that stop responding, not members that respond dishonestly. A compromised node that keeps heartbeating is indistinguishable from a healthy one. - **§9** - the property is widened from "no Byzantine fault tolerance" to include the absence of any compromised-node detection, which is the part a reporter is more likely to assume exists. ### Result §14 holds four open questions. Provenance moves to 41 documented / 32 maintainer / 9 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q7's remaining claims now each carry a code citation, so confirming them is a read rather than an investigation. Q10 and Q11 were policy questions with no code dependency. ### Modification - **Q7 - answered.** No signal handlers, child processes or process-global mutation, verified absent from the main sources. Two claims stand narrower than first written and say so in §5: `CoordinatedShutdown` registers one JVM shutdown hook, and `StandardOutLogger` prints to stdout during early startup bounded by `pekko.stdout-loglevel`. - **Q10 - answered.** Records which of the three security documents is canonical for what, and that the other two link to this one for scope rather than restating it. Carries a maintenance note: the reporting wording is duplicated between `SECURITY.md` and `security/index.md` and has already drifted once, so until one becomes a pointer to the other, both must be changed together. - **Q11 - answered.** The non-goals are confirmed. Two clarifications added to the draft's wording: the side-channel disclaimer is scoped to Pekko's own guarantees, since TLS is delegated to the JDK's JSSE; and "message content is in scope" is scoped to defects in Pekko's handling of that content, not the application's interpretation of it, which §6 assigns to the application. ### Result §14 holds two open questions, Q12 and Q13. Provenance moves to 41 documented / 43 maintainer / 4 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q12 assumed the failure detector and gossip convergence depend on clocks in a way an adversary on a cluster member could exploit. Reading the code, they largely do not, and the one place wall-clock time does cross nodes is already documented on the type. ### Modification **§14 Q12 - answered**, with the findings: - The failure detector reads only the local clock (`FailureDetector.scala:60`, used at `PhiAccrualFailureDetector.scala:144` and `:188`). No remote timestamp reaches it. - `Heartbeat.creationTimeNanos` is the sender's own `System.nanoTime()` (`ClusterHeartbeat.scala:130`), echoed back verbatim by the receiver (`:58`) and subtracted against the sender's own clock (`:251`). No node interprets another node's clock value, and the result feeds only a debug log guarded by `verboseHeartbeat`. - Gossip ordering uses logical `VectorClock` counters (`VectorClock.scala:90-92`), with no wall-clock component. - `LWWRegister` and `LWWMap` do merge by wall-clock timestamp across nodes. The requirement for synchronised clocks, and the alternatives, are stated in the `LWWRegister` scaladoc. §5's clock assumption is rewritten to match: it previously implied a dependency that the failure detector and gossip do not have. ### Result §14 holds one open question, Q13. Provenance moves to 43 documented / 44 maintainer / 3 inferred. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q13 was the last open question. Classic remoting is deprecated but still shipped and still CI-gated, and deprecation is not desupport. ### Modification - **§14 Q13 - answered.** Security reports against classic remoting are accepted on the same terms as artery: configuration is the operator's per §5b, and implementation bugs will be looked at per §5b.4. Its §5a settings follow the same rulings as their artery equivalents. - **§2** - the remoting row names classic remoting alongside artery, rather than describing the family as artery only. - **§14** - retitled, since every question now carries a ruling. The section keeps the questions in place so the reasoning behind each answer stays visible and cross-references continue to resolve. ### Result All thirteen questions are answered. Provenance moves to 43 documented / 48 maintainer / 3 inferred, the remaining three being the residual module in/out split noted in §2 and Q6. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q10 recorded three documents each canonical for something, and noted that the reporting wording was duplicated between `SECURITY.md` and the documentation site's security index, which had already drifted apart once. ### Modification `SECURITY.md` is now the strongest and canonical statement of the reporting policy. Other documents link to it rather than restating it, and link to the threat model for scope. Where another document carries a reporting statement that `SECURITY.md` does not, it is referred to the maintainers to decide whether to promote or drop it, rather than being migrated silently. ### Result The reporting policy has one owner. The documentation-site page keeps announcements and its index of security material. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation Q12 and §5 cited only the `LWWRegister` scaladoc for the synchronised-clock requirement. The published documentation states it more fully, in the section on `LWWMap` and again under `LWWRegister`, along with the custom `Clock` and `reverseClock` alternatives. ### Modification Both citations now name `typed/distributed-data.md` alongside the scaladoc. ### Result The citation points where a reader would look first. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation §5b makes §10 the operator's half of the contract: Pekko states what it does not provide, and states what it expects instead. That only holds if §10 is complete. Auditing it against `reference.conf` and the remoting documentation found four obligations the model relies on but never stated, and two existing items that were narrower than the code. ### Modification Corrected: - **10.4** - the `SECURITY` marker is not only the Java serializer's. The TLS providers use it to report a disabled hostname verification and surviving default keystore passwords, so the item now covers the marker rather than one emitter. - **10.8** - environment substitution was only half the password obligation. Both SSL blocks ship `changeme` as the keystore, key and truststore password (`reference.conf:701`, `:1205`), and Pekko warns under the `SECURITY` marker if those survive into a running system. Added: - **10.10** - protect the key material itself. §6 trusts keystores, truststores and PEM material as operator-supplied; §10.5 scoped what a certificate grants but nothing stated the file-level counterpart. - **10.11** - keep message-content logging off. `log-received-messages`, `log-sent-messages`, `pekko.actor.debug.receive` and `log-config-on-start` all default to `off`; turning any on moves payloads, or the secrets that §10.8 places in the environment, into the logging system. - **10.12** - transport encryption exists only on `tls-tcp`. On `tcp` and `aeron-udp` network isolation is not one control among several, it is the only one. - **10.13** - trust, or secure, the discovery mechanism. §6 marks resolver responses as potentially attacker-influenced; §10 asked nothing of the operator about it. ### Result Every input §6 marks as trusted, and every §9 property Pekko disclaims, now has a matching operator responsibility in §10. ### Tests Not run - docs only ### References Refs apache#3478
|
I have pjfanning#59 - I'm not sure what the merge order is but feel free to comment on either PR> |
### Motivation Q8 was recorded as "super-linear in message size is a bug" and routed to `VALID`, which made a whole class of CPU reports security findings. That was wider than intended, in two ways. First, it conflated "a bug" with "a vulnerability". §5b.4 already provides for defects Pekko fixes without their being security issues, and a performance defect belongs there. Second, the trigger did not match the intent. "Super-linear in message size" fires on an ordinary message that is merely large, whereas the concern is an input crafted so that cost explodes disproportionately to it. ### Modification - **§14 Q8** - CPU cost is not in itself a security concern; a report of extra work or degraded throughput is a performance issue. The exception is disproportionate cost, where work grows super-linearly in the size or structure of a single input. The test is the cost, not the appearance of the input: an input that looks out of the ordinary is the usual sign of such a path rather than a separate condition. Constant-factor overhead is never a finding, and volume from an associated peer stays out of model per §7. - **§6** - the size and rate note said the question was open. Frame-size limits and failure-detector bounds are recorded as tuning parameters, not security controls. - **§9** - the resource-exhaustion entry carries the ruling rather than deferring to it. ### Result Performance reports are triaged as performance, and only disproportionate cost reaches a security disposition. ### Tests Not run - docs only ### References Refs apache#3478
### Motivation The header still read "DRAFT - awaiting Pekko PMC review. Not yet maintainer-ratified." That stopped being true once the PMC chair answered all thirteen open questions: 48 of the document's claims now carry (maintainer) provenance. A triager citing §9 to close a report should not be citing a document that describes itself as unratified. ### Modification - Status: replaced the draft banner with "Reviewed by the Apache Pekko PMC, 2026-08-27", pointing at §14 for the rulings and naming the one item that is still open (the residual module in/out split, §2 and Q6). - Renamed "Draft confidence" to "Provenance mix"; the counts and the explanation beneath it were already current and are unchanged. No claim, ruling, citation or disposition is altered. ### Result The document no longer disclaims its own authority. The single remaining inferred item stays visible in the header rather than being smoothed over. ### Tests Not run - docs only ### References Refs apache#3478
|
Thanks @pjfanning — this is exactly what the draft was for, and considerably more Two of your commits correct me rather than extend me, and both are fair: On merge order — your branch fast-forwarded cleanly from this one, so I've If you'd rather it went the other way round — yours opened against I also pushed one small follow-up commit ( That open item is the last loose end: §2's module in/out split is still the ASF |
…3479) ### Motivation Both remoting transports log when TLS is enabled without hostname verification, but at different levels. Artery logs at `warning`, classic remoting at `info`, where it is easily lost in startup output. Both carry the `LogMarker.Security` marker, which the documentation tells operators to treat as security relevant, so the lower level in classic understates it. ### Modification Log the classic remoting message at `warning`, matching artery. The message text is unchanged, as is the `LogMarker.Security` marker. ### Result Both transports report a disabled hostname verification at the same level. ### Tests No test asserts on this message or its level. ### References None - noticed while reviewing #3478
|
Thanks @potiuk - I'll leave it open for review by others. |
| - **"`PoisonPill` can be sent remotely to shut down a system."** Documented behaviour, gated by `untrusted-mode` *(documented — `remote-security.md`)*. | ||
| - **"`hostname-verification` is disabled by default."** Known and documented, with the trade-off spelled out for dynamic-hostname deployments, and warned at runtime under `LogMarker.Security`. A request to change the default is `BY-DESIGN: default-configuration` per §5b. | ||
| - **Findings in `*-tests`, `*-testkit`, `bench-jmh`, `docs`** — `OUT-OF-MODEL: unsupported-component` per §3. | ||
| - **"SHA1PRNG with `/dev/urandom` reuses the seed."** Documented trade-off, deliberately recommended to avoid blocking *(documented)*. |
There was a problem hiding this comment.
I think this is a very out-of-date recommendation (2014). Should we consider removing that from the doc entirely and from the security model?
There was a problem hiding this comment.
This new doc was generated using AI in the main and it just found stuff in our own Pekko docs.
https://github.com/search?q=repo%3Aapache%2Fpekko+SHA1PRNG&type=code
No problem reviewing this but this threat model entry basically means we won't accept someone telling us to change the docs or default configs as a CVE issue. This line is in the 'Known non-findings' section.
|
|
||
| These are negative claims, rarely written down anywhere. Each is confirmed and carries the citation, or the exception, behind it *(maintainer — §14 Q7)*: | ||
|
|
||
| - Installs no signal handlers and spawns no child processes — no `sun.misc.Signal`/`SignalHandler`, `Runtime.exec` or `ProcessBuilder` in the main sources. It does register **one JVM shutdown hook**, via `CoordinatedShutdown` (`actor/.../actor/CoordinatedShutdown.scala:381`). |
There was a problem hiding this comment.
One JVM shutdown hook is registered by
CoordinatedShutdown, as disclosed in §5; a shutdown hook is not a signal handler.
AI is also pointing me to the one below. Does it need to be mentioned?
|
Should we advertise this PR in the committee mailing list for review? |
|
@samueleresca Can you send an email to the Dev mailing list? There are more people watching the GitHub repo but there might be some people only watching the list. |
Motivation
The Pekko PMC asked the ASF Security team for a draft threat model to refine, as
preparation for a Claude security scan. Pekko already documents its security posture
well —
remote-security.md,serialization.mdandremoting.mdbetween them statemost of the trust model — but that material is spread across three files and states it
implicitly, rather than in a form a triager (or a scanning agent) can cite when
classifying a finding.
Separately, the
AGENTS.md→SECURITY.mdchain that a scanning agent follows tolocate a project's model does not resolve today: there is no
SECURITY.mdin the repo.Modification
THREAT_MODEL.md— a v0 draft. Every claim is tagged(documented)with acitation into Pekko's own docs, or
(inferred)with a matching open question in §14.40 documented / 0 maintainer / 14 inferred.
SECURITY.md— reporting policy (security@apache.org; Pekko does not operate aseparate project security list), a link to the threat model, and the two assumptions
that catch most reporters.
AGENTS.md— a## Securitysection pointing at both.Nothing the existing docs assert has been dropped or weakened. §15 is a back-map
from each existing statement to the section that now carries it, so you can diff the two.
Result
The chain
AGENTS.md→SECURITY.md→THREAT_MODEL.mdresolves onmain, andtriagers get a citable document with a closed set of dispositions (§13).
§14 holds 13 questions, each stated as a proposed answer — confirming or correcting
is enough, no prose needed. The two that most change the document:
pekko.remote.artery.transportshipstcp, so a stock cluster has no peerauthentication. Is that the supported production posture given the documented
network-isolation assumption, so a report of "unauthenticated peer can associate" is
out of model when it assumes internet exposure — but valid if it shows harm reachable
pre-association from an adjacent-network host?
untrusted-modeand the remote deployment allow list securityboundaries, or hardening? The draft says hardening, on the strength of the
documented "untrusted mode does not give full protection against attacks by itself".
One conclusion is worth flagging explicitly because it disposes of a whole class of
scan findings: the draft reads §7 as having no Byzantine-peer model, on the strength
of "you'll have to trust all cluster nodes the same in a Pekko cluster anyway" and
"as soon as an actor system can connect to another remotely, it may in principle send
any possible message to any actor contained within that remote system." If that
generalises from remoting to sharding, singleton and
distributed-data(Q9), then anyfinding whose precondition is "a cluster member misbehaves" is out of model.
This is a draft and should not be treated as canonical until at least Q1 and Q4 are
answered. Happy to fold the answers in and push, or hand it over entirely — the PMC
owns the document.
Tests
Not run - docs only
References
None - requested by the Pekko PMC chair on the ASF security scan thread