Le rôle GCS « lecture seule » qui expose la liste complète de vos fichiers
Sur un bucket public, objectViewer autorise le LIST anonyme complet là où legacyObjectReader le bloque. La différence tient à une permission. Testé en curl.
Un rôle GCS « lecture seule » peut exposer la liste complète de vos fichiers en anonyme. Je l'ai testé, GET et LIST à l'appui, et le rôle le plus récent est le plus bavard.

Le test
Un bucket servant des fichiers publics par URL directe. Deux façons de donner la lecture à allUsers :
roles/storage.objectViewer, le rôle moderne recommandé partout :
GET https://storage.googleapis.com/BUCKET/objet.jpg → 200
LIST https://storage.googleapis.com/storage/v1/b/BUCKET/o → 200, la liste complète
roles/storage.legacyObjectReader, le rôle « legacy » que la console décourage :
GET https://storage.googleapis.com/BUCKET/objet.jpg → 200
LIST https://storage.googleapis.com/storage/v1/b/BUCKET/o → 403
Reproduisez-le vous-même, sans authentification :
curl -s "https://storage.googleapis.com/storage/v1/b/VOTRE_BUCKET/o?maxResults=10"
Si cette commande renvoie du JSON avec vos noms d'objets, n'importe qui sur Internet a la même vue.
La différence : une permission
objectViewer contient storage.objects.list. legacyObjectReader ne contient que storage.objects.get. Tout est là.
Pour un usage interne, lister est un confort. Accordé à allUsers, c'est une capacité d'énumération : la liste des clés révèle souvent des IDs utilisateurs, des noms de documents, des dates, des structures internes. Si vos URLs contiennent un UUID « impossible à deviner », l'obscurité de l'URL était peut-être votre seule barrière : le LIST anonyme la supprime d'un coup.
Les trois réflexes
Pour du public servi par URL directe : legacyObjectReader. Le préfixe « legacy » décourage, à tort. C'est exactement le rôle qui donne le GET sans le LIST. Le rôle le plus récent n'est pas le plus sûr, ici c'est l'inverse.
Pour tout bucket qui ne doit jamais être public : publicAccessPrevention: enforced. C'est un verrou volontaire : désactivable par qui a les droits (sauf policy d'organisation héritée), mais il transforme une erreur d'IAM silencieuse en action délibérée et auditée.
Dans la checklist d'audit : le curl anonyme. GET sur un objet connu, LIST sur le bucket, sans credentials. Dix secondes, et c'est le seul test qui reflète ce que voit réellement un inconnu, indépendamment de ce que la console affiche.
À retenir
objectViewerpourallUsers= GET 200 et LIST 200 : liste complète du bucket exposée.legacyObjectReader= GET 200 et LIST 403 : la seule différence eststorage.objects.list.- Public par URL directe : legacy. Jamais public :
publicAccessPreventionen verrou volontaire. Et dans les deux cas : tester en anonyme avec curl.
Vous avez déjà lancé le LIST anonyme sur vos propres buckets ?