REDHAT-BUG-2547357: Medium severity Red Hat smart_proxy_dynflow vulnerability
Proxy::Dynflow::Api selects authorizewithtoken from the path alone. If the Authorization header is absent, that method returns false and does not halt. A Sinatra before filter ignores the return value, so POST /dynflow/tasks/<uuid>/update and /done reach dispatchexternalevent. A second bypass sits in the same check: OtpManager.authenticate treats a Basic token with no colon as otp = nil, and passwords[username] == nil is true when that task has no stored OTP. generateotp has no production caller on current smartproxyremoteexecutionssh 1.0.x. On 0.11.x it is called only by PollingScriptRunner, and only in async-SSH mode. Omitting the header still bypasses that case.
This does not launch jobs. In the default :ssh mode, Runner::Base#externalevent refreshes and drops the payload. In :pull and :'pull-mqtt', PullScript#processexternalevent stores the caller’s output and exitcode, and exit code 0 is recorded as success.
On Satellite 6.16–6.18, async-SSH PollingScriptRunner#externalevent can also apply the payload when manualmode is set. That runner was removed in smartproxyremoteexecutionssh 1.0.0 (commit d8d1811, 2025-11-28).
The attacker must already know a live execution-plan UUID. Step ids are small integers. The console flaw below is what gives those UUIDs to a host that holds a CA-signed certificate.
Likely to be introduced in smartproxydynflow 0.4.0 by commit e205e19.
Affected Software
Event History
Frequently Asked Questions
Does the default SSH execution mode allow an attacker to change task results?
In the default :ssh mode, Runner::Base#external_event refreshes the task and drops the supplied payload. The issue does not launch jobs.
Which execution modes can record attacker-supplied output or a successful result?
In :pull and :'pull-mqtt' modes, PullScript#process_external_event stores the caller-provided output and exit_code; an exit code of 0 is recorded as success. On Satellite 6.16–6.18, async-SSH PollingScriptRunner can also apply the payload when manual_mode is set.
Can the authentication check be bypassed without an Authorization header?
Yes. When the Authorization header is absent, authorize_with_token returns false but does not halt processing, and the Sinatra before filter ignores that return value.
Is there also a bypass involving Basic authentication?
Yes. A Basic token with no colon is handled as an OTP value of nil, and authentication succeeds when the task has no stored OTP because passwords[username] == nil evaluates true.
Does the OTP-generation path affect current smart_proxy_remote_execution_ssh 1.0.x deployments?
The data states that generate_otp has no production caller in current 1.0.x. In 0.11.x, it is called only by PollingScriptRunner and only in async-SSH mode; the runner was removed in 1.0.0.