CVE-2026-92904: Rubygem-foreman_remote_execution: job output readable without object-level view_job_invocations check
A flaw was found in the foremanremoteexecution plugin's template invocations controller. The showtemplateinvocationbyhost action resolves the job invocation by ID without evaluating the caller's viewjobinvocations 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.
Other sources
The showtemplateinvocationbyhost action in TemplateInvocationsController resolves the job invocation via JobInvocation.find(params[:id]) and the host via Host.find(params[:hostid]) without performing an object-level authorization check against the caller's viewjobinvocations permission filter. The controller-level beforeaction :authorize checks only that the caller holds a viewjobinvocations 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?(:viewjobinvocations, @templateinvocation.jobinvocation), 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 defaultscope -> { where(taxonomyconditions) }, which limits host lookup to the caller's organizations. The attacker must supply a hostid 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 inputsafevalue), task details, and host/proxy information.
The V2 API controller has a related gap: the output and rawoutput actions in Api::V2::JobInvocationsController resolve the JobInvocation via findoptionalnestedobject (bare find) rather than findresource (which applies authorized(:viewjobinvocations)). The host IS properly scoped via authorized(:viewhosts), so the V2 gap is bounded by host authorization.
Introduced in foremanremoteexecution 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.
— Red Hat
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
foreman_remote_execution pluginto a version that resolves this vulnerability.Fixed in 15.0.0 - Upgrade
Upgrade
foreman_remote_execution pluginto a version that resolves this vulnerability.Fixed in 18.0.0 - Configuration
Modify TemplateInvocationsController#show_template_invocation_by_host to use an object-level authorization check equivalent to User.current.can?(:view_job_invocations, @template_invocation.job_invocation) instead of resolving JobInvocation via JobInvocation.find(params[:id]) without applying the permission's search filter to the specific record.
foreman_remote_execution TemplateInvocationsController (show_template_invocation_by_host) object-level authorization for view_job_invocations = enabled - Configuration
Update Api::V2::JobInvocationsController#output and #raw_output to resolve the JobInvocation using find_resource (so authorized(:view_job_invocations) is applied) instead of find_optional_nested_object (bare find) that bypasses object-level view_job_invocations filtering.
foreman_remote_execution Api::V2::JobInvocationsController (output/raw_output actions) job invocation authorization (find vs find_optional_nested_object) = use find_resource
Event History
Frequently Asked Questions
Who can exploit this issue?
An authenticated user must have view_job_invocations permission for the controller action, but their permission may be restricted by an object-level search filter. The issue allows such a user to access job invocations outside the records permitted by that filter, within their own organizations.
What information could be exposed?
An attacker who can enumerate job invocation IDs can read live job output, rendered scripts, and input values associated with other users' job invocations.
Is this limited to a particular access path?
Yes. The affected path is show_template_invocation_by_host in TemplateInvocationsController, which looks up job invocations and hosts by supplied IDs without checking the caller's object-level view_job_invocations filter. A sibling show action performs an explicit object-level authorization check, but the affected action does not.