Pourquoi ne pas utiliser la combinaison de l'action -execdir
find en utilisant -exec
non?
Lorsque j'exécute la commande ci-dessous, le message d'invite suivant s'affiche:
/path/to/currentDir/$ find . -type f -name 'partOfFileNames*' -execdir rm -- {} +
find: The current directory is included in the PATH environment variable, which is insecure
in combination with the -execdir action of find. Please remove the current directory
from your $PATH (that is, remove "." or leading or trailing colons)
Qu'est-ce qui a pu faire apparaître cette invite?
L'action -execdir
exécute votre commande à partir du répertoire contenant le ou les fichiers trouvés. Lorsque $PATH
contient des chemins relatifs, tels que .
ou tout ce qui ne commence pas par /
, -execdir
n'est pas sécurisé car un répertoire dans lequel un fichier est trouvé (ou un autre répertoire résolu par rapport à celui-ci) pourrait également contenir un exécutable du même nom que celui que vous essayez d’exécuter. Ce fichier exécutable potentiellement non fiable serait alors exécuté.
Cela pourrait être délibérément exploité par un autre utilisateur pour vous faire exécuter son programme, ce qui pourrait être dommageable ou violer la sécurité des données, au lieu du programme que vous essayez d'exécuter. Ou, moins souvent, le mauvais programme pourrait être exécuté par inadvertance, même sans que personne ne tente de résoudre le problème.
Si tout ce qui se trouve dans votre variable d’environnement PATH
correspond à un chemin absolu, cette erreur ne doit pas se produire, même si le répertoire dans lequel vous recherchez et où -execdir
ing est est contenu dans PATH
. (J'ai vérifié que cela fonctionne.) Si vous pensez que vous n'avez pas de répertoires relatifs dans $PATH
mais que vous rencontrez toujours cette erreur, veuillez mettre à jour votre question avec les détails, y compris la sortie de echo "$PATH"
.
Comme exemple de ce qui pourrait mal tourner, supposons:
.
dans son $PATH
car elle veut pouvoir exécuter des programmes dans le répertoire dans lequel elle est cd
'd, sans avoir à ajouter leur nom avec ./
./home/eve/shared
avec Alice..c
que Eve a partagés avec elle.Alors Alice court:
find ~eve/shared -name \*.c -execdir wc {} \;
Malheureusement pour Alice, Eve a créé son propre script, l'a nommée wc
, l'a défini comme exécutable (chmod +x
) et l'a placé clandestinement dans l'un des répertoires sous /home/eve/shared
. Le script d'Eve ressemble à ceci:
#!/bin/sh
/usr/bin/wc "$@"
do_evil # Eve replaces this command with whatver evil she wishes to do
Ainsi, lorsque Alice utilise find
avec -execdir
pour exécuter wc
sur les fichiers partagés par Eve, et que les fichiers du répertoire se trouvent dans le même répertoire que le script personnalisé wc
d'Eve, Eve wc
s'exécute - avec tous les privilèges d'Alice!
(Étant rusée, Eve a fait en sorte que son script wc
serve de wrapper pour le système wc
, de sorte que Alice ne saura même pas que quelque chose s'est mal passé, c'est-à-dire que do_evil
a été exécuté. Cependant, des variations plus simples et plus sophistiquées sont possibles.)
find
l'empêche.find
évite ce problème de sécurité en refusant d'effectuer l'action -execdir
lorsque $PATH
contient un répertoire relatif.
find
offre deux messages de diagnostic en fonction de la situation spécifique.
Si .
est dans $PATH
, alors (comme vous l'avez vu), il est écrit:
find: The current directory is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove the current directory from your $PATH (that is, remove "." or leading or trailing colons)
Il contient probablement un message spécial pour le cas .
, car il est particulièrement courant.
Si un chemin relatif autre que .
-- dit, foo
- apparaît dans $PATH
et que vous exécutez find
avec -execdir
, il indique:
find: The relative path `foo' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove that entry from $PATH
$PATH
.Le risque d'avoir .
ou d'autres chemins relatifs dans $PATH
est particulièrement accru lorsque vous utilisez un utilitaire qui modifie automatiquement le répertoire. C'est pourquoi find
ne vous laissera pas utiliser -execdir
dans cette situation.
Mais avoir des chemins relatifs, en particulier .
, dans votre $PATH
est intrinsèquement risqué et il vaut mieux éviter de toute façon. Considérez la situation fictive dans l'exemple ci-dessus. Supposons qu'au lieu d'exécuter find
, Alice mette simplement cd
s à ~eve/shared/blah
et exécute wc *.c
. Si blah
contient le script wc
d'Eve, do_evil
s'exécute en tant que Alice.
Il y a beaucoup d'informations détaillées ici . Une autre excellente référence est ici . Pour citer la première référence:
L'option -execdir est une option plus moderne introduite dans GNU. Find est une tentative de création d'une version plus sûre de -exec. Il a la même sémantique que -exec avec deux améliorations importantes:
Il fournit toujours le chemin absolu du fichier (utiliser un chemin relatif vers un fichier est vraiment dangereux en cas de -exec).
En plus de fournir un chemin absolu, il vérifie également la sécurité de la variable PATH (si dot est présent dans la variable env. PATH, vous pouvez extraire le fichier exécutable à partir du mauvais répertoire).
De la deuxième référence:
L’action ‘-execdir’ refuse de faire quoi que ce soit si le répertoire en cours est inclus dans la variable d’environnement $ PATH. Cela est nécessaire car ‘-execdir’ exécute des programmes dans le même répertoire où se trouvent les fichiers. En général, un tel répertoire peut être accessible en écriture à des utilisateurs non fiables. Pour des raisons similaires, "-execdir" ne permet pas à "{}" d'apparaître dans le nom de la commande à exécuter.
Le problème principal concerne la valeur de la variable système PATH
qui contient des dossiers relatifs. Ainsi, pour des raisons de sécurité, la commande find
ne vous permettra pas d’exécuter des fichiers binaires, car elle pourrait éventuellement exécuter de mauvais programmes.
Ainsi, par exemple, si vous avez votre répertoire actuel dans votre variable PATH conformément à l’avertissement, vous obtenez:
Le répertoire en cours est inclus dans la variable d’environnement PATH.
et vous exécuterez votre commande:
find . -type f -name 'partOfFileNames*' -execdir rm -- {} +
si vous avez un script local (rm
avec des indicateurs exécutables) contenant rm -fr /
, il peut supprimer tous vos fichiers, car au lieu d'exécuter le /bin/rm
attendu, vous exécuterez rm
à partir du répertoire en cours, ce qui signifie que ce n'est probablement pas ce que vous vouliez .
En remarque, c'est un problème connu dans Travis CI ( GH # 2811 ) lorsqu'il échoue avec l'erreur:
find: le chemin relatif `./node_modules/.bin 'est inclus dans la variable d'environnement PATH, qui n'est pas sécurisée en combinaison avec l'action -execdir de find. Veuillez supprimer cette entrée de $ PATH
La solution consiste donc à supprimer l’entrée concernée de la variable PATH, par exemple.
PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'`
tel que proposé par drogus . La progression de ce bogue peut être suivie à partir de GH # 4862 .
Voici la solution de contournement de la version Bash:
PATH=${PATH//:\.\/node_modules\/\.bin/}
Exemple d'utilisation (passage de PATH
filtré à une commande spécifique):
env PATH=${PATH//:\.\/node_modules\/\.bin/} find . -type f
xargs
et bash -c cd
solution de contournement
OK, j'abandonne:
find . -type f |
xargs -I '{}' bash -c 'cd "$(dirname "{}")" && pwd && echo "$(basename "{}")"'
sed
solution de contournement
Un peu moins sympa que la solution précédente:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" find . -execdir echo '{}' \;
Un test case:
[ "$(printf '/a/b::c/d:/e/f\n' | sed -E 's/(^|:)[^\/][^:]*//g')" = '/a/b:/e/f' ] || echo fail
Pour rename
en particulier, vous pouvez également contourner certains Perl regex-fu: https://stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in- linux/54163971 # 54163971
RTFS espère écraser
Pour ceux qui espèrent qu’il existe un moyen d’ignorer l’opinion exprimée par find
, laissez-moi l’écraser avec une source:
À partir de là, nous constatons qu’il semble impossible de désactiver la vérification du chemin.
La règle exacte à vérifier est la suivante: échec si la PATH
est vide ou ne commence pas par /
.