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

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 1a8c9cab62 Add threat model + security-model discoverability 
(AGENTS.md → SECURITY.md → THREAT_MODEL.md) (#7214)
1a8c9cab62 is described below

commit 1a8c9cab62bd657d6593c3c10940381edf84f4d2
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Jun 23 04:51:58 2026 -0400

    Add threat model + security-model discoverability (AGENTS.md → SECURITY.md 
→ THREAT_MODEL.md) (#7214)
    
    * Add threat model + security-model discoverability (AGENTS.md → 
SECURITY.md → THREAT_MODEL.md)
    
    Generated-by: Claude Code
    
    * Add ASF license header to generated files to satisfy Apache RAT
    
    Generated-by: Claude Opus 4.8 (1M context)
    
    * thread model update
    
    add claude.md file and update AGETNS.MD file
    
    ---------
    
    Co-authored-by: Hans Van Akelyen <[email protected]>
---
 AGENTS.md       |  43 +++++++
 CLAUDE.md       |   1 +
 SECURITY.md     |  49 ++++++++
 THREAT_MODEL.md | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pom.xml         |   2 +
 5 files changed, 447 insertions(+)

diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000000..0ea7ac48dc
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,43 @@
+<!--
+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.
+-->
+
+# Agent Guide for hop
+
+This file is read by automated agents (security scanners, code analyzers,
+AI assistants) and human contributors working on this repository. Keep it
+concise — we will expand the sections below over time.
+
+## Build & test
+
+- **Requirements:** Java 21 (JDK) and Maven 3.6.3+ — or use the bundled wrapper
+  `./mvnw` (no local Maven needed).
+- **Build + unit tests:** `./mvnw clean install` (build with Java 21, otherwise
+  tests are skipped).
+
+## Conventions
+
+- **Formatting:** code is formatted with Spotless. Run `./mvnw spotless:apply`
+  before committing; CI runs `spotless:check`.
+- **License headers:** every new source/text file needs the Apache License 2.0
+  header — Apache RAT fails the build otherwise.
+- **Contributing & PRs:** see [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+## Security
+
+Security model: [SECURITY.md](./SECURITY.md)
+
+Agents that scan this repository should consult `SECURITY.md` and the
+threat model it links before reporting issues.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 120000
index 0000000000..47dc3e3d86
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1 @@
+AGENTS.md
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..62b250b81d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,49 @@
+<!--
+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.
+-->
+
+# Security Policy
+
+## Reporting a Vulnerability
+
+`apache/hop` follows the [Apache Software Foundation security 
process](https://www.apache.org/security/). Please report suspected
+vulnerabilities privately to `[email protected]`; do not open public
+GitHub issues or pull requests for security reports.
+
+## Threat Model
+
+What the project treats as in scope and out of scope, the security
+properties it provides and disclaims, the adversary model, and how
+findings are triaged are documented in [THREAT_MODEL.md](./THREAT_MODEL.md).
+
+## Hardening a deployment
+
+Hop runs operator-authored pipelines and workflows with full host capability;
+it is not a sandbox. Operators exposing Hop on a network should, at minimum:
+
+- **Change the default Hop Server credential.** The shipped credential is the
+  well-known default `cluster`/`cluster`. Do not expose the Hop Server (or the
+  separate `rest/` REST API, which has no built-in authentication) to an
+  untrusted network without changed credentials and a fronting auth layer.
+- **Enable TLS** for the Hop Server and sensitive backends (off by default), 
and
+  set `javax.net.ssl.keyStore` so outbound TLS verification is not relaxed.
+- **Protect credentials at rest** with the AES2 password encoder
+  (`HOP_PASSWORD_ENCODER_PLUGIN=AES2` + `HOP_AES_ENCODER_KEY`) or a secrets
+  resolver (Vault / Azure Key Vault / Google Secret Manager); the default
+  metadata password protection is reversible obfuscation, not encryption.
+- **Only run pipelines/workflows from trusted authors**, and parameterize any
+  variable that may carry untrusted data.
+
+See [THREAT_MODEL.md](./THREAT_MODEL.md) §10 for the full list.
diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md
new file mode 100644
index 0000000000..3c04bd210f
--- /dev/null
+++ b/THREAT_MODEL.md
@@ -0,0 +1,352 @@
+<!--
+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 Hop — Threat Model
+
+**Status:** Ratified by the Hop PMC. Originally drafted by the ASF Security 
Team
+(2026-06-01) against `apache/hop` (default branch `main`); the inferred items
+were then code-verified against the source and confirmed/corrected by the PMC
+(2026-06-22). Claims below cite `file:line` evidence where it is load-bearing.
+
+**Revision triggers:** a change to the Hop Server's auth / remote-execution
+model; a new scripting/exec transform or action; a change to how connection
+credentials / variables are stored or resolved; a new metadata source.
+
+---
+
+## §1 Header
+
+- **Project:** Apache Hop (`apache/hop`) — the "Hop Orchestration Platform":
+  visual **data and metadata orchestration** (pipelines + workflows) authored
+  in a GUI and run on a local engine, a remote Hop Server, or Beam runners.
+- **Scope of this model:** the `apache/hop` repository only (`hop-website`
+  excluded per the PMC, 2026-05-15).
+- **What Hop is:** a tool that **executes operator-authored data pipelines and
+  workflows** — by design those can read/write files, query databases, call
+  services, and run scripting/exec steps. It is **not a sandbox** and **not a
+  multi-tenant isolation boundary** (confirmed: no JVM `SecurityManager`/policy
+  anywhere in `engine`/`core`/`plugins`; the scripting engines are deliberately
+  configured for full host access — see §9).
+
+## §2 Scope and intended use
+
+Hop is operated by a **data engineer / operator** who authors pipelines
+(`.hpl`) and workflows (`.hwf`) and runs them — interactively in Hop GUI, via
+the `hop-run` CLI, or submitted to a **Hop Server** for local/remote execution.
+
+### Component families (distinct threat profiles)
+
+| Family | Path | Role / trust notes |
+|---|---|---|
+| Execution engine | `engine/`, `engine-beam/` | Runs pipelines/workflows the 
operator authored — incl. transforms that touch files, DBs, network, and 
**scripting/exec** steps. |
+| Hop Server (servlet / HTTP) | `engine/` — package `org.apache.hop.www` + 
`HopServerMeta` in `org.apache.hop.server`; launched by the `hop-server` 
command (`org.apache.hop.www.HopServer`). *(The `org.apache.hop.server` 
connection helpers `HttpUtil`/`ServerConnectionManager` — see §9 — live in 
`core/`.)* | The **network trust boundary**: an embedded Jetty server whose 
servlets accept pipeline/workflow run requests over HTTP (`/hop/execPipeline`, 
`/hop/addPipeline`+`/hop/startExec`, `/hop [...]
+| Hop REST API | `rest/` (`hop-rest`, a separate JAX-RS WAR) | A **distinct 
deployable** from the servlet server. Exposes `/api/v1/execute` (run 
pipelines/workflows) and `/api/v1/metadata` CRUD. It has **no built-in 
authentication** 
([`HopApplication.java`](rest/src/main/java/org/apache/hop/rest/v1/HopApplication.java));
 auth is whatever the servlet container / reverse proxy provides (§10). |
+| GUI (desktop / web) | `ui/` (`hop-ui`, SWT core), `rcp/` (desktop fragment), 
`rap/` (`hop-ui-rap`, RAP/RWT **web** GUI) | Authoring surface used by the 
trusted operator. `rap/` is the **web GUI**, not a server. |
+| Plugins | `plugins/` | The large transform/action set, incl. scripting 
(GraalJS/Rhino/Groovy), shell/exec, SQL, and per-DB/per-cloud connectors 
(`plugins/tech/*`). |
+| Connection / driver layer | `lib-jdbc/` (bundled JDBC drivers), `core/` 
(`org.apache.hop.core.database`, `org.apache.hop.metadata`) | DB/file/cloud 
credentials + JDBC drivers the operator configures. (There is no standalone 
`metadata/` module — connection/metadata code is in `core/`.) |
+
+**In scope:** engine + Hop Server + plugins + connection layer + GUI glue.
+**Intended caller trust:** Hop is operated as a **single trust domain** — the
+pipeline/workflow **author, the local operator, and anyone holding Hop Server
+credentials are all trusted** (they direct what Hop does). The **network-facing
+Hop Server (and the `rest/` REST API)** is where an untrusted actor can appear.
+
+## §3 Out of scope (explicit non-goals)
+
+- `hop-website`, `docs/`, `integration-tests/`, `assemblies/` build mechanics,
+  samples/demos — not the shipped runtime product. *(Note: the **default
+  security posture** baked by `assemblies/` and `docker/` — the shipped
+  `hop-server.xml`, `pwd/hop.pwd`, and the container `0.0.0.0` bind + default
+  credentials — is an in-scope **fact** for the auth analysis in §8/§10, even
+  though the assembly build itself is out of scope.)*
+- **Bundled third-party JDBC drivers / libraries' own vulnerabilities** — a CVE
+  in a packaged driver is a dependency/supply-chain matter, not a Hop defect
+  (Hop's job is to call them correctly). `lib-jdbc/` bundles redshift,
+  clickhouse, h2, mssql, vertica, crate, monetdb, jt400, snowflake, derby,
+  duckdb, hsqldb, postgresql, sqlite, mysql.
+- **Credential acquisition / storage / rotation** for the DBs/services Hop
+  connects to — the operator supplies these via connections/variables (§8, 
§10).
+- **Multi-tenant isolation** between pipelines/users on a shared engine or
+  server — Hop runs as a single trust domain (§9).
+
+## §4 Trust boundaries and data flow
+
+1. **Pipeline/workflow author → engine.** The author is trusted; what they 
build
+   (incl. scripting/exec/SQL steps) is *intended* execution, not an attack
+   (§7, §9).
+2. **Remote client → Hop Server (HTTP).** The high-value boundary: a network
+   client requests pipeline/workflow execution. Authentication, transport
+   security, and "who can run what" live here. The separate `rest/` REST API is
+   a second network surface with its own (absent) auth posture (§8, §10).
+3. **Metadata / project ingestion.** Pipeline/workflow + metadata files loaded
+   from disk/VCS. **Loading** a file parses it (with hardened XML — §8) and
+   instantiates only the no-arg *metadata* classes of referenced
+   transforms/actions; no scripting/exec/DB/network/UI code runs from loading
+   alone. **Running** it executes those steps — so running an **untrusted**
+   `.hpl`/`.hwf` is equivalent to running untrusted instructions (§11).
+   Verified: 
[`PipelineMeta.java`](engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java),
 
[`TransformMeta.java:238`](engine/src/main/java/org/apache/hop/pipeline/transform/TransformMeta.java#L238).
+4. **Connection layer → external DB/file/cloud.** Carries operator-configured
+   credentials; responses are backend-controlled (§8).
+5. **Variables / parameters.** Resolved into transform config at run time by
+   **raw, unescaped string substitution** — an injection surface if a value is
+   sourced from untrusted input (§9). A `Set Variables` transform/action can 
copy
+   an upstream **row-stream value** (or an OS env / `-D` property) into a
+   variable, so untrusted data can demonstrably reach a sink.
+
+## §5 Assumptions about the environment
+
+JVM; the OS the engine/server runs on (full file + process access for
+exec/shell/scripting steps); network reachability to configured backends + the
+Hop Server's listen interface; system trust store for outbound TLS (with the
+caveats in §9). The operator is responsible for setting 
`javax.net.ssl.keyStore`
+where strict outbound TLS verification is required (see §9).
+
+## §6 Assumptions about inputs — per-parameter trust
+
+| Input | Source | Trusted? | Notes |
+|---|---|---|---|
+| Pipeline/workflow definitions (`.hpl`/`.hwf`) | Operator/author | Trusted | 
Running an untrusted definition = running untrusted code (§11). Loading is 
hardened against XXE (§8). |
+| Hop Server / REST run requests | Network client | **Untrusted-capable** | 
Auth/authz is the boundary. The servlet server enforces HTTP Basic auth by 
default but ships a world-known default credential and has no per-endpoint 
authz; the `rest/` API has no built-in auth (§8). |
+| Connection configs + credentials | Operator | Trusted (secret) | Stored only 
**obfuscated** by default — *not* confidential at rest unless the operator opts 
into AES2 / a secrets resolver (§8). |
+| Variables / parameters | Operator, OS env / `-D`, or upstream row data | 
Untrusted-capable | Resolved by raw substitution; injection into 
SQL/paths/commands if the value is untrusted (§9). |
+| Metadata (from project files / VCS) | Operator/author | Trusted-by-default | 
Untrusted if loaded from an external source (§11). No signature/provenance 
check exists. |
+| Row/stream data processed by a pipeline | Upstream sources | Pass-through | 
Hop moves it; semantic validation is the pipeline author's. |
+
+## §7 Adversary model
+
+- **Out of scope:** the **pipeline/workflow author, the local operator, and any
+  holder of Hop Server credentials** — Hop is a single trust domain, and they
+  already control execution (a scripting step that runs code is intent, not an
+  attack).
+- **In scope:** a **remote actor against an exposed Hop Server or `rest/` REST
+  API** (submitting/running pipelines, reading results, mutating metadata) —
+  bounded by whatever auth fronts the surface; and a **network MITM** between
+  Hop and its backends or between client and server.
+- **Conditional:** an attacker who can get an **untrusted pipeline/metadata
+  file** loaded/run, or who controls a **variable/parameter** value (incl. an
+  upstream row value picked up by `Set Variables`) that reaches a sink.
+
+## §8 Security properties the project provides
+
+- **Hop Server authentication (with a critical caveat).** The servlet Hop 
Server
+  enables HTTP Basic authentication **by default** (`enable_auth` defaults to
+  true — 
[`HopServerMeta.java:229,251`](engine/src/main/java/org/apache/hop/server/HopServerMeta.java#L229),
 
[`WebServer.java:197`](engine/src/main/java/org/apache/hop/www/WebServer.java#L197)),
 gating every endpoint, so a *fully unauthenticated* client is
+  rejected. **Caveat:** the only shipped credential is the **publicly-known
+  default `cluster`/`cluster`** 
([`pwd/hop.pwd`](assemblies/static/src/main/resources/pwd/hop.pwd), 
[`HopServer.java:164`](engine/src/main/java/org/apache/hop/www/HopServer.java#L164)),
 there is **no per-endpoint
+  authorization** (a single `/*` role gate — any authenticated user can 
run/stop
+  pipelines), and the **Docker image binds `0.0.0.0:8080`** with those 
defaults.
+  Changing the credential and restricting exposure is an operator 
responsibility
+  (§10). — violation symptom: remote code execution using the unchanged default
+  credential on an exposed deployment; severity: critical.
+- **XML parsing is hardened against XXE.** Pipeline/workflow/metadata files are
+  parsed through a secure `DocumentBuilderFactory`
+  
([`XmlParserFactoryProducer.java`](core/src/main/java/org/apache/hop/core/xml/XmlParserFactoryProducer.java))
 with external general/parameter entities and
+  external DTD loading disabled and `FEATURE_SECURE_PROCESSING` on — XXE
+  file-read/SSRF and entity-expansion are mitigated (verified empirically). The
+  same secure parser is used by the Hop Server remote-add endpoints.
+- **Credential storage — NOT confidential by default.** Connection passwords in
+  metadata are by default only **reversibly obfuscated, not encrypted**: the
+  built-in `Hop` encoder 
([`HopTwoWayPasswordEncoder.java`](core/src/main/java/org/apache/hop/core/encryption/HopTwoWayPasswordEncoder.java))
 XORs against a
+  hardcoded, publicly-known seed and prefixes `Encrypted ` — the code itself
+  states it is *"not really encryption … obfuscation."* Anyone with the file
+  recovers the plaintext. Real confidentiality is **opt-in**: set
+  `HOP_PASSWORD_ENCODER_PLUGIN=AES2` with an operator-held 
`HOP_AES_ENCODER_KEY`
+  (AES-GCM), and/or keep secrets out of metadata via a variable resolver
+  (HashiCorp Vault, Azure Key Vault, Google Secret Manager). See §9, §10, §11a.
+- **Credential leakage in logs.** No plaintext password is logged by default,
+  and decrypted DB passwords travel in a JDBC `Properties` object, not the URL.
+  However, resolved JDBC/REST/HTTP URLs are logged at debug/detailed level
+  **without credential masking** 
([`Database.java:488`](core/src/main/java/org/apache/hop/core/database/Database.java#L488),
 
[`Rest.java:142,199`](plugins/transforms/rest/src/main/java/org/apache/hop/pipeline/transforms/rest/Rest.java#L142)),
 so credentials an
+  author embeds in a URL can leak — operators should avoid in-URL credentials.
+- **Transport security — available, off by default.** The Hop Server can serve
+  over HTTPS via a Jetty `SslContextFactory` configured with a JKS keystore in
+  the `<sslConfig>` block of `hop-server.xml`, but **TLS is off by default** 
(the
+  shipped config starts a plain-HTTP listener; only auth is on). Outbound JDBC
+  TLS is fully driver-delegated; HTTP/REST/cloud transforms use the JVM trust
+  store unless given a per-transform truststore. Enabling TLS is an operator
+  responsibility (§10).
+
+## §9 Security properties the project does *not* provide
+
+- **Not a sandbox.** An authored pipeline/workflow runs scripting/shell/SQL and
+  touches files/network with **full host/JVM capability — by design**. There is
+  no `SecurityManager` anywhere. The `script` transform sets GraalJS
+  `HostAccess.ALL` + `allowHostClassLookup(true)` 
([`ScriptUtils.java:165-166`](plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/ScriptUtils.java#L165-L166));
 the
+  legacy `javascript` transform and `eval` action use Mozilla Rhino with no
+  `ClassShutter`; `User Defined Java Class`/`Janino`/`Java Filter` compile
+  arbitrary Java; `Exec process`/`Shell` run OS commands via
+  `Runtime.exec`/`ProcessBuilder`. The **only** restriction mechanism is an
+  opt-in, **default-empty** substring deny-list 
([`JaninoCheckerUtil`](plugins/transforms/janino/src/main/java/org/apache/hop/pipeline/transforms/util/JaninoCheckerUtil.java)
 +
+  `codeExclusions.xml`) that covers **only** the three Janino-based steps and
+  blocks nothing out of the box (§11a).
+- **No isolation between pipelines/tenants** running on the same engine/server
+  beyond what the OS/JVM provides. Hop is a single trust domain (§7).
+- **No per-endpoint authorization on the Hop Server, and no built-in auth on 
the
+  `rest/` REST API.** Any authenticated servlet-server user is fully 
privileged;
+  the REST API relies entirely on the deployment for access control (§10).
+- **Credential confidentiality at rest is not provided by default** — only
+  reversible obfuscation; key-based protection is opt-in (§8).
+- **No strict TLS verification on all client/internal paths.** The relaxation
+  that is genuinely in effect is in 
[`ServerConnectionManager`](core/src/main/java/org/apache/hop/server/ServerConnectionManager.java),
 which installs a
+  **process-global** default `SSLContext` that skips CA-chain/hostname
+  validation (date-only) when `javax.net.ssl.keyStore` is unset. 
(`HopServerMeta.getHttpClient`
+  also *constructs* a self-signed-accepting, no-hostname-verify socket factory 
in
+  `sslMode`, but it is not actually wired into the returned client — latent.)
+  Several transforms also offer opt-in `ignoreSsl`/`trustAllCertificates`
+  switches (all default to verification on).
+- **No automatic sanitization of variables.** `${VAR}`/`%%VAR%%`/`$[hex]` 
tokens
+  are resolved by raw, unescaped string substitution
+  
([`StringUtil.environmentSubstitute`](core/src/main/java/org/apache/hop/core/util/StringUtil.java));
 the result is concatenated directly into
+  SQL strings, file paths, and shell bodies. Parameterizing/escaping any 
variable
+  that may carry untrusted data is the pipeline author's job. *(Note: the
+  row-stream value path of SQL transforms — Table Input lookup params, Execute
+  SQL "parameters" mode — IS bound via JDBC `PreparedStatement` `?` 
placeholders;
+  that path is parameterized by design and is not the injection concern.)*
+- **No protection if an untrusted `.hpl`/`.hwf` is loaded and run** — 
equivalent
+  to executing untrusted instructions. There is **no signature, provenance, or
+  integrity check** on these files; they are unsigned XML, and trust comes 
solely
+  from their source.
+
+## §10 Downstream (operator) responsibilities
+
+- **Lock down the Hop Server:** change the default `cluster`/`cluster`
+  credential, do not expose the remote-execution API to an untrusted network,
+  and restrict who can submit runs. **Do not expose the `rest/` REST API
+  without a fronting authentication layer** (reverse proxy / container auth) —
+  it has none of its own. Be aware the Docker image binds `0.0.0.0:8080` with
+  the default credential.
+- **Protect credentials at rest:** enable the AES2 encoder
+  (`HOP_PASSWORD_ENCODER_PLUGIN=AES2` + `HOP_AES_ENCODER_KEY`) and/or a secrets
+  resolver (Vault / Azure Key Vault / Google Secret Manager); never commit
+  default-obfuscated credentials to VCS; avoid embedding credentials in URLs.
+- **Manage connection credentials**; don't source connection config or
+  pipeline/metadata files from untrusted input — only run pipelines from 
trusted
+  authors.
+- **Treat scripting/exec/SQL steps as code**; parameterize variables that carry
+  untrusted data. The Janino deny-list (`codeExclusions.xml`) can be populated 
to
+  block named constructs in the three Janino-based steps if desired.
+- **Use TLS** for the server + sensitive backends. Set `javax.net.ssl.keyStore`
+  to avoid the relaxed process-global TLS trust manager (§9).
+
+## §11 Known misuse patterns
+
+- Exposing a **Hop Server with the unchanged default credential** (`cluster`/
+  `cluster`), or with `enable_auth=false`, to an untrusted network → remote
+  pipeline execution = remote code execution.
+- Exposing the **`rest/` REST API** to an untrusted network with no fronting
+  auth → unauthenticated pipeline execution + metadata mutation.
+- Running an **untrusted pipeline/workflow file** (or one fetched from an
+  untrusted source).
+- Building unparameterized SQL / shell / file paths from **untrusted variable
+  values** — e.g. a value placed into a variable by a `Set Variables` transform
+  from an untrusted upstream row, or from an attacker-influenced OS env / `-D`
+  property. The resolver does not escape, so this is injection (SQL injection,
+  path traversal, shell command construction).
+
+### §11a Known non-findings (recurring false positives)
+
+All of the following are **DISCLAIMED §9 non-guarantees** with the §7 adversary
+being the **trusted author/operator** — they are intended functionality, not
+vulnerabilities:
+
+- "A pipeline can run JavaScript/Groovy/Python/shell/SQL" — by design. The
+  `script` transform's GraalJS `HostAccess.ALL` + `allowHostClassLookup(true)`,
+  the Rhino transforms/`eval` action without a `ClassShutter`, and the
+  `ScriptValuesAddedFunctions` helpers (`execProcess`, `loadFileContent`,
+  `appendToFile`) are deliberate full-host scripting affordances.
+- "`User Defined Java Class` / `Janino` / `Java Filter` compile arbitrary Java
+  with no `SecurityManager`" — by design; the empty `codeExclusions.xml`
+  deny-list (which permits `System.exit`/`Runtime.exec` until an operator
+  populates it) is the documented default, not a regression.
+- "`Exec process` uses `Runtime.exec`; `Shell` uses `ProcessBuilder`
+  (`cmd.exe /C` on Windows; the script file is run directly on other OSes);
+  `sql`/`execsqlrow`/`dynamicsqlrow` execute
+  operator-authored SQL; `ssh`/`as400command` run commands on a remote host" —
+  running operator-authored commands/SQL is the step's purpose.
+- "A connection password in a `.hpl`/`.hwf` is only obfuscated / the encoder
+  seed is hardcoded" — by design; the default `Hop` encoder is obfuscation, not
+  confidentiality. Key-based confidentiality (AES2) and secrets resolvers are
+  opt-in (§8). An exposed default-obfuscated metadata password is recoverable 
by
+  design.
+- "Hop connects to a database with a configured password" — operator-supplied
+  connection config, not a finding.
+- "A bundled JDBC driver has CVE-XXXX" — dependency/supply-chain, handled via 
the
+  driver/ASF process, not a Hop code defect.
+- "Hop reads/writes the files a pipeline tells it to" — the operator's pipeline
+  doing its job.
+- *(Clarifications so triagers don't misfire):* the SQL **row-stream value 
path**
+  uses `PreparedStatement` `?` binding and is **not** a SQL-injection bug; the
+  `formula` transform (bounded POI/`FormulaParser` DSL) and the `simpleeval`
+  action (field/variable comparison) are **not** code-execution steps and 
should
+  not be conflated with the scripting steps above.
+
+## §12 Conditions that would change this model
+
+A change to the Hop Server / REST API auth or remote-exec model; a new
+scripting/exec transform or action; a change to credential/variable storage or
+resolution (e.g. a new default encoder); a new metadata source format/location;
+or a decision to support multi-tenant isolation (which today does not exist).
+
+## §13 Triage dispositions
+
+| Disposition | When | Section |
+|---|---|---|
+| **VALID** | A genuine implementation defect that violates a §8 property 
under the §7 adversary in in-scope code — e.g. an auth gate that can be 
bypassed (an endpoint reachable without the configured credential), an 
authorization hole beyond the documented single `/*` role, a credential leak in 
logs, or an XXE that bypasses the hardened parser | §7, §8 |
+| **OUT-OF-MODEL** | Adversary is the trusted 
author/operator/credential-holder; or code in 
`hop-website`/tests/samples/assembly build | §3, §7 |
+| **DOWNSTREAM-RESPONSIBILITY** | Default-credential / network exposure, REST 
API without fronting auth, credential mgmt, running untrusted pipelines, 
unparameterized untrusted variables, enabling TLS | §10 |
+| **DISCLAIMED** | A §9 non-guarantee (authored pipeline runs code; default 
obfuscation; no pipeline isolation; no per-endpoint authz; relaxed internal 
TLS; bundled-driver CVE) | §9 |
+| **MODEL-GAP** | Plausible, not covered → escalate to PMC | §12 |
+
+## §14 Maintainer decisions (resolution of the v1 open questions)
+
+The v1 draft's open questions have been resolved by the PMC (2026-06-22):
+
+1. **Framing (Q1):** Confirmed — Hop runs operator-authored pipelines (incl.
+   scripting/exec) by design; it is not a sandbox (§1, §9; code-verified).
+2. **Trust model (Q2, Q7):** Confirmed — **single trust domain**: author,
+   operator, and Hop Server credential-holder are trusted and out of the
+   adversary model. Running an untrusted `.hpl`/`.hwf` is
+   DOWNSTREAM-RESPONSIBILITY / OUT-OF-MODEL; the network-facing server/REST
+   submit-run path stays in scope (§7).
+3. **Out of scope (Q3):** Confirmed — website, tests/samples, assembly build,
+   bundled-driver CVEs (§3), with the caveat that the shipped default *posture*
+   is an in-scope fact.
+4. **Hop Server auth (Q5):** Resolved as code fact — Basic auth on by default
+   but a world-known default credential, no per-endpoint authz, Docker 
`0.0.0.0`
+   bind; the `rest/` REST API has no built-in auth. Treated as
+   DOWNSTREAM-RESPONSIBILITY: operators must change the credential, restrict
+   exposure, and front the REST API with auth (§8, §10).
+5. **TLS (Q6):** Resolved — available, off by default; internal relaxations are
+   documented §9 non-guarantees with an operator mitigation (§9, §10).
+6. **Credentials (Q8):** Resolved — default storage is obfuscation, not
+   confidentiality (DISCLAIMED); AES2 / secrets resolvers are the supported
+   confidentiality controls (§8, §11a). Unmasked URL logging noted in §8/§10.
+7. **Variable injection (Q9):** Resolved — raw unescaped substitution is a
+   DISCLAIMED §9 non-guarantee; sanitizing untrusted variables is the author's
+   DOWNSTREAM responsibility (§9, §11).
+8. **Scripting/exec (Q12):** Resolved — full host capability by design
+   (DISCLAIMED), with the opt-in default-empty Janino deny-list as the only
+   hardening hook (§9, §11a).
+9. **Host environment / credential rotation (Q10/Q11):** Confirmed
+   downstream/out-of-scope (§3, §5, §10).
+10. **Recurring non-findings (Q18a):** Expanded with concrete per-step bullets
+    (§11a).
+11. **Discoverability chain (meta):** Confirmed — `AGENTS.md → SECURITY.md →
+    THREAT_MODEL.md`.
+
+## §15 Machine-readable companion
+
+Not generated for v1.
diff --git a/pom.xml b/pom.xml
index 1bbbe2a37f..a430d70e34 100644
--- a/pom.xml
+++ b/pom.xml
@@ -484,6 +484,8 @@
                         <exclude>**/hop.pwd</exclude>
                         <exclude>**/*.iml</exclude>
                         <exclude>.dockerignore</exclude>
+                        <!-- symlink alias of AGENTS.md (header lives on the 
target) -->
+                        <exclude>CLAUDE.md</exclude>
 
                         <!-- Unit Test Exclusions -->
                         <exclude>**/test/**/*.txt</exclude>

Reply via email to