chore: add draft threat model - #1642
Conversation
Adds docs/threat-model.md, a first draft of Karavan's threat model following the ASF Security threat-model-producer rubric. Karavan has no SECURITY.md and no entry in the ASF security site's project-coordinates.json. The Apache Camel security model (camel.apache.org/manual/security-model.html) scopes itself to apache/camel artifacts and notes that sibling subprojects have their own security surfaces, so Karavan currently has no document a triager can cite when classifying a vulnerability report or a scanner finding. The draft is written from public artifacts only. Every claim carries a (documented) / (maintainer) / (inferred) provenance tag: 53 documented, 0 maintainer, 28 inferred. The inferred claims are unratified hypotheses, each routed to a numbered question in section 4.14 for the maintainers to confirm, correct, or strike. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
b42af8b to
b499cb9
Compare
|
@mgubaidullin have a look at the questions so we could complete the model. |
|
Q1: Correct. The default password is a starting point set during installation (via Kubernetes secrets or Docker env vars) and operators are expected to change it through the UI; it is an out-of-scope dev/install convenience, not a supported production posture. Q2 — Confirm. Yes, any authenticated user is fully trusted. Q3 — Confirm. Yes, the connected Git repository and image registry are considered fully trusted inputs. Q4 — Confirm. It is just forward-looking scaffolding for future features. Q5 - Correct. That is just how it is today and we do not have any plans to change that. Q6 - Confirmed. Reports against insecure defaults are OUT-OF-MODEL (operator responsibility). Q7 (Resource Limits): Confirmed. DoS and resource exhaustion are OUT-OF-MODEL. Q8 (Public Endpoints): Confirmed. Pre-login disclosure of Keycloak/SSO configs is BY-DESIGN. Q9 - Already fixed Q10 (VS Code): Confirmed. Malicious workspaces/repos are OUT-OF-MODEL (trusted input). Q11 (API Sessions): Corrected. The non-invalidating route is BY-DESIGN (not an oversight). Q12 (Logs): Confirmed. Lack of strict audit trails is BY-DESIGN (it's just telemetry). |
@mgubaidullin answered waves 1-3 on #1642. Every hypothesis in the first draft is now confirmed, corrected, or superseded: 57 documented / 40 maintainer / 0 inferred, down from 28 inferred. Rulings that changed the model rather than confirming it: - Q11 corrected the draft. The non-invalidating /platform/internal/sources/{projectId}/{filename} route is by design, not an oversight; the single-use guarantee is scoped to the whole-project route only. - Q5 confirmed the negative side-effect inventory is accurate but declined to commit to it as an invariant, so it is recorded as a description of the current release rather than a promise. - Q1 ruled the default platform.password an install-time convenience set via secret or env var and changed through the UI, making reports against it OUT-OF-MODEL: non-default-build. Q9 was answered "already fixed", which rebinds the document. CsrfFilter (d211d71), PathUtils name validation (5e42524) and the Kubernetes resource allow-list all landed after the 4.22.0 tag, so the model now binds to main at 677a293 and says explicitly that a report against 4.22.0 or earlier is triaged against a model without those three. CSRF moved from a section 4.9 false friend to a claimed property in 4.8. The Kubernetes resource validation is described as defence in depth and explicitly not a boundary: it does not cover the builder pod path, build.sh, or the Docker compose path. Q13 and Q14, on document ownership and revision policy, remain open. Appendix B records every ruling so a disputed disposition can be traced to the answer behind it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What this is
A threat model for Karavan, at
docs/threat-model.md.It is deliberately not an audit, a pentest report, or a findings list. It describes the
implicit contract between Karavan and the people who deploy it: what Karavan assumes, what
it guarantees given those assumptions, what it leaves to the operator, and which misuses
look reasonable but aren't. The audience is two-sided — an operator deciding how to deploy
Karavan, and a triager who has to classify an inbound vulnerability report or a scanner hit
and cite a section to justify the call.
Why
Karavan has no
SECURITY.md, and no entry in the ASF security site'sproject-coordinates.json.The Apache Camel security model
scopes itself to
apache/camelartifacts and explicitly notes that sibling subprojects"have their own security surfaces" — Karavan isn't named. So today there is nothing a
triager can cite when a report or an automated scan lands.
The model inherits Camel's role vocabulary (route author / operator / external message
sender) rather than inventing a parallel one. Appendix A back-maps all eleven of that
document's statements to sections here.
Status: reviewed
@mgubaidullin answered waves 1–3 below. Every hypothesis in the first draft is now
confirmed, corrected, or superseded:
57
(documented)· 40(maintainer)· 0(inferred)— down from 28 inferred.Only Q13 and Q14 remain open, and both are about the document rather than about
Karavan (see Still open at the bottom).
The claim the document turns on — confirmed
The trust boundary is HTTP authentication, and nothing after it. A Karavan account is
Camel's "route author", which that model declares fully trusted. Docker mode bind-mounts
/var/run/docker.sock; Kubernetes mode grantsverbs: ["*"]pluspods/exec; a project'sdocker-compose.yamlreachesMountType.valueOf(...)and/bin/sh -c; andconfiguration/build.shis a user-editable file executed at mode0755.Q2 confirmed this. So "an authenticated user achieves RCE" is
OUT-OF-MODEL: adversary-not-in-scope, and §4.11a carries it as a suppression entry alongside thedocker.sock mount, the wildcard RBAC, and the
application.propertiescredentials thatevery secret scanner flags.
Three answers changed the model rather than confirming it
Q11 corrected the draft. I proposed that the non-invalidating
/platform/internal/sources/{projectId}/{filename}route was an oversight. It isn't — it'sby design. §4.8 property 9 now scopes the single-use guarantee to the whole-project route
only, and a report that the per-file route reuses a session is
BY-DESIGN.Q5 was confirmed but not promised. The negative side-effect inventory (no signal
handlers, no child processes, no host path reads, no extra listeners) is accurate — but
"that is just how it is today and we do not have any plans to change that" is a description,
not an invariant. §4.5 now says so explicitly and asks readers to re-verify on a §4.12
trigger, rather than treating it as a guarantee a future release will keep.
Q1 settled the insecure default.
platform.passwordis an install-time convenience setvia Kubernetes secret or Docker env var and changed afterwards through the UI, so a report
against the shipped default is
OUT-OF-MODEL: non-default-build.Q9 rebound the whole document
"Already fixed" turned out to mean three controls that landed after the 4.22.0 tag:
CsrfFilter— synchronizer-token check onX-CSRF-Token, constant-time, logout deliberately not exemptd211d71fPathUtils— project id / file name validation on the/ui/filewrite paths5e425249karavan.deployment.allowed-kinds+ pod-spec restrictions, namespace pinnedd211d71fSo the model is now bound to
mainat677a293a, not to 4.22.0, and says so in theheader: a report filed against 4.22.0 or earlier is triaged against a model in which those
three do not exist. CSRF moved out of the §4.9 "false friends" table and into §4.8 as a
claimed property.
Two things I want to flag rather than bury:
boundary. It covers
startDeploymentonly — notrunBuildProject's pod fragment, notconfiguration/build.sh, and nothing on the Docker path, where a compose file stillcontrols bind mounts and the shell command. §4.9 says that plainly so nobody later reads
it as a sandbox, and §4.11a routes "it can be bypassed via the builder pod" to
OUT-OF-MODELrather than to a control bypass.application.propertiessetsdeployment.allowed-kinds, butKubernetesServiceinjectskaravan.deployment.allowed-kinds. The names don't match, so the properties entrydoesn't bind and the code falls back to its
DEFAULT_ALLOWED_DEPLOYMENT_KINDSconstant.Same value today, so no behaviour change — but editing the properties file to widen the
list silently does nothing. Not a threat-model matter and not fixed here; worth a separate
one-line change.
Still open
Q13 — where does this live? Should Karavan get a
SECURITY.mdpointing atsecurity@apache.organd at this file, and be added to the ASF security site'sproject-coordinates.jsonso the Camel security page links it as a subproject?Q14 — who owns revisions, and does the model ship with releases? Proposed: Karavan
committers own it, it updates in the same PR as any change tripping a §4.12 trigger, and it
is tagged per release. This revision already spans two versions — which is exactly the drift
the tagging policy would prevent.
Notes
disputed disposition can be traced to the answer behind it rather than to prose.
🤖 Generated with Claude Code