samueleresca commented on code in PR #3478:
URL: https://github.com/apache/pekko/pull/3478#discussion_r3876457996
##########
THREAT_MODEL.md:
##########
@@ -0,0 +1,420 @@
+# Apache Pekko — Threat Model
+
+**Status:** Reviewed by the Apache Pekko PMC, 2026-08-27. The thirteen
questions this document was drafted around are answered in §14 and carry
*(maintainer)* provenance; the residual module in/out split noted in §2 and Q6
is the one open item.
+
+| | |
+| --- | --- |
+| **Project** | Apache Pekko (core toolkit) |
+| **Written against** | commit `90b02d60`, `main` |
+| **Date** | 2026-08-27 |
+| **Authors** | ASF Security team, at the request of the Pekko PMC |
+| **Version binding** | This model is versioned alongside the project. A
report against Pekko version *N* is triaged against the model as it stood at
*N*, not at `main`. |
+| **Reporting** | Findings that violate a §8 property should be reported per
[`SECURITY.md`](SECURITY.md). Findings that fall under §3 or §9 will be closed
citing this document. |
+
+**Provenance legend.** Every non-trivial claim is tagged:
+*(documented)* — stated in Pekko's own docs, cited.
+*(maintainer)* — stated by a Pekko maintainer in review of this document.
+*(inferred)* — reasoned from code or config defaults, **not yet confirmed**;
each has a matching question in §14.
+
+**Provenance mix:** 43 documented / 48 maintainer / 3 inferred. The documented
share is unusually high because Pekko's own remoting and serialization docs
already state much of the trust model explicitly. The §5a default rulings —
previously the largest inferred block — are now answered by the §5b posture
statement and §14 Q1 to Q5. What remains inferred is the residual module in/out
split (§14 Q6).
+
+## §1 Overview
+
+Apache Pekko is a Scala/Java toolkit for building concurrent, distributed and
resilient message-driven applications. Its unit of computation is the actor: an
object with private state that communicates only by asynchronous message
passing. Pekko extends that model across machines — an `ActorSystem` can
address actors on remote nodes as if they were local, and a cluster of such
systems provides membership, sharding, singletons and replicated data. That
transparency is the source of most of this document: **the network is not
incidental to Pekko, it is part of the programming model**, and the security
consequences follow from where the toolkit assumes that network sits.
+
+---
+
+## §2 Scope and intended use
+
+Pekko is an **in-process library** that the application embeds and configures.
It is not a server, not a daemon, and ships no runnable artifact that an
operator deploys on its own. There is consequently no "Pekko instance" to
secure independently of the application hosting it.
+
+Three caller roles matter, and they are not equally trusted:
+
+- **The embedding application** — fully trusted. It constructs the
`ActorSystem`, supplies configuration, and already shares the JVM with Pekko.
+- **The operator/deployer** — trusted for the instance. Chooses transport, TLS
material, and the network the node sits on. Most of §10 lands here.
+- **The remote peer** — another `ActorSystem` that has associated over
remoting. Its trust level is the central question of this model, and §7 answers
it.
+
+### Component families
+
+| Family | Modules | Entry point | Leaves the process? | In model |
+| --- | --- | --- | --- | --- |
+| Actor core | `actor`, `actor-typed`, `slf4j`, `coordination` |
`ActorSystem`, `ActorRef` | no | **yes** |
+| Classic IO | `actor` (`org.apache.pekko.io`) | `IO(Tcp)`, `IO(Udp)`,
`IO(Dns)` | **network — if the application binds** | **yes** |
+| Remoting | `remote` | Artery transport (`tcp` / `tls-tcp` / `aeron-udp`);
classic remoting (netty), deprecated but supported *(maintainer — §14 Q13)* |
**network** | **yes — primary surface** |
+| Cluster | `cluster`, `cluster-typed`, `cluster-tools`, `cluster-sharding*`,
`cluster-metrics` | gossip, membership, sharding | **network** (via remoting) |
**yes** |
+| Replicated data | `distributed-data` | CRDT replication | **network** (via
remoting) | **yes** |
+| Serialization | `serialization-jackson`, `serialization-jackson3` |
`Serializer` SPI | deserializes network bytes | **yes — critical** |
+| Wire encoding | `protobuf-v3` | shaded protobuf runtime | parses remoting
and cluster wire bytes | **yes** |
+| Streams | `stream`, `stream-typed` | `Source`/`Flow`/`Sink`; `Tcp`, `TLS`,
`FileIO`, `Framing` | **network / filesystem — if the application uses those
connectors** | **yes** |
+| Persistence | `persistence`, `persistence-typed`, `persistence-query`,
`persistence-shared` | journal / snapshot plugin SPI | **storage backend** |
**yes**, boundary at the SPI |
+| PKI | `pki` | PEM/keystore parsing | **reads files** | **yes** |
+| Discovery | `discovery` | service-discovery SPI | **network / DNS** |
**yes** |
+| OSGi | `osgi` | bundle activator | classloading | **yes** *(maintainer — §14
Q6)* |
+| Test kits | `*-testkit`, `multi-node-testkit`, `*-tests`, `persistence-tck`,
`stream-tests-tck` | — | — | **no** — §3 |
+| Benchmarks | `bench-jmh` | — | — | **no** — §3 |
+| Build / docs | `docs`, `project`, `scripts`, `legal`, `kubernetes`
(test-cluster provisioning scripts), `plugins`, `bill-of-materials`,
`scala-nightly` | — | — | **no** — §3 |
+
+*(inferred — the in/out split is the ASF Security team's proposal, except
`osgi`, which is confirmed in model; see §14 Q6)*
+
+---
+
+## §3 Out of scope (explicit non-goals)
+
+- **Test kits, benchmarks, build tooling and documentation sources.** These
ship in the repository but are not part of the security-supported surface. A
finding in `bench-jmh` or any `*-tests` module is `OUT-OF-MODEL:
unsupported-component`. *(inferred — §14 Q6)*
+- **Pekko is not a sandbox.** Actors are not an isolation boundary. Any code
running in the JVM can reach any actor's state by ordinary means; the actor
model is a concurrency discipline, not a security control. *(maintainer — §14
Q4)*
+- **Pekko is not an authorization framework.** It carries no notion of a
principal, role, or permission on a message. Application-level authorization is
the embedding application's job. *(maintainer — §14 Q11)*
+- **A Pekko cluster is not a multi-tenancy boundary.** The documentation is
explicit that *"you'll have to trust all cluster nodes the same in a Pekko
cluster anyway"* *(documented — `remote-security.md`)*. Separating
mutually-distrusting tenants across nodes of one cluster is not a supported
deployment.
+- **Attackers who already control the embedding process** are out of scope —
they have already won. *(maintainer — §14 Q11)*
+- **This document describes the `apache/pekko` core toolkit.** Its technical
content — the §2 component families, the §5a defaults, the §8 properties — is
about that codebase. Other Apache Pekko deliverables (Pekko Management, Pekko
HTTP, Pekko gRPC, Pekko Connectors, Pekko Projection, the persistence plugins)
ship from their own repositories, and this model does not enumerate their
surfaces.
+
+ That is a limit on **coverage, not on standing**. Reporting and triage are
identical across all Pekko repositories: the same address (see
[`SECURITY.md`](SECURITY.md)), the same PMC, and the same posture — an
implementation defect is Pekko's to fix, while a request to change a default is
a change request under §5b, not a vulnerability. A finding in another Pekko
repository is **not** `OUT-OF-MODEL: unsupported-component`; that disposition
is for the §3 components above, not for code that simply lives elsewhere.
*(maintainer — §14 Q6)*
+
+---
+
+## §4 Trust boundaries and data flow
+
+**The primary trust boundary is the remoting network boundary**, and Pekko's
documentation places it unusually explicitly:
+
+> "An `ActorSystem` should not be exposed via Pekko Cluster or Pekko Remote
over plain Aeron/UDP or TCP to an untrusted network, such as the Internet. It
should be protected by network security, such as a firewall. If that is not
considered enough protection, TLS with mutual authentication should be enabled."
+> — *(documented — `remote-security.md`)*
+
+and states the consequence of crossing it:
+
+> "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."
+> — *(documented — `remote-security.md`, Untrusted Mode)*
+
+Read together, these define the model: **remoting assumes it runs on a network
the operator has already restricted.** Association is the security decision;
once a peer is associated, it is inside. Pekko offers two mechanisms to tighten
that (TLS mutual authentication, untrusted mode) but neither converts remoting
into a boundary that is safe to face the open internet *(documented — see §9)*.
+
+The application's own boundaries — the HTTP endpoint, the message broker, the
database — sit **outside** Pekko and are the embedding application's
responsibility.
+
+### Reachability preconditions per family
+
+A finding must meet its family's precondition to be in-model:
+
+- **Remoting** — reachable from bytes arriving on the Artery transport, *and*
the report must state whether it assumes the network-isolation assumption above
is intact. A finding that requires an attacker already on the cluster network
is judged under §7, not automatically valid.
+- **Serialization** — reachable from a message payload deserialized by a
**configured, enabled** serializer. Findings reachable only when
`allow-java-serialization = on` are judged under §5a.
+- **Cluster / distributed-data** — reachable from gossip or replication
traffic originating at an **associated peer**. Per §7 such a peer is trusted,
so these are typically out of model unless the finding shows a pre-association
reach.
+- **Actor core / streams** — reachable from data the embedding application
passes in. Trusted by default; a finding must show the data crosses an
application boundary that Pekko itself defines.
+- **Persistence** — reachable from journal or snapshot contents. The store is
trusted *(maintainer — §14 Q5)*, so a finding requiring write access to it is
out of model; a defect in Pekko's replay handling is not.
+- **PKI** — reachable from PEM/keystore material. Operator-supplied and
trusted per §6.
+
+---
+
+## §5 Assumptions about the environment
+
+- **Runtime.** A conformant JVM. Pekko does not defend against a hostile JVM,
a hostile classpath, or an attacker with local code execution in the same
process. *(maintainer — §14 Q11)*
+- **Network adjacency.** *"Best practice is that Pekko remoting nodes should
only be accessible from the adjacent network."* *(documented —
`remote-security.md`)*
+- **PKI scope.** Where TLS is used, every certificate issued by the same
internal PKI tree is equivalent: *"there is still a risk that an attacker can
gain access to a valid certificate by compromising any node with certificates
issued by the same internal PKI tree."* *(documented — `remote-security.md`)*
+- **Clock.** Failure detection and gossip do **not** depend on other nodes'
clocks: the failure detector reads only the local clock, and gossip ordering
uses logical `VectorClock` counters. The exception is `LWWRegister`/`LWWMap`,
which merge by wall-clock timestamp and therefore assume reasonably
synchronised clocks across writers *(documented — `typed/distributed-data.md`,
and the `LWWRegister` scaladoc)*. Pekko does not defend against adversarial
clock manipulation on a cluster node *(maintainer — §14 Q12; see Q9)*.
+- **Entropy.** On Linux with SHA1PRNG, the docs recommend
`-Djava.security.egd=file:/dev/urandom` to avoid blocking, noting it *"is NOT
as secure because it reuses the seed."* *(documented — `remote-security.md`)*
+
+### What Pekko does not do to its host
+
+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`).
Review 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?
https://github.com/apache/pekko/blob/6bbd5d041de06ae43bea2a8e9dbc74bb5cad6d1d/remote/src/main/scala/org/apache/pekko/remote/artery/ArteryTransport.scala#L391-L392
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]