Found while verifying #461 (#294). The #294 fix confined include/fromJsonFile to a subtree allowlist in the reconcile template path (internal/reconcile/template.go) — the daemon-side, git-sourced, SOPS-adjacent path that was the actual exploitable vector.
The bosun render command has its OWN, separate implementations that were NOT covered:
internal/cmd/render.go:217 — include: os.ReadFile(path), no containment.
internal/cmd/render.go:223-224 — fromJsonFile: os.ReadFile(path), no containment.
Both read arbitrary paths. #461's security review was scoped to the PR diff (reconcile/template.go) and correctly gave CLEAR for the deployed-path vector; this is a distinct code path.
Severity: lower than #294. bosun render is a local developer/operator command rendering the operator's own templates on their own machine — not the daemon processing attacker-influenceable git-sourced templates. Exploitation requires getting a malicious template into what the operator renders locally. So it's a consistency/defense-in-depth gap, not the same live risk as the reconcile path.
Fix: apply the same subtree-allowlist confinement (reuse the ensureWithin/validateIncludePath approach from reconcile/template.go, or factor it into a shared helper) so bosun render's include/fromJsonFile are confined to the same template_include_dir allowlist. Factoring the containment into one shared function would also prevent the two implementations from drifting again.
Found while verifying #461 (#294). The #294 fix confined
include/fromJsonFileto a subtree allowlist in the reconcile template path (internal/reconcile/template.go) — the daemon-side, git-sourced, SOPS-adjacent path that was the actual exploitable vector.The
bosun rendercommand has its OWN, separate implementations that were NOT covered:internal/cmd/render.go:217—include:os.ReadFile(path), no containment.internal/cmd/render.go:223-224—fromJsonFile:os.ReadFile(path), no containment.Both read arbitrary paths. #461's security review was scoped to the PR diff (reconcile/template.go) and correctly gave CLEAR for the deployed-path vector; this is a distinct code path.
Severity: lower than #294.
bosun renderis a local developer/operator command rendering the operator's own templates on their own machine — not the daemon processing attacker-influenceable git-sourced templates. Exploitation requires getting a malicious template into what the operator renders locally. So it's a consistency/defense-in-depth gap, not the same live risk as the reconcile path.Fix: apply the same subtree-allowlist confinement (reuse the
ensureWithin/validateIncludePathapproach from reconcile/template.go, or factor it into a shared helper) sobosun render's include/fromJsonFile are confined to the sametemplate_include_dirallowlist. Factoring the containment into one shared function would also prevent the two implementations from drifting again.