** Description changed:

- == Summary ==
- 
-   sudo-rs ≤ 0.2.13 (the version Ubuntu 26.04 ships as the default 
/usr/bin/sudo)
-   silently drops argument restrictions and trailing rule content when a 
sudoers
-   rule uses the standard `\<newline>` line-continuation syntax inside a
-   SimpleCommand token. A narrow rule like:
+ [ Impact ]
+ 
+ One feature of the sudoers file, is that it can define argument restrictions 
to
+ a command, e.g. the caller is only allowed to run 'systemctl' with sudo iff it
+ is invoked with specifically with the argument 'restart myapp.service', but no
+ other arguments.
+ 
+ sudo-rs will currently drop all argument restrictions that follow a
+ `\<newline>`:
  
        deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
            restart myapp.service
  
-   is loaded as `(root) NOPASSWD: /usr/bin/systemctl` — i.e. systemctl with
-   arbitrary args — granting local privilege escalation via any shell-escapable
-   command (systemctl edit, find -exec, awk, etc.). visudo-rs flags the input
-   ("garbage at end of line") and reports "invalid sudoers file", but sudo-rs
-   commits the rule prefix to the active ruleset anyway.
- 
-   This has been disclosed to the upstream sudo-rs maintainers
-   ([email protected]) on 2026-05-11. Filing here to also reach Ubuntu
-   Security via Launchpad — the `[email protected]` email alias is currently
-   bouncing for unknown-recipient `[email protected]` (separate 
alias-
-   routing issue that probably needs fixing on Canonical's MTA).
- 
-   == Affected ==
- 
-   * Ubuntu 26.04 LTS shipping sudo-rs 0.2.13-0ubuntu1 as default /usr/bin/sudo
-   * Ubuntu 25.10 (same sudo-rs default switch)
-   * All sudo-rs releases v0.2.5 through v0.2.13. Earlier versions if parser 
code
-     unchanged.
-   * Other distros packaging sudo-rs are also affected when sudo-rs is used as
-     the sudo backend.
- 
-   == Status of upstream fix ==
- 
-   * Parser-level fix exists: commit 7780f593 on `main` ("parser: implement 
line
-     continuation (fix #1571)", authored 2026-04-27).
-   * Fix is NOT in any release tag. Latest release v0.2.13 (2026-03-10) 
predates
-     the fix and is the version Ubuntu 26.04 ships.
-   * Upstream issue #1571 was filed and closed (2026-05-01) as a non-security
-     parser bug; the LPE-class security implication of pre-fix releases does 
not
-     appear to have been recognized in the report.
-   * The parser fix is necessary but incomplete as defense-in-depth. The rule
-     loader commits the rule prefix to the active ruleset BEFORE the rest of
-     the rule is parsed, so any other parse error on a continuation line leaves
-     an over-permissive prefix active. C sudo's yacc grammar discards the
-     entire rule on any per-rule parse error — sudo-rs should match this.
-   == Reproducer (Ubuntu 26.04, default sudo) ==
- 
-       sudo tee /etc/sudoers.d/repro <<'EOF'
-       testuser ALL=(ALL) NOPASSWD: /bin/echo \
-          hello world
-       EOF
- 
-       sudo -l -U testuser
-       # /etc/sudoers.d/repro:3:4: garbage at end of line
-       #    hello world
-       #    ^
-       # ...
-       # User testuser may run the following commands:
-       #     (ALL) NOPASSWD: /usr/bin/echo
-       #                     ^^^^^^^^^^^^^ argument restriction silently 
dropped
- 
-       sudo -u testuser sudo -n /bin/echo MALICIOUS_NOT_HELLO_WORLD
-       # MALICIOUS_NOT_HELLO_WORLD   <-- succeeds, no password
- 
-   C sudo on the same input (Debian's /usr/bin/sudo 1.9.16p2) correctly rejects
-   the rule.
- 
-   End-to-end kara→root LPE PoC is attached (`exploit.sh`). It creates a
-   throwaway unprivileged user, plants a vulnerable sudoers.d rule (admin
-   intent: lowpriv runs `/usr/bin/find /tmp/target` only), and demonstrates
-   the unprivileged user reading /etc/shadow via `find -exec` running as root,
-   then auto-cleans up. Lab-verified on Ubuntu 26.04 sudo-rs 0.2.13-0ubuntu1
-   on 2026-05-11.
- 
-   == Suggested fix (defense-in-depth) ==
- 
-   The parser fix 7780f593 is the right immediate change. Additionally:
- 
-   1. Buffer the entire rule before commit. Parse a rule into a tentative AST
-      in src/sudoers/parse.rs; only commit to the active ruleset after the
-      full rule (across all continuation lines) parses successfully.
- 
-   2. Treat per-rule parse errors as fatal for that rule. When a rule's parse
-      fails partway through, discard the partially-parsed prefix and resume
-      with the next top-level statement.
- 
-   == Attachments ==
- 
-   * reproduce.sh — parser-level repro showing the abbreviated rule
-   * exploit.sh — full LPE end-to-end demo (find -exec /bin/sh shell-escape);
-     idempotent cleanup; gated behind --i-understand
-   * run-on-lab.sh — multi-distro harness (we tested Debian/Alma/Fedora/Ubuntu)
-   * Ubuntu-26.04.log — successful LPE transcript (find -exec ran as
-     uid=0(root) gid=0(root); /etc/shadow first lines readable)
-   * README.md — full writeup including affected-version matrix and the
-     variant-B Cmnd_Alias analysis
- 
-   == References ==
- 
-   * Upstream: https://github.com/trifectatechfoundation/sudo-rs
-   * Upstream issue #1571 (closed 2026-05-01, classified `bug`/non-security):
-     https://github.com/trifectatechfoundation/sudo-rs/issues/1571
-   * Fix commit 7780f593 (2026-04-27, "parser: implement line continuation"):
-     https://github.com/trifectatechfoundation/sudo-rs/commit/7780f593
-   * v0.2.13 release (does not contain the fix):
-     https://github.com/trifectatechfoundation/sudo-rs/releases/tag/v0.2.13
-   * C sudo behavior reference: https://www.sudo.ws/docs/man/sudoers.man/
-   * Upstream disclosure: emailed [email protected] on 2026-05-11 — copy
-     available on request.
- 
-   Filed by Kara Zajac, independent security researcher.
-   github.com/KaraZajac · [email protected]
+ In this example, the "restart myapp.service" restriction is dropped, and users
+ can call systemctl with arbitrary commands. The visudo command will report
+ "invalid sudoers file", however the rule is still committed to sudo-rs.
+ 
+ The justification for backporting this fix comes from the fact that the error
+ can lead to unintended consequences. An administrator may want to allow users
+ to restart a system service, however if they incorrectly format the rule as
+ shown above, they will unknowingly be granting users the ability to 
arbitrarily
+ modify any service.
+ 
+ This is fixed by the upload by making the following change to the sudo-rs's
+ token parser:
+ 
+ * If '\' is followed by '\n', check whether the the next char is a space
+ * If it is a space, treat it as line continuation (emit a space)
+ * Otherwise, reject() and treat it as the end token
+ 
+ [ Test Plan ]
+ 
+ * Detailed instructions on how to reproduce the bug.
+ 
+ * These should allow someone who is not familiar with the affected
+   package to reproduce the bug and verify that the updated package
+   fixes the problem.
+ 
+ * If other testing is appropriate to perform before landing this
+   update, this should also be described here.
+ 
+ Reproduce the bug
+ -----------------
+ 
+ * Assert that sudo-rs is the current sudo provider:
+ 
+ sudo --version
+ 
+ # Output:
+ # sudo-rs 0.2.13-0ubuntu1
+ # ~~~~~~~
+ 
+ * Create a test user:
+ sudo useradd -m -s /bin/bash resolute
+ 
+ * Create a sudoers file with an affected rule that applies to the user:
+ 
+ sudo tee /etc/sudoers.d/apt-update >/dev/null <<'EOF'
+ resolute ALL=(root) NOPASSWD: /usr/bin/apt \
+     update
+ EOF
+ 
+ * Change to the test user:
+ 
+ su resolute
+ 
+ * Verify that the test user is not able to use sudo with any other
+ command:
+ 
+ resolute@ubuntu:~$ sudo echo hello
+ 
+ # Output:
+ # /etc/sudoers.d/apt-update:2:5: garbage at end of line
+ #    update
+ #    ^
+ # sudo: I'm sorry resolute. I'm afraid I can't do that
+ 
+ * Run 'apt' against an argument outside the rule restriction (remember we
+   should only be allowed to run 'sudo apt update'):
+ 
+ resolute@ubuntu:~$ sudo apt install cowsay
+ 
+ # Output:
+ # /etc/sudoers.d/apt-update:2:5: garbage at end of line
+ #     update
+ #     ^
+ # Installing:
+ #   cowsay
+ #
+ # Suggested packages:
+ #   filters  cowsay-off
+ #
+ # Summary:
+ #   Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 131
+ #   Download size: 18.1 kB
+ #   Space needed: 89.1 kB / 268 GB available
+ 
+ * Verify that the command was executed successfully despite it being outside
+   the allowed arguments
+ 
+ Testing proposed
+ ----------------
+ 
+ * Install the proposed sudo-rs:
+ 
+ sudo apt install -t resolute-proposed rust-sudo-rs
+ 
+ * Verify that the user "resolute" is no longer able to run any other command
+   with sudo than 'apt update':
+ 
+ resolute@ubuntu:~$ sudo apt install cowsay
+ 
+ # Output:
+ # sudo: I'm sorry resolute. I'm afraid I can't do that
+ 
+ resolute@ubuntu:~$ sudo apt update
+ 
+ # Output:
+ # Hit:1 http://security.ubuntu.com/ubuntu resolute-security InRelease
+ # Hit:3 http://archive.ubuntu.com/ubuntu resolute InRelease
+ # Hit:4 http://archive.ubuntu.com/ubuntu resolute-updates InRelease
+ # Hit:5 http://archive.ubuntu.com/ubuntu resolute-backports InRelease
+ # Hit:6 http://archive.ubuntu.com/ubuntu resolute-proposed InRelease
+ 
+ [ Where problems could occur ]
+ 
+ * The primary risks associated with this change is how it affects the generic
+   token parse function which is used by all token types, not just command line
+   lists. One example where this can have side-effects is when a token has
+   `ALLOW_ESCAPE = true`, there is a risk that two rules might be joined even
+   if they are separate rules.
+ 
+ * Previously broken sudoers files will now parse differently. For instance if
+   an administrator has specified `command + arg` in the sudoers file in the
+   affected way, that would previously have allowed all arguments. The argument
+   restriction is now honored correctly with the fix, which may be surprising,
+   even though it is technically correct.
+ 
+ [ Other Info ]
+ 
+ * The bug was first marked as a believed vulnerability, however this was
+   decided not to be the case as it requires sudo access in the first place
+   to edit the sudoers file.
+ 
+ * This SRU is part of a larger merge proposal for 26.04.1
+ 
+ * The fix is also natively part of the 0.2.14-1 upload to Stonking, currently
+   in proposed-migration
+ 
+ 
+ [ Original Description ]
+ 
+ == Summary ==
+ 
+   sudo-rs ≤ 0.2.13 (the version Ubuntu 26.04 ships as the default 
/usr/bin/sudo)
+   silently drops argument restrictions and trailing rule content when a 
sudoers
+   rule uses the standard `\<newline>` line-continuation syntax inside a
+   SimpleCommand token. A narrow rule like:
+ 
+       deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
+           restart myapp.service
+ 
+   is loaded as `(root) NOPASSWD: /usr/bin/systemctl` — i.e. systemctl with
+   arbitrary args — granting local privilege escalation via any shell-escapable
+   command (systemctl edit, find -exec, awk, etc.). visudo-rs flags the input
+   ("garbage at end of line") and reports "invalid sudoers file", but sudo-rs
+   commits the rule prefix to the active ruleset anyway.
+ 
+   This has been disclosed to the upstream sudo-rs maintainers
+   ([email protected]) on 2026-05-11. Filing here to also reach Ubuntu
+   Security via Launchpad — the `[email protected]` email alias is currently
+   bouncing for unknown-recipient `[email protected]` (separate 
alias-
+   routing issue that probably needs fixing on Canonical's MTA).
+ 
+   == Affected ==
+ 
+   * Ubuntu 26.04 LTS shipping sudo-rs 0.2.13-0ubuntu1 as default /usr/bin/sudo
+   * Ubuntu 25.10 (same sudo-rs default switch)
+   * All sudo-rs releases v0.2.5 through v0.2.13. Earlier versions if parser 
code
+     unchanged.
+   * Other distros packaging sudo-rs are also affected when sudo-rs is used as
+     the sudo backend.
+ 
+   == Status of upstream fix ==
+ 
+   * Parser-level fix exists: commit 7780f593 on `main` ("parser: implement 
line
+     continuation (fix #1571)", authored 2026-04-27).
+   * Fix is NOT in any release tag. Latest release v0.2.13 (2026-03-10) 
predates
+     the fix and is the version Ubuntu 26.04 ships.
+   * Upstream issue #1571 was filed and closed (2026-05-01) as a non-security
+     parser bug; the LPE-class security implication of pre-fix releases does 
not
+     appear to have been recognized in the report.
+   * The parser fix is necessary but incomplete as defense-in-depth. The rule
+     loader commits the rule prefix to the active ruleset BEFORE the rest of
+     the rule is parsed, so any other parse error on a continuation line leaves
+     an over-permissive prefix active. C sudo's yacc grammar discards the
+     entire rule on any per-rule parse error — sudo-rs should match this.
+   == Reproducer (Ubuntu 26.04, default sudo) ==
+ 
+       sudo tee /etc/sudoers.d/repro <<'EOF'
+       testuser ALL=(ALL) NOPASSWD: /bin/echo \
+          hello world
+       EOF
+ 
+       sudo -l -U testuser
+       # /etc/sudoers.d/repro:3:4: garbage at end of line
+       #    hello world
+       #    ^
+       # ...
+       # User testuser may run the following commands:
+       #     (ALL) NOPASSWD: /usr/bin/echo
+       #                     ^^^^^^^^^^^^^ argument restriction silently 
dropped
+ 
+       sudo -u testuser sudo -n /bin/echo MALICIOUS_NOT_HELLO_WORLD
+       # MALICIOUS_NOT_HELLO_WORLD   <-- succeeds, no password
+ 
+   C sudo on the same input (Debian's /usr/bin/sudo 1.9.16p2) correctly rejects
+   the rule.
+ 
+   End-to-end kara→root LPE PoC is attached (`exploit.sh`). It creates a
+   throwaway unprivileged user, plants a vulnerable sudoers.d rule (admin
+   intent: lowpriv runs `/usr/bin/find /tmp/target` only), and demonstrates
+   the unprivileged user reading /etc/shadow via `find -exec` running as root,
+   then auto-cleans up. Lab-verified on Ubuntu 26.04 sudo-rs 0.2.13-0ubuntu1
+   on 2026-05-11.
+ 
+   == Suggested fix (defense-in-depth) ==
+ 
+   The parser fix 7780f593 is the right immediate change. Additionally:
+ 
+   1. Buffer the entire rule before commit. Parse a rule into a tentative AST
+      in src/sudoers/parse.rs; only commit to the active ruleset after the
+      full rule (across all continuation lines) parses successfully.
+ 
+   2. Treat per-rule parse errors as fatal for that rule. When a rule's parse
+      fails partway through, discard the partially-parsed prefix and resume
+      with the next top-level statement.
+ 
+   == Attachments ==
+ 
+   * reproduce.sh — parser-level repro showing the abbreviated rule
+   * exploit.sh — full LPE end-to-end demo (find -exec /bin/sh shell-escape);
+     idempotent cleanup; gated behind --i-understand
+   * run-on-lab.sh — multi-distro harness (we tested Debian/Alma/Fedora/Ubuntu)
+   * Ubuntu-26.04.log — successful LPE transcript (find -exec ran as
+     uid=0(root) gid=0(root); /etc/shadow first lines readable)
+   * README.md — full writeup including affected-version matrix and the
+     variant-B Cmnd_Alias analysis
+ 
+   == References ==
+ 
+   * Upstream: https://github.com/trifectatechfoundation/sudo-rs
+   * Upstream issue #1571 (closed 2026-05-01, classified `bug`/non-security):
+     https://github.com/trifectatechfoundation/sudo-rs/issues/1571
+   * Fix commit 7780f593 (2026-04-27, "parser: implement line continuation"):
+     https://github.com/trifectatechfoundation/sudo-rs/commit/7780f593
+   * v0.2.13 release (does not contain the fix):
+     https://github.com/trifectatechfoundation/sudo-rs/releases/tag/v0.2.13
+   * C sudo behavior reference: https://www.sudo.ws/docs/man/sudoers.man/
+   * Upstream disclosure: emailed [email protected] on 2026-05-11 — copy
+     available on request.
+ 
+   Filed by Kara Zajac, independent security researcher.
+   github.com/KaraZajac · [email protected]

** Summary changed:

- [security] sudo-rs ≤ 0.2.13: silent drop of argument restrictions on 
\<newline> line continuation (LPE)
+ [SRU] sudo-rs ≤ 0.2.13: silent drop of argument restrictions on \<newline> 
line continuation (LPE)

** Description changed:

  [ Impact ]
  
  One feature of the sudoers file, is that it can define argument restrictions 
to
  a command, e.g. the caller is only allowed to run 'systemctl' with sudo iff it
  is invoked with specifically with the argument 'restart myapp.service', but no
  other arguments.
  
  sudo-rs will currently drop all argument restrictions that follow a
  `\<newline>`:
  
-       deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
-           restart myapp.service
+       deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
+           restart myapp.service
  
  In this example, the "restart myapp.service" restriction is dropped, and users
  can call systemctl with arbitrary commands. The visudo command will report
  "invalid sudoers file", however the rule is still committed to sudo-rs.
  
  The justification for backporting this fix comes from the fact that the error
  can lead to unintended consequences. An administrator may want to allow users
  to restart a system service, however if they incorrectly format the rule as
  shown above, they will unknowingly be granting users the ability to 
arbitrarily
  modify any service.
  
  This is fixed by the upload by making the following change to the sudo-rs's
  token parser:
  
  * If '\' is followed by '\n', check whether the the next char is a space
  * If it is a space, treat it as line continuation (emit a space)
  * Otherwise, reject() and treat it as the end token
  
  [ Test Plan ]
  
- * Detailed instructions on how to reproduce the bug.
- 
- * These should allow someone who is not familiar with the affected
-   package to reproduce the bug and verify that the updated package
-   fixes the problem.
- 
- * If other testing is appropriate to perform before landing this
-   update, this should also be described here.
- 
  Reproduce the bug
  -----------------
  
  * Assert that sudo-rs is the current sudo provider:
  
  sudo --version
  
  # Output:
  # sudo-rs 0.2.13-0ubuntu1
  # ~~~~~~~
  
  * Create a test user:
  sudo useradd -m -s /bin/bash resolute
  
  * Create a sudoers file with an affected rule that applies to the user:
  
  sudo tee /etc/sudoers.d/apt-update >/dev/null <<'EOF'
  resolute ALL=(root) NOPASSWD: /usr/bin/apt \
-     update
+     update
  EOF
  
  * Change to the test user:
  
  su resolute
  
  * Verify that the test user is not able to use sudo with any other
  command:
  
  resolute@ubuntu:~$ sudo echo hello
  
  # Output:
  # /etc/sudoers.d/apt-update:2:5: garbage at end of line
  #    update
  #    ^
  # sudo: I'm sorry resolute. I'm afraid I can't do that
  
  * Run 'apt' against an argument outside the rule restriction (remember we
-   should only be allowed to run 'sudo apt update'):
+   should only be allowed to run 'sudo apt update'):
  
  resolute@ubuntu:~$ sudo apt install cowsay
  
  # Output:
  # /etc/sudoers.d/apt-update:2:5: garbage at end of line
  #     update
  #     ^
  # Installing:
  #   cowsay
  #
  # Suggested packages:
  #   filters  cowsay-off
  #
  # Summary:
  #   Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 131
  #   Download size: 18.1 kB
  #   Space needed: 89.1 kB / 268 GB available
  
  * Verify that the command was executed successfully despite it being outside
-   the allowed arguments
+   the allowed arguments
  
  Testing proposed
  ----------------
  
  * Install the proposed sudo-rs:
  
  sudo apt install -t resolute-proposed rust-sudo-rs
  
  * Verify that the user "resolute" is no longer able to run any other command
-   with sudo than 'apt update':
+   with sudo than 'apt update':
  
  resolute@ubuntu:~$ sudo apt install cowsay
  
  # Output:
  # sudo: I'm sorry resolute. I'm afraid I can't do that
  
  resolute@ubuntu:~$ sudo apt update
  
  # Output:
  # Hit:1 http://security.ubuntu.com/ubuntu resolute-security InRelease
  # Hit:3 http://archive.ubuntu.com/ubuntu resolute InRelease
  # Hit:4 http://archive.ubuntu.com/ubuntu resolute-updates InRelease
  # Hit:5 http://archive.ubuntu.com/ubuntu resolute-backports InRelease
  # Hit:6 http://archive.ubuntu.com/ubuntu resolute-proposed InRelease
  
  [ Where problems could occur ]
  
  * The primary risks associated with this change is how it affects the generic
-   token parse function which is used by all token types, not just command line
-   lists. One example where this can have side-effects is when a token has
-   `ALLOW_ESCAPE = true`, there is a risk that two rules might be joined even
-   if they are separate rules.
+   token parse function which is used by all token types, not just command line
+   lists. One example where this can have side-effects is when a token has
+   `ALLOW_ESCAPE = true`, there is a risk that two rules might be joined even
+   if they are separate rules.
  
  * Previously broken sudoers files will now parse differently. For instance if
-   an administrator has specified `command + arg` in the sudoers file in the
-   affected way, that would previously have allowed all arguments. The argument
-   restriction is now honored correctly with the fix, which may be surprising,
-   even though it is technically correct.
+   an administrator has specified `command + arg` in the sudoers file in the
+   affected way, that would previously have allowed all arguments. The argument
+   restriction is now honored correctly with the fix, which may be surprising,
+   even though it is technically correct.
  
  [ Other Info ]
  
  * The bug was first marked as a believed vulnerability, however this was
-   decided not to be the case as it requires sudo access in the first place
-   to edit the sudoers file.
+   decided not to be the case as it requires sudo access in the first place
+   to edit the sudoers file.
  
  * This SRU is part of a larger merge proposal for 26.04.1
  
  * The fix is also natively part of the 0.2.14-1 upload to Stonking, currently
-   in proposed-migration
- 
+   in proposed-migration
  
  [ Original Description ]
  
  == Summary ==
  
    sudo-rs ≤ 0.2.13 (the version Ubuntu 26.04 ships as the default 
/usr/bin/sudo)
    silently drops argument restrictions and trailing rule content when a 
sudoers
    rule uses the standard `\<newline>` line-continuation syntax inside a
    SimpleCommand token. A narrow rule like:
  
        deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
            restart myapp.service
  
    is loaded as `(root) NOPASSWD: /usr/bin/systemctl` — i.e. systemctl with
    arbitrary args — granting local privilege escalation via any shell-escapable
    command (systemctl edit, find -exec, awk, etc.). visudo-rs flags the input
    ("garbage at end of line") and reports "invalid sudoers file", but sudo-rs
    commits the rule prefix to the active ruleset anyway.
  
    This has been disclosed to the upstream sudo-rs maintainers
    ([email protected]) on 2026-05-11. Filing here to also reach Ubuntu
    Security via Launchpad — the `[email protected]` email alias is currently
    bouncing for unknown-recipient `[email protected]` (separate 
alias-
    routing issue that probably needs fixing on Canonical's MTA).
  
    == Affected ==
  
    * Ubuntu 26.04 LTS shipping sudo-rs 0.2.13-0ubuntu1 as default /usr/bin/sudo
    * Ubuntu 25.10 (same sudo-rs default switch)
    * All sudo-rs releases v0.2.5 through v0.2.13. Earlier versions if parser 
code
      unchanged.
    * Other distros packaging sudo-rs are also affected when sudo-rs is used as
      the sudo backend.
  
    == Status of upstream fix ==
  
    * Parser-level fix exists: commit 7780f593 on `main` ("parser: implement 
line
      continuation (fix #1571)", authored 2026-04-27).
    * Fix is NOT in any release tag. Latest release v0.2.13 (2026-03-10) 
predates
      the fix and is the version Ubuntu 26.04 ships.
    * Upstream issue #1571 was filed and closed (2026-05-01) as a non-security
      parser bug; the LPE-class security implication of pre-fix releases does 
not
      appear to have been recognized in the report.
    * The parser fix is necessary but incomplete as defense-in-depth. The rule
      loader commits the rule prefix to the active ruleset BEFORE the rest of
      the rule is parsed, so any other parse error on a continuation line leaves
      an over-permissive prefix active. C sudo's yacc grammar discards the
      entire rule on any per-rule parse error — sudo-rs should match this.
    == Reproducer (Ubuntu 26.04, default sudo) ==
  
        sudo tee /etc/sudoers.d/repro <<'EOF'
        testuser ALL=(ALL) NOPASSWD: /bin/echo \
           hello world
        EOF
  
        sudo -l -U testuser
        # /etc/sudoers.d/repro:3:4: garbage at end of line
        #    hello world
        #    ^
        # ...
        # User testuser may run the following commands:
        #     (ALL) NOPASSWD: /usr/bin/echo
        #                     ^^^^^^^^^^^^^ argument restriction silently 
dropped
  
        sudo -u testuser sudo -n /bin/echo MALICIOUS_NOT_HELLO_WORLD
        # MALICIOUS_NOT_HELLO_WORLD   <-- succeeds, no password
  
    C sudo on the same input (Debian's /usr/bin/sudo 1.9.16p2) correctly rejects
    the rule.
  
    End-to-end kara→root LPE PoC is attached (`exploit.sh`). It creates a
    throwaway unprivileged user, plants a vulnerable sudoers.d rule (admin
    intent: lowpriv runs `/usr/bin/find /tmp/target` only), and demonstrates
    the unprivileged user reading /etc/shadow via `find -exec` running as root,
    then auto-cleans up. Lab-verified on Ubuntu 26.04 sudo-rs 0.2.13-0ubuntu1
    on 2026-05-11.
  
    == Suggested fix (defense-in-depth) ==
  
    The parser fix 7780f593 is the right immediate change. Additionally:
  
    1. Buffer the entire rule before commit. Parse a rule into a tentative AST
       in src/sudoers/parse.rs; only commit to the active ruleset after the
       full rule (across all continuation lines) parses successfully.
  
    2. Treat per-rule parse errors as fatal for that rule. When a rule's parse
       fails partway through, discard the partially-parsed prefix and resume
       with the next top-level statement.
  
    == Attachments ==
  
    * reproduce.sh — parser-level repro showing the abbreviated rule
    * exploit.sh — full LPE end-to-end demo (find -exec /bin/sh shell-escape);
      idempotent cleanup; gated behind --i-understand
    * run-on-lab.sh — multi-distro harness (we tested Debian/Alma/Fedora/Ubuntu)
    * Ubuntu-26.04.log — successful LPE transcript (find -exec ran as
      uid=0(root) gid=0(root); /etc/shadow first lines readable)
    * README.md — full writeup including affected-version matrix and the
      variant-B Cmnd_Alias analysis
  
    == References ==
  
    * Upstream: https://github.com/trifectatechfoundation/sudo-rs
    * Upstream issue #1571 (closed 2026-05-01, classified `bug`/non-security):
      https://github.com/trifectatechfoundation/sudo-rs/issues/1571
    * Fix commit 7780f593 (2026-04-27, "parser: implement line continuation"):
      https://github.com/trifectatechfoundation/sudo-rs/commit/7780f593
    * v0.2.13 release (does not contain the fix):
      https://github.com/trifectatechfoundation/sudo-rs/releases/tag/v0.2.13
    * C sudo behavior reference: https://www.sudo.ws/docs/man/sudoers.man/
    * Upstream disclosure: emailed [email protected] on 2026-05-11 — copy
      available on request.
  
    Filed by Kara Zajac, independent security researcher.
    github.com/KaraZajac · [email protected]

** Description changed:

  [ Impact ]
  
  One feature of the sudoers file, is that it can define argument restrictions 
to
  a command, e.g. the caller is only allowed to run 'systemctl' with sudo iff it
  is invoked with specifically with the argument 'restart myapp.service', but no
  other arguments.
  
  sudo-rs will currently drop all argument restrictions that follow a
  `\<newline>`:
  
        deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
            restart myapp.service
  
  In this example, the "restart myapp.service" restriction is dropped, and users
  can call systemctl with arbitrary commands. The visudo command will report
  "invalid sudoers file", however the rule is still committed to sudo-rs.
  
  The justification for backporting this fix comes from the fact that the error
  can lead to unintended consequences. An administrator may want to allow users
  to restart a system service, however if they incorrectly format the rule as
  shown above, they will unknowingly be granting users the ability to 
arbitrarily
  modify any service.
  
  This is fixed by the upload by making the following change to the sudo-rs's
  token parser:
  
  * If '\' is followed by '\n', check whether the the next char is a space
  * If it is a space, treat it as line continuation (emit a space)
  * Otherwise, reject() and treat it as the end token
  
  [ Test Plan ]
  
  Reproduce the bug
  -----------------
  
  * Assert that sudo-rs is the current sudo provider:
  
  sudo --version
  
  # Output:
  # sudo-rs 0.2.13-0ubuntu1
  # ~~~~~~~
  
  * Create a test user:
+ 
  sudo useradd -m -s /bin/bash resolute
  
  * Create a sudoers file with an affected rule that applies to the user:
  
  sudo tee /etc/sudoers.d/apt-update >/dev/null <<'EOF'
  resolute ALL=(root) NOPASSWD: /usr/bin/apt \
      update
  EOF
  
  * Change to the test user:
  
  su resolute
  
  * Verify that the test user is not able to use sudo with any other
  command:
  
  resolute@ubuntu:~$ sudo echo hello
  
  # Output:
  # /etc/sudoers.d/apt-update:2:5: garbage at end of line
  #    update
  #    ^
  # sudo: I'm sorry resolute. I'm afraid I can't do that
  
  * Run 'apt' against an argument outside the rule restriction (remember we
    should only be allowed to run 'sudo apt update'):
  
  resolute@ubuntu:~$ sudo apt install cowsay
  
  # Output:
  # /etc/sudoers.d/apt-update:2:5: garbage at end of line
  #     update
  #     ^
  # Installing:
  #   cowsay
  #
  # Suggested packages:
  #   filters  cowsay-off
  #
  # Summary:
  #   Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 131
  #   Download size: 18.1 kB
  #   Space needed: 89.1 kB / 268 GB available
  
  * Verify that the command was executed successfully despite it being outside
    the allowed arguments
  
  Testing proposed
  ----------------
  
  * Install the proposed sudo-rs:
  
  sudo apt install -t resolute-proposed rust-sudo-rs
  
  * Verify that the user "resolute" is no longer able to run any other command
    with sudo than 'apt update':
  
  resolute@ubuntu:~$ sudo apt install cowsay
  
  # Output:
  # sudo: I'm sorry resolute. I'm afraid I can't do that
  
  resolute@ubuntu:~$ sudo apt update
  
  # Output:
  # Hit:1 http://security.ubuntu.com/ubuntu resolute-security InRelease
  # Hit:3 http://archive.ubuntu.com/ubuntu resolute InRelease
  # Hit:4 http://archive.ubuntu.com/ubuntu resolute-updates InRelease
  # Hit:5 http://archive.ubuntu.com/ubuntu resolute-backports InRelease
  # Hit:6 http://archive.ubuntu.com/ubuntu resolute-proposed InRelease
  
  [ Where problems could occur ]
  
  * The primary risks associated with this change is how it affects the generic
    token parse function which is used by all token types, not just command line
    lists. One example where this can have side-effects is when a token has
    `ALLOW_ESCAPE = true`, there is a risk that two rules might be joined even
    if they are separate rules.
  
  * Previously broken sudoers files will now parse differently. For instance if
    an administrator has specified `command + arg` in the sudoers file in the
    affected way, that would previously have allowed all arguments. The argument
    restriction is now honored correctly with the fix, which may be surprising,
    even though it is technically correct.
  
  [ Other Info ]
  
  * The bug was first marked as a believed vulnerability, however this was
    decided not to be the case as it requires sudo access in the first place
    to edit the sudoers file.
  
  * This SRU is part of a larger merge proposal for 26.04.1
  
  * The fix is also natively part of the 0.2.14-1 upload to Stonking, currently
    in proposed-migration
  
  [ Original Description ]
  
  == Summary ==
  
    sudo-rs ≤ 0.2.13 (the version Ubuntu 26.04 ships as the default 
/usr/bin/sudo)
    silently drops argument restrictions and trailing rule content when a 
sudoers
    rule uses the standard `\<newline>` line-continuation syntax inside a
    SimpleCommand token. A narrow rule like:
  
        deploy ALL=(root) NOPASSWD: /usr/bin/systemctl \
            restart myapp.service
  
    is loaded as `(root) NOPASSWD: /usr/bin/systemctl` — i.e. systemctl with
    arbitrary args — granting local privilege escalation via any shell-escapable
    command (systemctl edit, find -exec, awk, etc.). visudo-rs flags the input
    ("garbage at end of line") and reports "invalid sudoers file", but sudo-rs
    commits the rule prefix to the active ruleset anyway.
  
    This has been disclosed to the upstream sudo-rs maintainers
    ([email protected]) on 2026-05-11. Filing here to also reach Ubuntu
    Security via Launchpad — the `[email protected]` email alias is currently
    bouncing for unknown-recipient `[email protected]` (separate 
alias-
    routing issue that probably needs fixing on Canonical's MTA).
  
    == Affected ==
  
    * Ubuntu 26.04 LTS shipping sudo-rs 0.2.13-0ubuntu1 as default /usr/bin/sudo
    * Ubuntu 25.10 (same sudo-rs default switch)
    * All sudo-rs releases v0.2.5 through v0.2.13. Earlier versions if parser 
code
      unchanged.
    * Other distros packaging sudo-rs are also affected when sudo-rs is used as
      the sudo backend.
  
    == Status of upstream fix ==
  
    * Parser-level fix exists: commit 7780f593 on `main` ("parser: implement 
line
      continuation (fix #1571)", authored 2026-04-27).
    * Fix is NOT in any release tag. Latest release v0.2.13 (2026-03-10) 
predates
      the fix and is the version Ubuntu 26.04 ships.
    * Upstream issue #1571 was filed and closed (2026-05-01) as a non-security
      parser bug; the LPE-class security implication of pre-fix releases does 
not
      appear to have been recognized in the report.
    * The parser fix is necessary but incomplete as defense-in-depth. The rule
      loader commits the rule prefix to the active ruleset BEFORE the rest of
      the rule is parsed, so any other parse error on a continuation line leaves
      an over-permissive prefix active. C sudo's yacc grammar discards the
      entire rule on any per-rule parse error — sudo-rs should match this.
    == Reproducer (Ubuntu 26.04, default sudo) ==
  
        sudo tee /etc/sudoers.d/repro <<'EOF'
        testuser ALL=(ALL) NOPASSWD: /bin/echo \
           hello world
        EOF
  
        sudo -l -U testuser
        # /etc/sudoers.d/repro:3:4: garbage at end of line
        #    hello world
        #    ^
        # ...
        # User testuser may run the following commands:
        #     (ALL) NOPASSWD: /usr/bin/echo
        #                     ^^^^^^^^^^^^^ argument restriction silently 
dropped
  
        sudo -u testuser sudo -n /bin/echo MALICIOUS_NOT_HELLO_WORLD
        # MALICIOUS_NOT_HELLO_WORLD   <-- succeeds, no password
  
    C sudo on the same input (Debian's /usr/bin/sudo 1.9.16p2) correctly rejects
    the rule.
  
    End-to-end kara→root LPE PoC is attached (`exploit.sh`). It creates a
    throwaway unprivileged user, plants a vulnerable sudoers.d rule (admin
    intent: lowpriv runs `/usr/bin/find /tmp/target` only), and demonstrates
    the unprivileged user reading /etc/shadow via `find -exec` running as root,
    then auto-cleans up. Lab-verified on Ubuntu 26.04 sudo-rs 0.2.13-0ubuntu1
    on 2026-05-11.
  
    == Suggested fix (defense-in-depth) ==
  
    The parser fix 7780f593 is the right immediate change. Additionally:
  
    1. Buffer the entire rule before commit. Parse a rule into a tentative AST
       in src/sudoers/parse.rs; only commit to the active ruleset after the
       full rule (across all continuation lines) parses successfully.
  
    2. Treat per-rule parse errors as fatal for that rule. When a rule's parse
       fails partway through, discard the partially-parsed prefix and resume
       with the next top-level statement.
  
    == Attachments ==
  
    * reproduce.sh — parser-level repro showing the abbreviated rule
    * exploit.sh — full LPE end-to-end demo (find -exec /bin/sh shell-escape);
      idempotent cleanup; gated behind --i-understand
    * run-on-lab.sh — multi-distro harness (we tested Debian/Alma/Fedora/Ubuntu)
    * Ubuntu-26.04.log — successful LPE transcript (find -exec ran as
      uid=0(root) gid=0(root); /etc/shadow first lines readable)
    * README.md — full writeup including affected-version matrix and the
      variant-B Cmnd_Alias analysis
  
    == References ==
  
    * Upstream: https://github.com/trifectatechfoundation/sudo-rs
    * Upstream issue #1571 (closed 2026-05-01, classified `bug`/non-security):
      https://github.com/trifectatechfoundation/sudo-rs/issues/1571
    * Fix commit 7780f593 (2026-04-27, "parser: implement line continuation"):
      https://github.com/trifectatechfoundation/sudo-rs/commit/7780f593
    * v0.2.13 release (does not contain the fix):
      https://github.com/trifectatechfoundation/sudo-rs/releases/tag/v0.2.13
    * C sudo behavior reference: https://www.sudo.ws/docs/man/sudoers.man/
    * Upstream disclosure: emailed [email protected] on 2026-05-11 — copy
      available on request.
  
    Filed by Kara Zajac, independent security researcher.
    github.com/KaraZajac · [email protected]

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2152220

Title:
  [SRU] sudo-rs ≤ 0.2.13: silent drop of argument restrictions on
  \<newline> line continuation (LPE)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/rust-sudo-rs/+bug/2152220/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to