To produce, run `sudo -u user bash -c 'declare -p PATH'`. The value of PATH would begin with this: '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin' This is unintuitive and is inconsistent with the default value of ROOTPATH which is '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin'. If one would create wrappers or different versions of a binary in /usr/local/*bin, they would expect them to execute first regardless if sudo is being used or not. The code responsible for this can be found in sudo's ebuild: set_secure_path() { # FIXME: secure_path is a compile time setting. using PATH or # ROOTPATH is not perfect, env-update may invalidate this, but until it # is available as a sudoers setting this will have to do. einfo "Setting secure_path ..." # first extract the default ROOTPATH from build env SECURE_PATH=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env; echo "${ROOTPATH}") case "${SECURE_PATH}" in */usr/sbin*) ;; *) SECURE_PATH=$(unset PATH; . "${EPREFIX}"/etc/profile.env; echo "${PATH}") ;; esac if [[ -z ${SECURE_PATH} ]] ; then ewarn " Failed to detect SECURE_PATH, please report this" fi # then remove duplicate path entries cleanpath() { local newpath thisp IFS=: for thisp in $1 ; do if [[ :${newpath}: != *:${thisp}:* ]] ; then newpath+=:${thisp} else einfo " Duplicate entry ${thisp} removed..." fi done SECURE_PATH=${newpath#:} } cleanpath /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin${SECURE_PATH:+:${SECURE_PATH}} # finally, strip gcc paths #136027 rmpath() { local e newpath thisp IFS=: for thisp in ${SECURE_PATH} ; do for e ; do [[ ${thisp} == ${e} ]] && continue 2 ; done newpath+=:${thisp} done SECURE_PATH=${newpath#:} } rmpath '*/gcc-bin/*' '*/gnat-gcc-bin/*' '*/gnat-gcc/*' einfo "... done" }
The set_secure_path function can be made simpler like this: set_secure_path() { einfo "Setting secure_path ..." SECURE_PATH=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env; echo "${ROOTPATH}") [[ ${SECURE_PATH} != */usr/sbin* ]] && SECURE_PATH=$(unset PATH; . "${EPREFIX}"/etc/profile.env; echo "${PATH}") local IFS=: __ set -- /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /opt/bin ${SECURE_PATH} SECURE_PATH= for __; do case $__ in ''|*/gcc-bin/*|*/gnat-gcc-bin/*|*/gnat-gcc/*) ;; *) [[ :${SECURE_PATH}: != *:"$__":* ]] && SECURE_PATH+=:$__ ;; esac done SECURE_PATH=${SECURE_PATH#:} einfo "... done" }
Not up to me but note that, if unspecified, sudo upstream also starts with /bin and doesn't even add /usr/local at all when using optional --with-secure-path.
As I've tested earlier, the value of PATH when secure-path is disabled, is set to the PATH of calling environment (as root). I only haven't tested it as a user. But point is if there's going be a default value for PATH set through --with-secure-path, better just base it on ROOTPATH.
Here's an example output of sudo with secure-path disabled. # declare -p PATH; sudo -u (user) bash -c 'declare -p PATH' declare -x PATH="/home/base/.gem/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/lib/llvm/11/bin:/write/sbin:/write/bin:/usr/games/bin" declare -x PATH="/home/base/.gem/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/lib/llvm/11/bin:/write/sbin:/write/bin:/usr/games/bin As you can see, bash not having the -l option just inherits the value of the calling environment's PATH where /usr/local/*bin come first. This idea that sudo upstream starts with /bin needs to be verified as it might simply be caused by the shell or something else not exactly sudo.
I just found out that secure_path can be configured via /etc/sudoers thanks to ggabriel. I didn't see it in my first attempt to grep /etc, and the configuration was found in /etc/sudoers.dist. The phrase " but until it is available as a sudoers setting this will have to do." also made me think the configuration wasn't available. Anyway this is my final solution for this, but I'm not closing this bug yet since I believe even this compile-time default should still be corrected. ---------- /etc/portage/bashrc ---------- if [[ ${CATEGORY} == app-admin && ${PN} == sudo ]]; then set_secure_path() { SECURE_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin } fi ---------- /usr/local/sbin ---------- #!/bin/bash set -f update_secure_path() { local secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin local extra_path=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env; echo "${ROOTPATH}") if [[ ${extra_path} != */usr/sbin* ]]; then extra_path=$(unset PATH; . "${EPREFIX}"/etc/profile.env; echo "${PATH}") fi local IFS=: __ set -- ${extra_path} for __; do case $__ in ''|*/gcc-bin/*|*/gnat-gcc-bin/*|*/gnat-gcc/*) ;; *) [[ :${secure_path}: != *:"$__":* ]] && secure_path+=:$__ ;; esac done printf 'Defaults secure_path="%s"\n' "${secure_path}" > /etc/sudoers.d/secure_path } function main { local PATH=${PATH}:/lib/rc/bin einfo "Calling /usr/sbin/env-update ... " /usr/sbin/env-update eend "$?" || return einfo "Updating /etc/sudoers.d/secure_path ... " update_secure_path eend "$?" } main
By the way please don't make env-update updating /etc/sudoers.d/secure_path a hardcoded solution as it would be difficult to customize. Maybe just save it in /etc/sudoers.secure_path instead and allow user to include it if they like (or if enabled by default, allow them to disable).
I created a request to make env-update call post-update scripts in https://bugs.gentoo.org/777393. If this gets granted, app-admin/sudo can install its own post-update script that updates /etc/sudoers.d/secure_path. I like the method since I can easily customize the script, or disable it by remove the exec bit if I want to.
The bug has been closed via the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=45fd59bda6eaec275f44ecba6cd5b8a29cfb535f commit 45fd59bda6eaec275f44ecba6cd5b8a29cfb535f Author: Mike Gilbert <floppym@gentoo.org> AuthorDate: 2021-03-21 15:02:51 +0000 Commit: Mike Gilbert <floppym@gentoo.org> CommitDate: 2021-03-21 15:06:06 +0000 app-admin/sudo: re-order default secure_path Match the order from baselayout. Closes: https://bugs.gentoo.org/777267 Signed-off-by: Mike Gilbert <floppym@gentoo.org> app-admin/sudo/{sudo-1.9.6_p1.ebuild => sudo-1.9.6_p1-r1.ebuild} | 3 ++- app-admin/sudo/sudo-9999.ebuild | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=786ecd5f4c84942af2dc178c2ac9fcaab224a7c9 commit 786ecd5f4c84942af2dc178c2ac9fcaab224a7c9 Author: Mike Gilbert <floppym@gentoo.org> AuthorDate: 2021-03-21 15:09:41 +0000 Commit: Mike Gilbert <floppym@gentoo.org> CommitDate: 2021-03-21 15:09:41 +0000 app-admin/sudo: remove obsolete comments The built-in secure_path should be viewed as a reasonable fallback. The sysadmin may in fact customize it via sudoers at runtime. Also drop the useless einfo output: this function takes a fraction of a second to complete, and there is no need for a status message. Bug: https://bugs.gentoo.org/777267 Signed-off-by: Mike Gilbert <floppym@gentoo.org> app-admin/sudo/sudo-1.9.6_p1-r1.ebuild | 7 ------- app-admin/sudo/sudo-9999.ebuild | 7 ------- 2 files changed, 14 deletions(-)