[PR #2843] fix: avoid false ServerUserNotAllowedInSudoers on GCE (google-sudoers group) #2975

Open
opened 2026-10-14 21:06:36 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amnezia-client/pull/2843
Author: @roquie
Created: 7/18/2026
Status: 🔄 Open

Base: dev ← Head: fix/sudo-check-group-name-false-positive


📝 Commits (1)

  • d69e29a fix: silence group listing in sudo check to avoid false ServerUserNotAllowedInSudoers

📊 Changes

1 file changed (+1 additions, -1 deletions)

View changed files

📝 client/server_scripts/check_user_in_sudo.sh (+1 -1)

📄 Description

Problem

check_user_in_sudo.sh reports the login user as not being in sudoers
(client surfaces Error 209 — ServerUserNotAllowedInSudoers) even when the
user has fully working passwordless sudo. This reproduces on any Google Cloud
(GCE)
VM.

Root cause

The membership test is written as:

if [ "$CUR_USER" = "root" ] || ( groups "$CUR_USER" | grep -E '\<(sudo|wheel)\>' ); then

grep here is used only as a boolean for the if, but without -q it also
prints the matching line — i.e. the user's entire group list — to stdout.

The client scans the combined script output for the word \bsudoers\b to decide
the sudo check failed (installController.cpp). On GCE the guest agent adds every
managed user to the google-sudoers group. \bsudoers\b matches the
sudoers inside google-sudoers (- is a word boundary), so the check is
treated as failed → Error 209.

So a correctly-configured sudo user (user ALL=(ALL:ALL) NOPASSWD:ALL, member of
sudo) is rejected purely because one of its group names happens to contain the
substring sudoers. Only root works, because the root branch skips the
groups call entirely.

Fix

Add -q to the membership grep so it stays a pure exit-code test and stops
leaking the group list into the output the client parses:

if [ "$CUR_USER" = "root" ] || ( groups "$CUR_USER" | grep -qE '\<(sudo|wheel)\>' ); then

One character (-q); behaviour of the if is unchanged. The sudo probes below
already redirect stdout to /dev/null, so after this change the script emits no
spurious output for a valid sudo user.

Verification

On a GCE Ubuntu 22.04 VM with a sudo-group user that has passwordless sudo:

  • Before: running the script prints user : ... sudo ... google-sudoers, which
    matches the client's sudoers scan → Error 209.
  • After: the script produces empty output → the sudo check passes and install
    proceeds. Also confirmed root and non-GCE users are unaffected.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amnezia-client/pull/2843 **Author:** [@roquie](https://github.com/roquie) **Created:** 7/18/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `fix/sudo-check-group-name-false-positive` --- ### 📝 Commits (1) - [`d69e29a`](https://github.com/amnezia-vpn/amnezia-client/commit/d69e29a3fc2e235fb61cbb7ea42b175425d0664c) fix: silence group listing in sudo check to avoid false ServerUserNotAllowedInSudoers ### 📊 Changes **1 file changed** (+1 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `client/server_scripts/check_user_in_sudo.sh` (+1 -1) </details> ### 📄 Description ## Problem `check_user_in_sudo.sh` reports the login user as **not** being in sudoers (client surfaces **Error 209 — ServerUserNotAllowedInSudoers**) even when the user has fully working passwordless sudo. This reproduces on any **Google Cloud (GCE)** VM. ### Root cause The membership test is written as: ```sh if [ "$CUR_USER" = "root" ] || ( groups "$CUR_USER" | grep -E '\<(sudo|wheel)\>' ); then ``` `grep` here is used only as a boolean for the `if`, but **without `-q`** it also prints the matching line — i.e. the user's **entire group list** — to stdout. The client scans the combined script output for the word `\bsudoers\b` to decide the sudo check failed (`installController.cpp`). On GCE the guest agent adds every managed user to the **`google-sudoers`** group. `\bsudoers\b` matches the `sudoers` inside `google-sudoers` (`-` is a word boundary), so the check is treated as failed → Error 209. So a correctly-configured sudo user (`user ALL=(ALL:ALL) NOPASSWD:ALL`, member of `sudo`) is rejected purely because one of its group names happens to contain the substring `sudoers`. Only `root` works, because the `root` branch skips the `groups` call entirely. ## Fix Add `-q` to the membership `grep` so it stays a pure exit-code test and stops leaking the group list into the output the client parses: ```sh if [ "$CUR_USER" = "root" ] || ( groups "$CUR_USER" | grep -qE '\<(sudo|wheel)\>' ); then ``` One character (`-q`); behaviour of the `if` is unchanged. The `sudo` probes below already redirect stdout to `/dev/null`, so after this change the script emits no spurious output for a valid sudo user. ## Verification On a GCE Ubuntu 22.04 VM with a `sudo`-group user that has passwordless sudo: - **Before:** running the script prints `user : ... sudo ... google-sudoers`, which matches the client's `sudoers` scan → Error 209. - **After:** the script produces empty output → the sudo check passes and install proceeds. Also confirmed `root` and non-GCE users are unaffected. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#2975
No description provided.