Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: yggdrasil-worker-package-manager-0.2.3-4.el10 ------ Summary: Remote Code Execution via APT Argument Injection: attacker-controlled package names beginning with `-` are passed to `apt-get` as raw arguments on Debian/Ubuntu code paths, allowing APT option injection and potentially root code execution through dangerous APT configuration directives for callers that can reach the worker dispatch boundary. Requirements to exploit: The attacker must be able to dispatch package-manager requests to the worker over its configured D-Bus/dispatcher trust boundary on a Debian/Ubuntu deployment where the APT backend is selected. The `remove` path is directly reachable; the `install` path is also reachable when the configured `allow-pattern` permits the supplied name. Component affected: `yggdrasil-worker-package-manager`, Debian/Ubuntu APT backend in `package_manager_apt.go` (`PackageManagerApt.run`), reached from message handling in `main.go` (`dataRx`) Version affected: `yggdrasil-worker-package-manager-0.2.3-4.el10`, when this code is built or deployed on Debian/Ubuntu systems using the APT backend Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - 7.8 (HIGH) AV:L - Exploitation requires access to the local D-Bus/dispatcher boundary used to send requests to the worker. AC:L - A leading-hyphen package name is sufficient to trigger APT option parsing; no special race or environmental condition is required for the injection primitive. PR:L - The caller must already be allowed to dispatch requests to this worker. UI:N - No separate user interaction is required once the caller can invoke the worker. S:U - The impact is within the same system security scope. C:H - Successful abuse of root-executed APT configuration can expose all data available to the worker context. I:H - Successful abuse can execute attacker-controlled actions as root and fully compromise system integrity. A:H - Successful abuse can disrupt package management or broader system availability in the worker's root context. Impact: Important. This issue can allow a caller that is authorized to use the worker interface to cross a trust boundary and influence a root-executed package-manager invocation, with high confidentiality, integrity, and availability consequences if dangerous APT options are accepted. It does not meet Critical because exploitation is not unauthenticated remote and depends on a restricted dispatch boundary and the Debian/Ubuntu APT code path. Embargo: no Reason: Exploitation depends on access to the configured worker dispatch boundary and the Debian/Ubuntu APT backend rather than unauthenticated remote reachability. The issue is serious, but the exposure is constrained enough that coordinated public fixing without embargo appears appropriate. Acknowledgement: Aisle Research Vulnerability Details: The APT backend invokes `apt-get` through `exec.Command`, so this is not shell injection. The security flaw is argument injection: untrusted `name` values are appended directly to the `apt-get` argument list without an option terminator (`--`) and without rejecting leading-hyphen values. As a result, a package name such as `-h` or `-o...` is interpreted by APT as an option rather than a package name. ```go func (p *PackageManagerApt) run( command string, args ...string, ) (stdout, stderr []byte, code int, err error) { cmdargs := []string{"--assume-yes", command} cmdargs = append(cmdargs, args...) cmd := exec.Command("/usr/bin/apt-get", cmdargs...) stdout, stderr, code, err = run(cmd, p.sendStdout, p.sendStderr) return } ``` The message handling path forwards `remove` requests without any allow-pattern check, and `install` is only protected by the configured allow-patterns. With the default permissive configuration, both paths accept attacker-controlled names: ```go case "install": if !packageAllowed(m.Name) { return fmt.Errorf("cannot install %v: does not match an allow pattern", m.Name) } outb, errb, code, err = pm.Install(m.Name) case "remove": outb, errb, code, err = pm.Uninstall(m.Name) ``` ```toml allow-pattern = [".*"] ``` A deterministic proof of the bug is that `{"command":"remove","name":"-h"}` causes APT help output instead of package removal behavior, showing that the attacker-controlled `name` is parsed as an APT option. That establishes the option-injection primitive. Escalation from this primitive to root command execution depends on which APT configuration directives are accepted for the chosen operation, so the exact RCE path is configuration- and behavior-dependent, but the trust-boundary violation is directly observable. Steps to reproduce: 1. On a Debian/Ubuntu system with this worker installed, ensure the test caller has access to the configured dispatch boundary for the package-manager worker. 2. Dispatch a `remove` request with a leading-hyphen package name, for example: ```json {"command":"remove","name":"-h"} ``` 3. Send it using the normal worker dispatch mechanism, for example: ```sh echo '{"command":"remove","name":"-h"}' | yggctl dispatch --worker package_manager - ``` 4. Observe that the worker returns `apt-get` help output rather than attempting to remove a package. This confirms the injected `name` was interpreted as an APT option. 5. To test the broader impact, replace `-h` with a crafted `-o...` argument and verify whether the selected APT directive is honored for the invoked operation. The option-injection primitive is reproducible even where a specific hook-style command execution path is not demonstrated. Mitigation: Do not allow untrusted callers to access this worker's dispatch boundary. On affected deployments, tighten `allow-pattern` values so package names cannot begin with `-`, and avoid relying on the `remove` path for untrusted input until validation is added. The APT backend should also terminate option parsing with `--` before forwarding package names. Proposed Fix: Reject empty or leading-hyphen package names before invoking `apt-get`, and insert `--` so subsequent arguments are treated only as package names. As additional hardening, consider applying the same allow-pattern policy to `remove` that is already used for `install`. ```diff diff --git a/package_manager_apt.go b/package_manager_apt.go — a/package_manager_apt.go +++ b/package_manager_apt.go @@ func (p *PackageManagerApt) run( command string, args ...string, ) (stdout, stderr []byte, code int, err error) { + for _, a := range args { + if len(a) == 0 || a[0] == '-' { + return nil, nil, -1, fmt.Errorf("invalid package name: %q", a) + } + } cmdargs := []string{"-assume-yes", command} + cmdargs := []string{"--assume-yes", command, "--"} cmdargs = append(cmdargs, args...) cmd := exec.Command("/usr/bin/apt-get", cmdargs...) stdout, stderr, code, err = run(cmd, p.sendStdout, p.sendStderr) return } ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use
Tracker filed for rhel-10.3: https://issues.redhat.com/browse/RHEL-189261