Bug 2535942 (CVE-2026-92904)

Summary: CVE-2026-92904 rubygem-foreman_remote_execution: Job output readable without object-level view_job_invocations check
Product: [Other] Security Response Reporter: TEJ RATHI <trathi>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: anthomas, ehelms, ggainey, jpasqual, juwatts, mdellweg, mhulan, nmoumoul, osousa, pcreech, rchan, smallamp, tmalecek
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in the foreman_remote_execution plugin's template invocations controller. The show_template_invocation_by_host action resolves the job invocation by ID without evaluating the caller's view_job_invocations permission filter against the record. An authenticated user whose job invocation visibility is restricted by a permission filter can enumerate job invocation IDs and read the live output, rendered script, and input values for other users' job invocations within their own organizations.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description TEJ RATHI 2026-09-17 11:18:51 UTC
The show_template_invocation_by_host action in TemplateInvocationsController resolves the job invocation via JobInvocation.find(params[:id]) and the host via Host.find(params[:host_id]) without performing an object-level authorization check against the caller's view_job_invocations permission filter. The controller-level before_action :authorize checks only that the caller holds a view_job_invocations permission covering the controller action; it does not evaluate the permission's search filter against the specific record. The sibling show action in the same controller explicitly performs User.current.can?(:view_job_invocations, @template_invocation.job_invocation), which is the object-level form.

JobInvocation includes Authorizable but not Taxonomix and has no taxonomy default scope, so the job invocation ID is unconstrained. Host::Base carries default_scope -> { where(taxonomy_conditions) }, which limits host lookup to the caller's organizations. The attacker must supply a host_id within their organizations that was targeted by the job invocation.

The action returns live output (stdout/stderr), the rendered script preview, template input values (hidden values are masked via input_safe_value), task details, and host/proxy information.

The V2 API controller has a related gap: the output and raw_output actions in Api::V2::JobInvocationsController resolve the JobInvocation via find_optional_nested_object (bare find) rather than find_resource (which applies authorized(:view_job_invocations)). The host IS properly scoped via authorized(:view_hosts), so the V2 gap is bounded by host authorization.

Introduced in foreman_remote_execution v15.0.0 by commit 45bd8b894424c9316516001fa0c44a0cedd70a2b (MariaAga, 2025-01-24, Fixes #38123, "add template invocation info to new job details"). The sibling show action has had the object-level User.current.can? check since 2016 (commit d194bf0, Fixes #13287). The new action added in 2025 did not replicate the check. All versions from v15.0.0 through v18.0.0 (current HEAD) are affected.