This is an automated email from the ASF dual-hosted git repository.

rubenada pushed a commit to branch site
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit d8aced3bfb4b90cdf529e4ebc7c6a74c270a0266
Author: Vladimir Sitnikov <[email protected]>
AuthorDate: Tue Jul 21 18:22:04 2026 +0300

    [CALCITE-7605] Threat model: add Inputs, Downstream responsibilities, 
Triage dispositions
    
    Fold in the three additive sections proposed in vlsi/calcite#3, corrected
    against the code:
    
    - Inputs: map every attacker-controlled input to its governing rule. Add the
      metaTableFactory/metaColumnFactory PLUGIN properties, place operator 
under the
      RelJson row (SqlOperator loads only via RelJson), and note that fun 
selects
      built-in libraries rather than loading a class.
    - Downstream responsibilities: collect the host/operator duties in one 
place and
      drop the now-duplicated transport paragraph from the attacker section.
    - Triage dispositions: a closed outcome set a human or agent can route 
against.
    - Not a vulnerability: state that pushed-down SQL is by design, while a 
pushdown
      bug that reads beyond the configured schemas is P4.
    
    Also remove the draft-status line ahead of merge.
    
    Co-authored-by: Jarek Potiuk <[email protected]>
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 site/_docs/security_threat_model.md | 79 +++++++++++++++++++++++++++++++++----
 1 file changed, 72 insertions(+), 7 deletions(-)

diff --git a/site/_docs/security_threat_model.md 
b/site/_docs/security_threat_model.md
index 5f5deb7b9a..d9936197d4 100644
--- a/site/_docs/security_threat_model.md
+++ b/site/_docs/security_threat_model.md
@@ -31,8 +31,6 @@
 contradicts this model is a feature request or a documentation gap, not a
 vulnerability.
 
-**Status:** draft for PMC discussion; not yet ratified.
-
 * TOC
 {:toc}
 
@@ -58,11 +56,6 @@ ## Attacker and trust boundary
 points at. If a model references h2, h2's own settings and behavior are
 h2's concern, not Calcite's.
 
-Because Calcite listens on no socket of its own, network transport, TLS, and
-authentication belong to the host application, not to this model. A host that
-lets an untrusted principal set connection properties has handed that principal
-the attacker's full capability above.
-
 ## Assets
 
 * the host running Calcite: no code execution, and no file access beyond
@@ -70,6 +63,23 @@ ## Assets
 * the internal network reachable from that host: no attacker-directed
   outbound requests.
 
