afs commented on code in PR #3966:
URL: https://github.com/apache/jena/pull/3966#discussion_r3367446793


##########
THREAT_MODEL.md:
##########
@@ -0,0 +1,205 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Apache Jena — Threat Model (v0 draft)
+
+## §1 Header
+
+- **Project:** Apache Jena (`apache/jena`), `main`, against which this draft 
was written. A monorepo: the RDF/SPARQL Java framework (`jena-core`, 
`jena-arq`, `jena-base`, RIOT parsers, `jena-tdb1`/`jena-tdb2` stores, 
SHACL/ShEx, GeoSPARQL, text index) **and** the Fuseki HTTP server 
(`jena-fuseki2`).
+- **Date:** 2026-06-02. **Status:** draft — for Apache Jena PMC review. 
**Author:** ASF Security team (drafted via the Scovetta threat-model rubric), 
for PMC ratification.
+- **Version binding:** versioned with the project; a report against version 
*N* is triaged against the model as it stood at *N*.
+- **Reporting cross-reference:** §8-property violations → report privately per 
ASF process (`[email protected]` → `[email protected]`); §3/§9 findings 
are closed citing this document.
+- **Provenance legend:** *(documented)* = Jena's own docs/repo; *(maintainer)* 
= confirmed by a Jena PMC member through this process (andy@ has ratified 
destination + the help-with-model request); *(inferred)* = reasoned from 
architecture, not yet confirmed — each has a matching §14 open question.
+- **Draft confidence:** ~12 documented / ~2 maintainer / ~34 inferred.
+- **What Jena is:** Apache Jena is a Java framework for building Semantic-Web 
/ linked-data applications over RDF. It provides an in-process API to RDF data 
held in memory or in a native store (TDB), the ARQ SPARQL query/update engine, 
RIOT parsers/serialisers for RDF syntaxes (Turtle, RDF/XML, JSON-LD, N-Triples, 
…), and **Fuseki** — a standalone HTTP server exposing SPARQL query, SPARQL 
Update, and the Graph Store Protocol over the network. *(documented — README, 
jena.apache.org; maintainer — andy@ 2026-06-01: "an HTTP-based data server 
(Fuseki) and a Java API to RDF data stored in memory and in a custom database")*
+
+## §2 Scope and intended use
+
+- **Two deployment shapes** *(maintainer — andy@)*:
+  - **Fuseki** — a long-running **HTTP server** that answers SPARQL over the 
network. The primary network trust surface.
+  - **The Jena Java API** — `jena-core`/`jena-arq`/TDB embedded **in-process** 
in another application. Trusted caller; the bytes/queries it feeds Jena are 
that application's responsibility.
+- **Caller roles** (Fuseki is a network service — the role splits):
+  - **anonymous SPARQL client** — issues SPARQL queries over HTTP. 
**Default-public for query** *(documented — Fuseki security docs: "SPARQL 
endpoints are open to the public but administrative functions are limited to 
localhost")*.
+  - **authenticated user / admin** — gated by Apache Shiro (`shiro.ini`); 
admin functions (`/$/*`) restricted to localhost by default *(documented)*.
+  - **operator/deployer** — configures Shiro, datasets, TDB location, and 
which endpoints are read-only vs updatable. **Trusted.** *(inferred)*
+  - **embedding application** (Java API) — trusted; supplies queries/RDF to 
the library. *(inferred)*
+
+**Component-family table** *(monorepo; in/out of model):*
+
+| Family | Entry point | Touches OS/network | In model? |
+| --- | --- | --- | --- |
+| Fuseki HTTP server | `jena-fuseki2` — SPARQL query / Update / Graph Store 
Protocol, admin `/$/*` | network (listens) | **In — primary boundary** 
*(documented)* |
+| SPARQL engine (ARQ) | `jena-arq` — query/update eval, `SERVICE` federation, 
custom functions | network out (SERVICE), file (file: URLs) | **In — high 
value** *(inferred)* |
+| RDF I/O (RIOT) | `jena-arq`/`jena-core` parsers (RDF/XML, Turtle, JSON-LD, 
…) | parses untrusted RDF | **In — XXE / parser-DoS surface** *(inferred)* |
+| Stores | `jena-tdb1`, `jena-tdb2`, `jena-db` | filesystem | **In (engine's 
use); on-disk store is operator-trusted** *(inferred)* |
+| IRI / langtag | `jena-iri3986`, `jena-langtag`, `jena-base` | none | **In 
(input parsing)** *(inferred)* |
+| Validation / extensions | `jena-shacl`, `jena-shex`, `jena-geosparql`, 
`jena-text`, `jena-serviceenhancer` | text index; SERVICE | **In (reachable 
from queries)** *(inferred)* |
+| Client/API helpers | `jena-rdfconnection`, `jena-querybuilder`, 
`jena-rdfpatch`, `jena-commonsrdf`, `jena-ontapi` | none | **In as libraries 
(memory/correctness)** *(inferred)* |
+| CLI tools | `jena-cmds` | filesystem | **In iff fed untrusted input; usually 
operator-run** *(inferred)* |
+| Examples / tests / benchmarks | `jena-examples`, `jena-integration-tests`, 
`jena-benchmarks` | n/a | **Out** *(see §3)* |
+
+## §3 Out of scope (explicit non-goals)
+
+- **`jena-examples`, `jena-integration-tests`, `jena-benchmarks`** — 
illustrative/test, not production. *(inferred)*
+- **Attackers who control the host, the Fuseki config (`shiro.ini`, dataset 
config), the TDB data directory, or the embedding Java application.** 
Operator-trusted. *(inferred)*
+- **The embedding application's own use of the Java API** — if an app feeds 
attacker-controlled SPARQL it built by string-concatenation to ARQ, that 
injection is the app's bug, not Jena's (analogous to SQL injection in a JDBC 
caller). *(inferred)*
+- **Generic DoS / query-complexity exhaustion** beyond a to-be-confirmed line 
— Andy raised resource-volume as a concern; the §8 resource line + §14 frame 
it. *(inferred)*
+- **Confidentiality of RDF data at rest / TLS on the wire** — operator 
deployment (reverse proxy for TLS; filesystem perms for TDB). *(inferred)*
+
+## §4 Trust boundaries and data flow
+
+- **Primary boundary: the Fuseki SPARQL endpoint.** Queries arrive over HTTP 
from (by default) **anonymous** clients. The boundary question is what an 
anonymous/low-privilege SPARQL query can reach: read data it shouldn't, 
**write** (SPARQL Update / GSP) without authorisation, make Fuseki issue 
outbound requests (`SERVICE` → SSRF), read local files (`file:` URLs / FROM), 
execute code (ARQ custom/JavaScript functions if enabled), or exhaust 
resources. *(inferred; public-query default documented)*
+- **Admin boundary:** the `/$/*` admin surface is localhost-only by default 
*(documented)*; exposing it to the network is an operator misconfiguration.
+- **RDF-parse boundary:** any endpoint that **parses** caller-supplied RDF 
(Update bodies, GSP PUT/POST, content negotiation) runs RIOT on untrusted bytes 
— the XXE (RDF/XML) and parser-DoS surface. *(inferred)*
+- **Reachability preconditions:**
+  - A finding in ARQ/RIOT/stores is **in-model** iff reachable from a Fuseki 
request at the relevant role (default: anonymous query; authenticated for 
Update). *(inferred)*
+  - A finding reachable only through the **in-process Java API** with 
caller-supplied trusted input is `OUT-OF-MODEL: trusted-input` (the embedding 
app owns it). *(inferred)*
+  - A finding requiring operator config (`shiro.ini`, exposing admin, enabling 
JS functions) is `OUT-OF-MODEL: trusted-input` / `non-default-build`. 
*(inferred)*
+
+## §5 Assumptions about the environment
+
+- **Runtime:** JVM (Java; "old in places" per andy@). *(maintainer)*
+- **Fuseki auth:** Apache Shiro via `$FUSEKI_BASE/shiro.ini`; changing it 
needs a restart *(documented — Fuseki security docs)*.
+- **Store:** TDB1/TDB2 on the local filesystem, assumed private to the 
Fuseki/JVM process. *(inferred)*
+- **Network:** TLS is the deployer's (reverse proxy); Fuseki's bundled example 
setup is plaintext *(documented — "no TLS, passwords in plain text")*.
+- **Negative side-effects inventory** (inferred — wave-1/2 target): Fuseki 
listens on HTTP; ARQ can make **outbound** network requests via `SERVICE` 
(federation) and can read **`file:`/http: URLs** named in queries (FROM/FROM 
NAMED/SERVICE); RIOT parses untrusted RDF; ARQ may execute **custom/JavaScript 
functions** if the operator enabled them; TDB reads/writes the data directory. 
*(inferred — these are the load-bearing confirmations)*
+
+## §5a Build-time and configuration variants
+
+Security-relevant configuration *(Fuseki auth documented; the rest inferred — 
confirm defaults):*
+
+| Knob | Default | Effect / stance |
+| --- | --- | --- |
+| Fuseki Shiro auth (`shiro.ini`) | SPARQL **query** public; admin `/$/*` 
**localhost-only** | *(documented)* Restricting query access requires Shiro 
`[urls]` ACLs. |
+| Fuseki example user setup | `admin`/`pw`, plaintext, no TLS | *(documented)* 
explicitly "not recommended for production". Any "default admin/pw in prod" 
report → `OUT-OF-MODEL: non-default-build`. |
+| SPARQL **Update** / Graph Store write | per-dataset (read-only vs read-write 
service) — **default to confirm** | *(inferred)* If a dataset ships 
update-enabled + unauthenticated, anonymous write is in-model; if read-only by 
default, anonymous write is not reachable. **Wave-1 question.** |

Review Comment:
   The default is not enabled for persistent storage or data from a file; 
enabled on an empty in-memory store.



-- 
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]

Reply via email to