From 9927214eb629e4f6796bfd8c951547ad21efd77f Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Fri, 15 May 2026 15:03:06 +0200 Subject: [PATCH] Fix #2834: Add Kamelet Catalog security model, SECURITY.md and AGENTS.md Adds a security model for the Kamelet Catalog that specialises the Apache Camel Security Model for Kamelets (PMC-authored route templates), mirroring the apache/camel house style: - docs/modules/ROOT/pages/security-model.adoc: trust roles, component families, in/out-of-scope vulnerability classes, false-friend properties, downstream responsibilities, closed triage-disposition set, and a maintainer-ratification record (Camel PMC, 2026-05-15). - SECURITY.md: root reporting pointer to the Apache Camel ASF process. - AGENTS.md (+ CLAUDE.md symlink): AI agent guidelines with the Kamelet-specific Security Model section, mirroring apache/camel. Documentation only; no code or runtime change. nav.adoc is generated, so the page is reached via the SECURITY.md / AGENTS.md xrefs. AI-assisted (Claude Code) on behalf of Andrea Cosentino. Co-Authored-By: Claude Opus 4.7 (1M context) --- AGENTS.md | 330 +++++++++++ CLAUDE.md | 1 + SECURITY.md | 32 ++ docs/modules/ROOT/pages/security-model.adoc | 586 ++++++++++++++++++++ 4 files changed, 949 insertions(+) create mode 100644 AGENTS.md create mode 120000 CLAUDE.md create mode 100644 SECURITY.md create mode 100644 docs/modules/ROOT/pages/security-model.adoc diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..62cbe9fe2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,330 @@ +# Apache Camel Kamelets - AI Agent Guidelines + +Guidelines for AI agents working on this codebase. + +## Project Info + +The Apache Camel Kamelet Catalog is the default catalog of reusable Camel route +templates ("Kamelets"), distributed as Kubernetes-style YAML and consumed by +Camel, Camel K, Camel Quarkus and Camel Spring Boot. + +- Version: 4.20.0 +- Camel: 4.20.0 +- Java: 17+ +- Build: Maven (`mvn verify`); Go is required for the `script/` and `crds/` + generators +- Issue tracker: GitHub — https://github.com/apache/camel-kamelets/issues +- Related repository: `apache/camel` (Camel core — the Kamelet **runtime** + lives there, not here) + +## AI Agent Rules of Engagement + +These rules apply to ALL AI agents working on this codebase. + +### Attribution + +- All AI-generated content (GitHub PR descriptions, review comments, issue + comments) MUST clearly identify itself as AI-generated and mention the human + operator. Example: "_Claude Code on behalf of [Human Name]_" + +### PR Volume + +- An agent MUST NOT open more than 10 PRs per day per operator to ensure human + reviewers can keep up. +- Prioritize quality over quantity — fewer well-tested PRs are better than many + shallow ones. + +### Git branch + +- An agent MUST NEVER push commits to a branch it did not create. +- If a contributor's PR needs changes, the agent may suggest changes via review + comments, but must not push to their branch without explicit permission. +- An agent should prefer to use its own fork to push branches instead of the + main `apache/camel-kamelets` repository, to avoid filling the main repository + with uncleaned branches. +- Branch names: fix-issue → `ci-issue-`, quick-fix → + `quick-fix/`, CI fix → `ci-fix/`. Include the topic + and issue number where possible. +- After a Pull Request is merged or rejected, delete the branch. + +### GitHub Issue Ownership + +- An agent MUST ONLY pick up **unassigned** GitHub issues. +- If an issue is already assigned to a human, the agent must not reassign it or + work on it. +- Before starting work, assign the issue to its operator. +- Beginner tasks carry the `good first issue` label; experienced tasks carry + `help wanted`. + +### Commits + +- Fix an issue: `Fix #: ` +- Quick fix / chore: `chore: ` +- CI fix: `ci: ` +- Always reference the GitHub issue when applicable. The repository accepts + **squash** and **rebase** merges only (no merge commits). + +### PR Description Maintenance + +When pushing new commits to a PR, **always update the PR description** (and +title if needed) to reflect the current state of the changeset. Use +`gh pr edit --title "..." --body "..."` after each push. + +### PR Reviewers + +When creating a PR, **always identify and request reviews** from the most +relevant committers: + +- Run `git log --format='%an' --since='1 year' -- | sort | uniq -c | sort -rn | head -10` + to find who has been most active on the affected files. +- Use `git blame` on key modified files to identify who wrote the code. +- Cross-reference with the + [committer list](https://home.apache.org/committers-by-project.html#camel). +- Request review from **at least 2 relevant committers** via + `gh pr edit --add-reviewer`. +- When all comments are addressed and checks are green, re-request review. + +### Merge Requirements + +- An agent MUST NOT merge a PR if there are any **unresolved review + conversations**. +- An agent MUST NOT merge a PR without at least **one human approval**. +- An agent MUST NOT approve its own PRs — human review is always required. + +### Code Quality + +- Every new or changed Kamelet SHOULD include Citrus tests under + `tests/camel-kamelets-itest/src/test/resources//`; Kamelets with + passing behaviour tests are labelled `camel.apache.org/kamelet.verified=true`. +- After adding or modifying a Kamelet, **regenerate and commit** the generated + docs and validate, or CI will fail: + ```bash + cd script/generator && go run . ../../kamelets/ ../../docs/modules/ROOT/ + cd ../validator && go run . ../../kamelets/ # must report no ERRORS + ``` +- `nav.adoc` and the per-Kamelet doc pages are **generated** — do not hand-edit + them. +- A full `mvn verify` from the repository root must pass before pushing. + +### Asynchronous Testing + +Do **NOT** use `Thread.sleep()` in test code; it leads to flaky, slow, +non-deterministic tests. Use the project's Citrus test constructs (or +Awaitility, where Java test code applies) with an explicit timeout instead. + +### Issue Investigation (Before Implementation) + +Before implementing a fix, **thoroughly investigate** the issue. Kamelets are a +long-lived shared catalog — a template often looks "wrong" but exists for a +reason (compatibility with a Camel component default, an explicit insecure +convenience Kamelet, an intentional inbound-header mapping). + +1. **Validate the issue** — confirm it is real and reproducible; question + assumptions in the description. +2. **Check git history** — `git log --oneline ` and `git blame `; + read commit messages and linked issues. +3. **Search for related issues/PRs** on GitHub for prior discussion or + intentional decisions. +4. **Check the developer guide** — `docs/modules/ROOT/pages/development.adoc` + and the catalog `README.md` for authoring rules. +5. **Check the runtime boundary** — if the behaviour is in the `kamelet:` + component, `{{property}}` placeholder binding, or + `org.apache.camel.kamelets.utils.*`, the fix belongs in **`apache/camel`**, + not here. +6. **Check if the "fix" reverts prior work** — if so, stop and reconsider; if + still justified, acknowledge it explicitly in the PR description. + +**Present findings** to the operator before implementing. Flag risks, +ambiguities, or cases where the issue may be invalid. + +### Knowledge Cutoff Awareness + +AI agents have a training cutoff. **Never make authoritative claims about +external project state (Camel component options, dependency versions) based +solely on training knowledge** — verify against the Camel catalog, Maven +Central, or release notes before relying on or questioning a version. + +### Documentation Conventions + +When writing or modifying `.adoc` documentation: + +- Use `xref:` for internal links, never external `https://camel.apache.org/...` + URLs for pages that exist in this module. +- Do not hand-edit generated pages (`nav.adoc`, per-Kamelet pages); change the + Kamelet YAML and regenerate. +- When reviewing doc PRs, check `xref:` links and anchors resolve. + +## Security Model + +The Kamelet Catalog has a documented security model that defines who is +trusted, where the trust boundaries sit, what counts as a **catalog** +vulnerability, and what is route-author or operator responsibility. The +canonical document is +[`docs/modules/ROOT/pages/security-model.adoc`](docs/modules/ROOT/pages/security-model.adoc). +It **specialises** the +[Apache Camel Security Model](https://camel.apache.org/manual/security-model.html); +where the catalog model is silent, the Camel model governs. Use it as the +reference when triaging security reports, deciding whether a finding warrants a +CVE, or reviewing a security-sensitive Kamelet PR. + +For the vulnerability **reporting** convention, +[`SECURITY.md`](SECURITY.md) at the repository root is the entry point GitHub +and security tooling expect. It points to the security model for scope and to +the Apache Camel ASF process for private disclosure. An agent that discovers or +is handed a suspected vulnerability MUST NOT open a public issue, PR, or +mailing-list post about it — follow the private process and stop. + +### Trust assumptions + +- **Kamelet authors and the Camel PMC** are trusted: the Kamelet template *is* + route code, reviewed by the PMC. The catalog's special obligation is that the + *template author is the catalog*, so a shipped template must be + safe-by-default for the untrusted-data boundary. +- **Route authors and operators** are **fully trusted**. They bind every + property — `url`, `query`, `template`, `expression`, `executable`, file + paths, credentials — from configuration. Binding a property to + attacker-controlled data is route-author error, not a catalog vulnerability. +- **Data flowing through a Kamelet** (the message a source emits or a + sink/action consumes) is **untrusted**. This is the primary attacker model. +- **The Kamelet runtime is not in this repository.** The `kamelet:` component, + placeholder binding and `org.apache.camel.kamelets.utils.*` live in + `apache/camel`; defects there are routed to that project. + +The fundamental trust boundary is between **the Kamelet (template + bound +configuration)** and **the data flowing through it** — unchanged from Camel, +except the author of the trusted template is now the catalog. + +### What is in scope (concise summary) + +A report is in scope when a **shipped Kamelet template**, in its default +configuration, lets untrusted data cross a boundary the template — not the +operator's wiring — should have held: + +- A sink/action template that maps an untrusted inbound header/body into a + dispatch position (`CamelHttpUri`, `CamelFileName`, `Camel*DestinationName`, + `CamelExec*`, `CamelBeanMethodName`, …) without stripping/fixing the + dispatch headers it does not deliberately consume. +- A template that passes message data (not a `{{property}}`) to a + `simple`/template-language/JSONPath/query evaluator the Kamelet's purpose did + not require. +- A template that ships a Camel component with a security-relevant **insecure + default** (Java serialisation on an untrusted consumer, TLS verification off, + admin surface on `0.0.0.0`, permissive header filter), reachable just by + deploying the Kamelet. +- A secret property not marked `format: password` + + `x-descriptors: [urn:camel:group:credentials]`, or a missing `pattern:` + that turns operator contract into reachable unintended behaviour + (hardening tier). + +### What is out of scope + +- An operator/route author binding a property (`{{template}}`, `{{query}}`, + `{{expression}}`, `{{url}}`, `{{executable}}`, credentials, paths) to + untrusted data — including all template-language and SQL/NoSQL/GraphQL + Kamelets. +- A Kamelet doing, by design, the dangerous thing it is **named** for + (`exec-sink`, `ssh-*`, `scp-sink`) or network exposure of a source + (`webhook-source`, `http-source`); `*-secured-*` means auth *options* exist, + not that auth is on by default. +- Explicitly-named insecure conveniences (`*-not-secured-*`, + `kafka-not-secured-*`). +- Underlying Camel component or transitive-dependency CVEs not caused by the + template. +- Defects in the Kamelet execution runtime (route to `apache/camel`). +- DoS via resource exhaustion (operator applies throttling/limits). +- The `data:image` icon annotation (metadata for tooling, never executed). +- `camel-kamelets-catalog` "parsing YAML" — it reads only build-bundled + classpath YAML, not untrusted documents. +- Build/CI/test/scaffolding code (`script/`, `crds/` generator, `tests/`, + `templates/`, `kamelets-maven-plugin`). +- Scanner reports without a PoC through a shipped template. + +### Operator hardening checklist + +When reviewing or recommending a deployment, surface: + +- Treat a deployed Kamelet exactly like a route you wrote — same privileges and + trust. +- Load Kamelets only from a trusted, integrity-checked catalog (an entity that + can modify a Kamelet definition has arbitrary code execution by design). +- Never bind a property from untrusted message data. +- Strip `Camel*` headers from untrusted producers before a sink Kamelet, even + though many templates also do this for known dispatch headers. +- Do not place `exec-sink` / `ssh-*` / `scp-sink` downstream of untrusted + input. +- Secure inbound source Kamelets with network controls and the `*-secured-*` + auth options. +- Resolve credentials through a Camel vault, not plaintext properties. +- Pin the catalog and Camel versions; follow Camel security announcements. + +### Reviewer checklist (for security-sensitive Kamelet PRs) + +When reviewing a PR that adds or changes a Kamelet template: + +- Does the template map an untrusted inbound header/body into a + dispatch-controlling position? It MUST strip or fix every Camel-internal + header it does not deliberately consume, before the dispatching step + (compare `http-sink`'s `removeHeader: CamelHttpUri`). +- Does the template pass message data (not a `{{property}}`) to an + expression/template/query evaluator? That is the in-scope injection class — + the evaluated input must be a bound property. +- Does the template add a component with a security-relevant default? Ship the + safe default; if it must be relaxed, name the Kamelet `*-not-secured-*`, + document it, and get PMC sign-off. +- Does a property carry a secret? It MUST be `format: password` with + `x-descriptors: [urn:camel:group:credentials]`. +- Does a free-form property feed an endpoint/resource URI? Add a `pattern:` + (operator-typo containment — not a trust control). +- Does the change relax a default or widen what a template forwards? It needs + an upgrade-guide entry and PMC review. + +## Structure + +``` +camel-kamelets/ +├── kamelets/ # ~250 *.kamelet.yaml route templates (the product) +├── library/ +│ ├── camel-kamelets/ # resource bundle (jars the YAML) +│ ├── camel-kamelets-bom/ # Maven BOM (pom only) +│ ├── camel-kamelets-catalog/ # runtime metadata reader (Java) +│ ├── camel-kamelets-crds/ # Fabric8-generated K8s CRD POJOs (Java) +│ └── kamelets-maven-plugin/ # build-time validation plugin +├── crds/ # Go CRD client generator (build/CI) +├── script/ # Go doc generator + YAML validator (build/CI) +├── templates/ # init .vm template + Pipe examples +├── tests/camel-kamelets-itest/ # Citrus integration tests +└── docs/modules/ROOT/ # Antora AsciiDoc (security-model.adoc lives here) +``` + +## Build + +```bash +mvn verify # full build (from root) +mvn verify -Pcoverage # with coverage +cd script/generator && go run . ../../kamelets/ ../../docs/modules/ROOT/ # regen docs +cd script/validator && go run . ../../kamelets/ # validate +``` + +## Kamelet Authoring Conventions + +- One `*.kamelet.yaml` per Kamelet; file name MUST match `metadata.name`. +- Each Kamelet is exactly one of `source`, `sink`, or `action` + (`camel.apache.org/kamelet.type` label, mandatory). +- `camel.apache.org/provider` MUST be `"Apache Software Foundation"`. +- Icons MUST be embedded `data:image` (no external URLs). +- Source templates send to `kamelet:sink`; sink templates consume from + `kamelet:source`. +- Dependencies go in `spec.dependencies` (`camel:`, + `mvn:group:artifact:version` with Apache-compatible license, or + `github:apache/...` source only). +- Properties are declared as JSON-schema in `spec.definition`; mark secrets + `format: password` + `x-descriptors: [urn:camel:group:credentials]`. + +## Links + +- https://camel.apache.org/ +- https://github.com/apache/camel-kamelets +- https://github.com/apache/camel-kamelets/issues +- https://camel.apache.org/camel-k/latest/kamelets/kamelets.html +- https://camel.apache.org/security/ +- dev@camel.apache.org diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /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 000000000..04b71b4ed --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,32 @@ +# Security Policy + +The Apache Camel Kamelet Catalog is an Apache Camel sub-project and follows the +Apache Camel security process. + +## Supported Versions + +To see which versions of Apache Camel (and the Kamelet Catalog shipped with +them) are supported, please refer to this +[page](https://camel.apache.org/download/). + +## Reporting a Vulnerability + +For information on how to report a new security problem please see +[here](https://camel.apache.org/security/). + +Do not open a public GitHub issue or pull request for an unpublished +vulnerability — follow the private ASF process and stop. + +## Security Model + +Before submitting a report, please read the project's +[Security Model](docs/modules/ROOT/pages/security-model.adoc). It documents who +is trusted, where the trust boundaries sit, which classes the Camel PMC accepts +as a Kamelet Catalog vulnerability, and which categories are out of scope +(route-author or operator responsibility, a Kamelet doing the dangerous thing it +is named for, the Kamelet execution runtime that lives in `apache/camel`, +third-party CVEs not caused by a template, DoS through unthrottled routes, etc.). +It specialises the +[Apache Camel Security Model](https://camel.apache.org/manual/security-model.html); +where this catalog's model is silent, the Camel model governs. Reports outside +the documented scope will be closed with a reference to that page. diff --git a/docs/modules/ROOT/pages/security-model.adoc b/docs/modules/ROOT/pages/security-model.adoc new file mode 100644 index 000000000..523b472a0 --- /dev/null +++ b/docs/modules/ROOT/pages/security-model.adoc @@ -0,0 +1,586 @@ += Security Model + +This page documents the security model of the *Apache Camel Kamelet Catalog*: +who is trusted, where the trust boundaries sit, what counts as a catalog +vulnerability, and what is left to the route author and the deployment operator. +It is the reference used by the Apache Camel PMC when triaging security reports +against the Kamelet Catalog and when deciding whether a behaviour should be +hardened in a Kamelet template or addressed by the deployment. + +The Kamelet Catalog is an *Apache Camel sub-project*. It does not define its own +trust model from scratch: it *specialises* the +https://camel.apache.org/manual/security-model.html[Apache Camel Security Model] +for the specific shape of a Kamelet (a pre-written, PMC-reviewed Camel route +template distributed as YAML). Where this document is silent, the Camel Security +Model governs. Where they overlap, this document is the more specific authority +for the catalog. + +[IMPORTANT] +==== +*Status:* Maintainer-ratified (Apache Camel PMC, 2026-05-15). Ready to publish +as the catalog's security model. + +*Version binding:* written against `camel-kamelets` 4.20.0 (commit +`79dcf4cfca`, 2026-05-15), Camel 4.20.0. A report against catalog version _N_ is +triaged against this model as it stood at _N_, not at `main`. + +*Provenance:* claims grounded in the catalog README, the +`development.adoc` developer guide, the CRD specification, or the Kamelet YAML +itself are stated as fact. The structural inferences in the initial draft were +ratified by the Camel PMC on 2026-05-15; the _Maintainer ratification_ section +at the end records what was confirmed and what was deliberately deferred, so a +triager can cite "_(maintainer, 2026-05)_" rather than bare prose. + +*Confidence:* the trust model, component families and scope boundaries are +documented (catalog README, developer guide, Kamelet YAML, the parent Camel +model) and PMC-confirmed; one item (a machine-readable triage sidecar) is +deferred by PMC decision, not unresolved. + +*Reporting:* see _Reporting a vulnerability_. Findings that fall under +_In-scope vulnerability classes_ are reported privately through the Camel ASF +process; findings under _Out of scope_ or _Known limitations_ are closed with a +reference to this page. +==== + +== Audience + +This document is written for four audiences: + +* *Security researchers and CVE reporters* who need to know what the Camel PMC + will accept as a Kamelet Catalog vulnerability before submitting a report. +* *Automated triage tooling* (CVE scanners, AI-assisted security review) that + needs an authoritative scope statement to distinguish a real catalog + vulnerability from intentional, documented design. +* *Kamelet authors and reviewers* contributing or reviewing Kamelet YAML, who + need to know which template patterns and property defaults are acceptable. +* *Route authors and deployment operators* who embed Kamelets in an + integration, and need to know which responsibilities the catalog delegates to + them. + +== What a Kamelet is (and what this changes) + +A Kamelet is a single YAML file containing a *Camel route template* (in +`spec.template`, YAML DSL) plus a JSON-schema declaration of the *configuration +properties* the route author binds (in `spec.definition.properties`). The +catalog ships about 250 of these (94 sources, 95 sinks, 61 actions). A Kamelet +is referenced by name from a route or `Pipe`; the runtime substitutes +`{{property}}` placeholders with the bound values and runs the template like any +other Camel route. + +The security-relevant consequence: *in a hand-written Camel route, the route +author writes the route; in a Kamelet, the catalog author (the Camel community, +reviewed by the PMC) writes the route fragment and the route author only +supplies bound property values.* The trust boundary between trusted route code +and untrusted message data is unchanged from Camel's model - but the *author of +the trusted code* is now the catalog. That is the single fact that shapes +everything below: a Kamelet template must be safe-by-default for the +untrusted-data boundary, because the operator who deploys it generally does not +inspect or rewrite the template. + +== Trust model + +=== Roles + +[cols="1,1,3"] +|=== +| Role | Trust level | What this role can do + +| Kamelet authors and the Camel PMC +| Trusted +| Author and review the Kamelet template (which is route code), choose property + defaults, decide which inbound headers a template maps where, and select the + underlying Camel component. The catalog relies on PMC review to ship templates + that are safe by default. + +| Route authors (who reference a Kamelet and bind its properties in Java, XML, + YAML DSL or a `Pipe`) +| Fully trusted +| Choose which Kamelet to use and where to place it in a route, and bind every + property - URLs, queries, file paths, OS commands, template/expression + strings, credentials - from configuration. Binding a property to an + attacker-controlled value is route-author error, not a catalog vulnerability. + +| Deployment operators +| Fully trusted +| Decide network exposure of source Kamelets, supply secrets and the secrets + backend, choose the Camel runtime and JVM, and decide which catalog to load + Kamelets from. Loading a Kamelet from an untrusted source is operator error + (see _Known limitations_). + +| External message senders / data flowing through the Kamelet +| Untrusted +| Provide the message body, headers and attachments that a source Kamelet emits + or that a sink/action Kamelet consumes. This is the primary attacker model. + The catalog's templates must not turn this data into code execution, endpoint + redirection, unsafe deserialisation, remote-resource resolution or auth bypass + on their own. +|=== + +=== Trust boundaries + +The fundamental trust boundary is identical to Camel's: between *the Kamelet +(its template plus the operator's bound configuration)* and *the data flowing +through it*. The Kamelet template and every `{{property}}` value are trusted; +anything that arrives in an `Exchange` body, header or attachment from the wire +or filesystem is untrusted. + +The Kamelet Catalog adds one internal boundary of its own: the boundary between +*the catalog as a distribution* (the set of YAML files the PMC signs and +releases) and *the consumer that loads them*. An entity that can introduce or +modify a Kamelet definition in the catalog a runtime loads is, by design, a +trusted route author with arbitrary route/code execution. Integrity of the +catalog artifact is therefore a precondition of this whole model, not a property +the runtime re-checks. + +=== Component families + +The repository ships several artifacts with different threat profiles. Only the +first is the security-relevant product. + +[cols="2,3,1",options="header"] +|=== +| Family | What it is | In this model? + +| Kamelet YAML catalog (`kamelets/*.kamelet.yaml`, shipped via the + `camel-kamelets` resource bundle) +| ~250 PMC-reviewed Camel route templates. The product. All template-level + security posture lives here. +| *Yes - primary* + +| `camel-kamelets-catalog` (Java) +| Runtime metadata reader. Loads only the YAML bundled on its own classpath at + build time, via Jackson `YAMLFactory`, into Fabric8/CRD model objects. No + public API accepts a caller-supplied path, URL or stream; not on the message + data path. +| Yes - metadata API surface only + +| `camel-kamelets-crds` (Java) +| Fabric8-generated Kubernetes model POJOs for the Kamelet CRD. Deserialised by + the consumer's Kubernetes client / Fabric8, not by code in this repository. +| No - the deserialiser is the consumer's, not this repo's (PMC-confirmed) + +| `kamelets-maven-plugin` +| Build-time validation of catalog YAML against the Camel component model. +| No - build tooling + +| `camel-kamelets-bom`, `camel-kamelets` packaging +| Maven BOM (pom only) and the resource bundle that jars family 1. +| Only as the delivery vehicle for family 1 + +| `script/` (Go generator/validator), `crds/` Go client generator, + `tests/camel-kamelets-itest` (Citrus), `templates/` (init `.vm` and Pipe + examples) +| CI, documentation generation, test and scaffolding code. Not shipped to a + runtime. +| No - unsupported / build / examples + +| The Kamelet execution runtime: the `kamelet:` component, `{{property}}` + placeholder binding, and `org.apache.camel.kamelets.utils.*` +| *Lives in `apache/camel` core, not in this repository* (the + `camel-kamelets-utils` module was removed here and folded into core). +| No - governed by the Camel Security Model +|=== + +The last row is the most consequential boundary statement: a defect in *how* a +Kamelet is executed (placeholder resolution, the `kamelet:` component, the +shared utility beans) is an `apache/camel` finding, not a catalog finding. A +defect in *what a shipped template does by default* is a catalog finding. + +== Vulnerability scope + +A report is in scope when it demonstrates that a *shipped Kamelet template*, in +its default configuration, lets untrusted message data cross a trust boundary +that an equivalent competently-written hand route would not have crossed - +because the defect is in the template the catalog authored, not in how the +operator wired it. + +=== Security properties and violation severity + +The catalog commits to a small set of properties *on top of* whatever the +underlying Camel component already provides. The Camel Security Model's +property/severity table applies unchanged to the component layer; the table +below is the catalog-template layer. + +[cols="3,3,1",options="header"] +|=== +| Property the catalog upholds (default configuration) +| What a violation looks like +| Indicative severity + +| A sink/action template that maps an untrusted inbound header or body into a + dispatch-controlling position strips or fixes the Camel-internal dispatch + headers it does not intend to expose +| A wire-supplied `CamelHttpUri`, `CamelFileName`, `Camel*DestinationName`, + `CamelExec*` (etc.) header survives into a `to:` / component call and + redirects the sink, when the Kamelet's stated purpose did not require it +| High to Critical (CVSS 7.5-9.8) + +| A template does not pass untrusted message data to an expression/template/ + query evaluator the Kamelet's purpose did not call for +| The template feeds `${body}` / an inbound header into `simple`, a template + language, JSONPath or a query string in a way the operator never asked for +| High to Critical (CVSS 8.1-9.8) + +| A shipped template does not enable a security-relevant component default that + the Camel model classes as insecure (Java deserialisation on an untrusted + consumer, TLS verification disabled, an admin surface bound to `0.0.0.0`) +| Adding the Kamelet to a route and sending a message reaches the insecure + behaviour with no risky property set +| Severity of the underlying Camel class; in scope + +| Secret-bearing properties are declared so tooling can mask them + (`format: password`, `x-descriptors: urn:camel:group:credentials`) +| A credential property is rendered or logged in plaintext by tooling that + honoured the schema, because the Kamelet failed to mark it +| Medium (CVSS 4.0-6.5) + +| Free-form destination-like properties constrain their accepted shape + (`pattern:` regex on URLs, template resource URIs, etc.) +| A property documented as an HTTP URL accepts a `file:` / `jar:` / `classpath:` + value because the template declared no constraint - widening operator error + into reachable behaviour +| Low to Medium (CVSS 3.7-6.1); see the false-friend note in _Out of scope_ +|=== + +These tiers are indicative. The PMC assigns the definitive CVSS per report. A +property only counts here if the catalog has actually committed to it in a +template, the README/developer guide, or a PMC statement. + +=== In-scope vulnerability classes + +==== Template-introduced header / dispatch injection + +A sink or action template that copies an untrusted inbound header or body into +a Camel-internal dispatch header (`CamelHttpUri`, `CamelFileName`, +`Camel*DestinationName`, `CamelExecCommand*`, `CamelBeanMethodName`, ...) - or +that fails to strip such a header it does not consume - so that wire input +redirects the component. Many catalog templates already defend this (for +example `http-sink` performs `removeHeader: CamelHttpUri` before `to: {{url}}`, +and `extract-field-action` sanitises a configurable header name). A *new or +changed template* that maps untrusted input into dispatch without that +discipline is the catalog analogue of the Camel header-injection CVE family. + +==== Template-introduced expression / template / query injection + +A template that passes untrusted message data (not a `{{property}}`) to a +`simple` expression, a template language (Velocity, Freemarker, Mustache, MVEL, +JSLT, XJ, string-template, ...), JSONPath/JQ, or a back-end query string the +Kamelet builds. The defect is the template doing this without the route author +asking; an operator binding a `{{template}}` / `{{query}}` / `{{expression}}` +property to untrusted data is out of scope (route-author responsibility, +mirroring Camel). + +==== Insecure component default shipped in a template + +A template that adds a Camel component to the route with a security-relevant +option set to the insecure value by default (Java serialisation on a consumer +exposed to an untrusted broker, TLS/hostname verification disabled, a +permissive header filter, an unfiltered `ObjectInputStream`), reachable simply +by deploying the Kamelet. This is the Camel "insecure defaults" class scoped to +the template's choice of defaults. + +==== Missing or incorrect secret / constraint metadata + +A property carrying a credential that is not declared `format: password` with +the credentials `x-descriptors`, so schema-honouring tooling exposes it; or a +destination-like property whose missing `pattern:` turns a documented operator +contract into reachable unintended behaviour. Triaged as low/medium hardening +unless it produces a concrete disclosure. + +=== Out of scope + +The following are *not* Kamelet Catalog vulnerabilities and will be closed as +such, with a reference to this page. + +* *A route author or operator binding a Kamelet property to untrusted data.* + `{{template}}`, `{{query}}`, `{{expression}}`, `{{url}}`, `{{executable}}`, + file paths and credentials are configuration. The catalog cannot decide on the + operator's behalf whether a bound value is trusted. Template-language Kamelets + (`velocity-template-action`, `jslt-action`, `freemarker-template-action`, + `mvel-template-action`, `mustache-template-action`, `xj-template-action`, + `string-template-action`, `chunk-template-action`) and SQL/NoSQL/GraphQL + Kamelets (`postgresql-*`, `mysql-*`, `mariadb-*`, `sqlserver-*`, + `oracle-database-*`, `cassandra-*`, `mongodb-*`, `snowflake-*`, + `graphql-sink`, ...) evaluate or build their template/query from an + operator-bound property. Wiring an untrusted source into that property is + route-author error, exactly as in the Camel model. +* *A Kamelet doing, by design, the dangerous thing it is named for.* + `exec-sink` ("Execute system commands") deliberately maps an inbound `args` / + `ce-args` header into `CamelExecCommandArgs` and runs `exec:{{executable}}`; + `ssh-sink`, `scp-sink`, `ssh-source` run remote commands/transfers. Placing + such a Kamelet downstream of untrusted input is operator responsibility - the + behaviour is the Kamelet's documented contract, analogous to Camel's + "bean-based dispatch via internal headers is intentional" limitation. +* *Network exposure of a source Kamelet.* `webhook-source`, `http-source`, + `http-secured-source` and similar open a `platform-http` listener. The catalog + does not add authentication except where a Kamelet's name and properties say + it does (`*-secured-*` variants expose auth *options* the operator must + configure). Exposing a source to untrusted networks, or not configuring the + offered auth, is operator responsibility. +* *Explicitly-named insecure convenience Kamelets.* `*-not-secured-*` / + `kafka-not-secured-*` Kamelets advertise their posture in the name and are + development/test conveniences. Their lack of transport security is the + documented contract, not a defect. +* *Vulnerabilities in the underlying Camel component or its transitive + dependencies.* "Kamelet X uses component Y which had CVE Z" is a Camel / + upstream finding unless the *template* configures Y insecurely by default. A + Kamelet's declared `mvn:` dependencies are vetted only for Apache-license + compatibility; their CVEs follow Camel's third-party-dependency policy. +* *Defects in the Kamelet execution runtime.* The `kamelet:` component, + `{{property}}` placeholder binding and `org.apache.camel.kamelets.utils.*` + live in `apache/camel`; route such findings there. +* *Denial of service via resource exhaustion.* Unthrottled sources, oversized + messages, expansion bombs - operators apply `throttle`, `circuitBreaker`, + resilience and JVM limits, exactly as in the Camel model. +* *The `data:image` icon annotation as an injection vector.* It is base64 + metadata for catalog tooling, never executed by the route runtime; safe + rendering of catalog metadata is the consuming UI's concern. +* *`camel-kamelets-catalog` "deserialises YAML".* It parses only YAML bundled + on its own build-time classpath into model objects; it is not an + untrusted-document parser, and exposes no API that accepts caller-supplied + YAML. +* *Build, CI, scaffolding and test code* (`script/`, `crds/` generator, + `tests/`, `templates/`, `kamelets-maven-plugin`) - separately authored, + not shipped to a runtime. +* *Reports from automated scanners with no proof of a concrete trust-boundary + breach through a shipped template.* + +=== Known limitations + +These look like vulnerabilities at first glance but are documented design +points. They may be tightened over time through the normal upgrade-guide +channel. + +* *The `exec-sink` argument path is intentional.* It reads an untrusted inbound + header into command arguments by design; the Kamelet is literally named + "Exec Sink" and lives in the `System` namespace. The mitigation is operator + placement, not a template change. +* *Kafka source Kamelets default `deserializeHeaders: true`.* Inbound Kafka + message headers are converted to their String representation by a fixed + `KafkaHeaderDeserializer` bean (CAMEL-21843). This is a documented default + with a per-Kamelet opt-out property; it is a String conversion, not Java + object deserialisation. +* *A `pattern:` regex on a property is shape validation, not an attack control.* + It constrains what an operator may type (e.g. a URL must start `http`/ + `https`); it does not make an attacker-controlled bound value safe and is not + an SSRF defence. See the false-friend note below. +* *`kamelet.verified=true` is a functional-test marker, not a security audit.* + It records that Citrus tests assert the Kamelet's behaviour; it makes no + security assertion. +* *A Kamelet inherits the security posture of its underlying component.* A + report must show the *template*, not the Camel component, is the cause. +* *There are no global build-time or compile flags that change the security + envelope.* The catalog is data (YAML); the only security-relevant "variants" + are per-Kamelet defaults and the explicitly-named insecure-convenience + Kamelets, both covered above. "The project" is the catalog as released, not a + configurable family of binaries. + +==== False-friend properties + +Single highest-value note for an integrator: + +* *An "action" Kamelet between an untrusted source and a sink is not a + sanitiser, WAF, or trust boundary.* It transforms or filters per its + documented purpose only. `predicate-filter-action` / + `header-matches-filter-action` decide pass/drop on a JSONPath/header; they do + not neutralise hostile content. +* *A `pattern:` regex looks like input security; it is operator-typo + containment.* It restricts scheme/shape, not trust. +* *`*-secured-*` in a Kamelet name means "auth options exist", not "auth is on + by default".* The operator must configure them. +* *`kamelet.verified=true` looks like a security seal; it is a test marker.* + +== Downstream responsibilities + +For these assumptions to hold, the route author and operator must: + +* *Treat a deployed Kamelet exactly like a route they wrote* - it runs with + their privileges and trust. +* *Load Kamelets only from a trusted, integrity-checked catalog.* An entity that + can add or modify a Kamelet definition has arbitrary code execution by design. +* *Bind every property from trusted configuration* - never bind + `{{template}}` / `{{query}}` / `{{expression}}` / `{{url}}` / + `{{executable}}` / credentials / file paths from untrusted message data. +* *Strip `Camel*` headers from untrusted producers* before a sink Kamelet, even + though many templates also do this for the dispatch headers they know: ++ +[source,yaml] +---- +- from: + uri: "platform-http:///ingest" + steps: + - removeHeaders: { pattern: "Camel*" } + - to: "kamelet:http-sink?url=https://trusted/backend" +---- +* *Not place command/transfer Kamelets* (`exec-sink`, `ssh-*`, `scp-sink`) + downstream of untrusted input. +* *Secure inbound source Kamelets* with network controls and, where offered, the + `*-secured-*` auth options. +* *Resolve credentials through a Camel vault*, not plaintext Kamelet properties. +* *Pin the catalog and Camel versions* and follow Camel security announcements. + +== Guidance for Kamelet authors and reviewers + +When contributing or reviewing a Kamelet, these questions decide whether the +change matches this model: + +* *Does the template map an untrusted inbound header or body into a + dispatch-controlling position?* If so it must strip or fix every + Camel-internal header it does not deliberately consume, before the dispatching + step. +* *Does the template pass message data (not a `{{property}}`) to an + expression/template/query evaluator?* If yes, that is the in-scope injection + class - the evaluated input must be a bound property, not the body/headers. +* *Does the template add a component with a security-relevant default?* Ship the + safe default; if a Kamelet must relax one, name it (e.g. `*-not-secured-*`), + document it, and get PMC sign-off. +* *Does a property carry a secret?* Mark it `format: password` with + `x-descriptors: [urn:camel:group:credentials]`. +* *Does a free-form property feed an endpoint URI or resource?* Add a `pattern:` + to contain operator error - and remember it is not a trust control. +* *Does the change relax a default or widen what a template forwards?* It needs + an upgrade-guide entry and PMC review. + +== Reporting a vulnerability + +The Kamelet Catalog uses the standard Apache Camel / ASF vulnerability process: + +* Read https://camel.apache.org/security/[Apache Camel Security]. +* Email `private-security@camel.apache.org` with the affected catalog + version(s), the specific Kamelet, and a proof of concept that demonstrates the + trust-boundary breach *through a shipped template in its default + configuration*. +* Do not open a public issue, pull request, or mailing-list/social post about an + unpublished vulnerability. Follow the ASF Security team's instructions. + +Reports matching _In-scope vulnerability classes_ are triaged on the private +list, fixed in a coordinated release, and published as a CVE advisory under the +Camel project. Reports matching _Out of scope_ or _Known limitations_ are closed +with a reference to this page. + +=== Triage dispositions + +The closed set of outcomes for a report, scanner finding, or AI analysis: + +[cols="2,3,1",options="header"] +|=== +| Disposition | Meaning | Licensed by + +| `VALID` +| A shipped template, in default configuration, turns untrusted data into + execution / redirection / unsafe deserialisation / remote-resource fetch / + auth bypass that the template - not the operator's wiring - introduced. +| _In-scope vulnerability classes_ + +| `VALID-HARDENING` +| No property above is broken, but a template could reasonably strip a header, + tighten a `pattern:`, add secret metadata, or flip a default. Fixed at PMC + discretion; usually no CVE. +| _Missing or incorrect secret / constraint metadata_ + +| `OUT-OF-MODEL: operator-bound-input` +| Requires attacker control of a `{{property}}` (template, query, expression, + URL, command, path, credential). +| _Out of scope_, item 1 + +| `OUT-OF-MODEL: by-design-named-behaviour` +| Requires the Kamelet to do the dangerous thing it is explicitly named for, or + network exposure of a source. +| _Out of scope_, items 2-4 + +| `OUT-OF-MODEL: runtime-not-in-this-repo` +| The defect is in the `kamelet:` component, placeholder binding, or + `kamelets.utils` - route to `apache/camel`. +| _Component families_, last row + +| `OUT-OF-MODEL: unsupported-component` +| Lands in `script/`, `crds/` generator, `tests/`, `templates/`, or the build + plugin. +| _Component families_ / _Out of scope_ + +| `BY-DESIGN: property-disclaimed` +| Concerns a behaviour _Known limitations_ documents (Kafka header + deserialisation, `pattern:` not a trust control, verified marker, component + inheritance). +| _Known limitations_ + +| `OUT-OF-MODEL: third-party` +| Underlying Camel component or transitive dependency CVE not caused by the + template. +| _Out of scope_, item 5 + +| `MODEL-GAP` +| Cannot be routed to any of the above - triggers a revision of this model + rather than an ad-hoc call. +| this section +|=== + +=== Conditions that would change this model + +Revise this document when: a new Kamelet introduces a sink-side dispatch +surface or evaluates message data as an expression/template by default; a +template ships an insecure component default; the catalog gains a runtime that +parses untrusted Kamelet YAML; `camel-kamelets-utils` returns to this +repository; a `script/` / example artifact is promoted into shipped runtime; or +a report arrives that cannot be cleanly assigned a disposition above. + +== Maintainer ratification + +The structural inferences in the initial draft were put to the Apache Camel PMC +and *confirmed on 2026-05-15*. They are now folded into the body as fact; this +record preserves the chain of authority so a triager can cite +"_(maintainer, 2026-05)_" when closing a report. + +[cols="3,2",options="header"] +|=== +| Question put to the PMC | Ratified answer (now in the body) + +| Is the catalog covered by Camel's existing security process, with this page + as the Kamelet-specific annex? +| *Yes.* `private-security@camel.apache.org`, the Camel PMC, CVEs under the + Camel project. (Header / _Reporting a vulnerability_.) + +| Must a sink/action template that maps untrusted input into a dispatch + position strip the dispatch headers it does not consume - committed property + or per-Kamelet practice? +| *Committed property.* Every such new or changed template must satisfy it. + (_Security properties_ / _Guidance for Kamelet authors and reviewers_.) + +| Is loading a Kamelet from an untrusted/user-writable source "attacker is a + trusted route author - RCE by design, out of scope"? +| *Yes.* (_Trust boundaries_; _Downstream responsibilities_.) + +| Is `deserializeHeaders: true` on Kafka source Kamelets the supported + production default? +| *Yes* - supported default, String conversion only, per-Kamelet opt-out + documented; a report against it is `BY-DESIGN`. (_Known limitations_.) + +| Are the `*-not-secured-*` Kamelets shippable / out of scope? +| *Out of scope* as a "vulnerability" - documented dev/test convenience, + explicit in the name. (_Out of scope_.) + +| Is `camel-kamelets-crds` in or out of model? +| *Out of model* - the deserialiser is the consumer's Kubernetes client / + Fabric8, not this repository's code. (_Component families_.) + +| Document placement and pointers (this page, root `SECURITY.md`, `AGENTS.md` + mirroring `apache/camel`)? +| *Confirmed* and in place. (_Related documents_.) + +| Publish a machine-readable triage sidecar (per-Kamelet trust / in-out / + dispositions) for automated review? +| *Deferred by PMC decision* - revisit once the prose model has lived through + a few triage cycles. This is a deliberate non-goal for now, not an open + question. (_Conditions that would change this model_.) +|=== + +A future revision is triggered by the events listed under +_Conditions that would change this model_ - in particular a report that cannot +be assigned a disposition, which is treated as a `MODEL-GAP` and a prompt to +revise this page rather than make an ad-hoc call. + +== Related documents + +* https://camel.apache.org/manual/security-model.html[Apache Camel Security + Model] - the parent model this page specialises. +* xref:development.adoc[Kamelets Developer Guide] - how Kamelets are authored. +* xref:apis/spec.adoc[Kamelet CRD specification] - the YAML contract. +* https://camel.apache.org/security/[Apache Camel Security] - the public + advisory index and reporting process. +* `SECURITY.md` (repository root) - the GitHub-rendered security pointer.