+## Inputs
+
+Everything the attacker controls resolves to one of P1–P4 or to an explicit
+carve-out below. A report that reaches a sink not covered here is a model gap
+(see [Triage dispositions](#triage-dispositions)).
+
+| Input | How it is supplied | What it feeds | Governing rule |
+| --- | --- | --- | --- |
+| SQL text, including DDL | any statement on the connection | parser → 
validator → planner → generated code | P1–P4; parser nesting depth is a DoS 
surface (see [Denial of service](#denial-of-service)) |
+| Class-naming connection properties — `schemaFactory`, `parserFactory`, 
`typeSystem`, `metaTableFactory`, `metaColumnFactory` | connection property or 
`model` | a class loaded through a Calcite SPI | [Surprising vs unsurprising 
class loading](#surprising-vs-unsurprising-class-loading) (P1) |
+| `tableFactory` and function classes | `model` | a class loaded through a 
Calcite table or function SPI | Surprising vs unsurprising class loading (P1) |
+| `dataSource`, `jdbcDriver` | connection property or `model` | a class loaded 
through a standard-Java SPI (`javax.sql.DataSource`, `java.sql.Driver`) | 
Surprising vs unsurprising class loading (P1); the host it then dials is P3 |
+| `fun` | connection property | selects built-in function libraries by name | 
no class loading; ordinary SQL semantics under P1–P4 |
+| `model` — inline JSON, a `file:` path, or a URL | connection property | 
schema/table factories and adapter operands | P1 (factories via SPI), P2 
(local-file operands), P3 (a URL model, or a URL-fetching adapter) |
+| A serialized RelNode plan (`RelJson`) — types and operators | any path that 
reconstructs a plan from attacker input | type and operator class resolution | 
Surprising vs unsurprising class loading (P1) |
+| Adapter operands — e.g. a file/CSV/JSON path, or the os-adapter | `model` or 
SQL | the adapter's configured resource | P2 for a configured local path 
(opt-in ⇒ not a vulnerability); the os-adapter is opt-in (not a vulnerability) |
+
 ## Security properties
 
 * **P1: no code execution.** Neither connecting nor running SQL may
@@ -114,12 +124,39 @@ ## Not a vulnerability
   outside the attacker's reach by assumption.
 * The behavior of a third-party driver once Calcite has connected to the
   endpoint it was configured with.
+* SQL that Calcite pushes down to a configured backend. Calcite generates the
+  text and sends it to the endpoint the operator configured, and the query
+  author can already reach that endpoint's data through the visible schemas. A
+  pushdown bug that reads beyond the configured schemas is P4 and a
+  vulnerability; the generated SQL reaching the configured backend is not.
 * Cross-tenant reads that follow from the embedder exposing more than one
   principal's schemas on a single connection. Calcite has no authentication or
   authorization; scoping each connection's root schema to what its principal 
may
   see is the embedder's job. P4 applies where the user submits only SQL; a user
   who also sets connection properties configures their own schema visibility.
 
+## Downstream responsibilities
+
+Calcite is embedded, so several controls belong to the host or the operator,
+not to the library. A finding that lands in one of these is not a Calcite
+vulnerability.
+
+* **Transport and identity.** Calcite opens no socket. TLS, the network
+  perimeter, authentication, and authorization live in the host. A host that
+  lets an untrusted principal set connection properties hands that principal 
the
+  full capability in [Attacker and trust 
boundary](#attacker-and-trust-boundary).
+* **Schema scoping.** Scope each connection's root schema to what its principal
+  may see; Calcite has no authentication or authorization. Cross-tenant reads
+  across schemas exposed on one connection are the embedder's to prevent (see
+  [Not a vulnerability](#not-a-vulnerability)).
+* **Adapter selection.** Add the os-adapter and the file, CSV, or JSON adapters
+  only where the query author is trusted to reach what they expose.
+* **Classpath.** The operator owns the classpath. Calcite gates class loading 
by
+  SPI; which classes are present is the operator's trust decision.
+* **What a `model` points at.** A third-party driver or service a `model`
+  references is configured and patched by the operator; its behavior past the
+  connection boundary is out of this model.
+
 ## Surprising vs unsurprising class loading
 
 Calcite loads a class named in a connection property or in SQL only to use it
@@ -200,3 +237,31 @@ ## Denial of service
 
 Once the planning bounds exist, a single reasonably-sized query that exceeds
 them is a configuration choice, not a vulnerability.
+
+## Triage dispositions
+
+Every security report against Calcite resolves to exactly one of:
+
+* **Valid** — violates P1–P4, or matches an item in
+  [Always a vulnerability](#always-a-vulnerability). Gets a fix. A demonstrated
+  class-loading primitive qualifies on its own (see
+  [Triage rule for class-loading sinks](#triage-rule-for-class-loading-sinks));
+  it need not be chained to end-to-end RCE.
+* **Not a vulnerability (by design)** — matches an item in
+  [Not a vulnerability](#not-a-vulnerability): the os-adapter, an opt-in
+  file/CSV/JSON adapter reading its configured path, third-party driver or
+  pushed-down SQL behavior past the connection, or cross-tenant reads that
+  follow from the embedder's schema exposure. Close with a pointer to this
+  model.
+* **Out of model** — requires a capability the attacker does not have (changing
+  a JVM system property or the classpath), or lands in a layer this model
+  assigns to the host (network transport, TLS, authentication, authorization).
+  Close; redirect to the operator or embedder.
+* **Known limitation** — a [Denial of service](#denial-of-service) gap whose
+  control has not landed yet. Tracked as hardening, not a per-report
+  vulnerability, until the bound exists.
+* **Duplicate** — the same sink or root cause is already tracked in an open
+  Jira. Link and close.
+* **Model gap** — plausible, but this model does not clearly place it in or 
out.
+  Escalate to the PMC to decide, then update this document with the ruling so
+  the next report of its kind is no longer a gap.

Reply via email to