Le SecurityManager va disparaître de Java : quelles conséquences pour vous ?
15 juin 2023
0 minutes de lectureLe package java.security de la bibliothèque Java Development Kit (JDK) est l’un des plus importants, mais malgré des mises à jour régulières, il reste largement sous-utilisé.
Face à l’importance croissante accordée aux frameworks de cybersécurité, notamment au zero trust, les développeurs Java doivent se familiariser avec les bibliothèques de sécurité de Java SE.
Comme tous les domaines de l’informatique, la cybersécurité est par nature imprévisible. Après tout, elle doit suivre les dernières tendances de la cybercriminalité. La suppression du SecurityManager est l’une des évolutions — ou régressions, selon les avis — de la sécurité Java. Mais pourquoi est-ce important ? Y a-t-il vraiment lieu de s’inquiéter ? Cet article vous aidera à répondre à ces questions.
Pourquoi la sécurité Java est nécessaire
Java est considéré comme un langage intrinsèquement sûr, grâce à des fonctionnalités comme la machine virtuelle Java (JVM), la gestion de la mémoire, une gestion robuste des exceptions et l’absence de pointeurs explicites (*c’est-à-dire* de références). Malgré ces fonctionnalités intégrées, les utilisateurs peuvent être moins enclins à l’utiliser en raison de vulnérabilités très médiatisées, comme Log4j.
Il est toutefois important de noter que bon nombre de ces vulnérabilités sont liées aux produits, à des tiers ou aux développeurs (*c’est-à-dire* au fait que les développeurs n’écrivent pas de code sécurisé). Java a certes connu des vulnérabilités propres au JDK, comme l’exposition de données sensibles et des problèmes de désérialisation, mais beaucoup ont été corrigées ou sont en cours de correction. Par exemple, JDK 20 a été publié avec une optimisation améliorée des intrinsèques cryptographiques pour certaines plateformes.
Bien sûr, cela ne signifie pas que Java gère automatiquement tous les aspects de la sécurité. Il incombe toujours aux développeurs d’écrire du code sécurisé. Cela implique de comprendre les capacités et les limites des packages de sécurité intégrés à Java. Il est souvent inutile de recourir à des API et bibliothèques de sécurité tierces.
Le JDK comprend des fonctionnalités de sécurité des plateformes, de cryptographie, de contrôle d’accès et d’authentification, de communication et d’infrastructure à clé publique. Vous pouvez découvrir toutes ces fonctionnalités dans le Guide du développeur sur la sécurité officiel.
Améliorer une plateforme ou un outil implique aussi de supprimer les fonctionnalités non sécurisées ou superflues. Le SecurityManager est l’une d’entre elles.
Qu’est-ce que le SecurityManager ?
Le SecurityManager de Java a été conçu comme une autorité fédérée pour la sécurité des applications. Il sert (ou servait) à définir des politiques de sécurité et des règles pour les applications Java, afin de garantir la sécurité de certaines opérations. La classe Java.lang.SecurityManager existe depuis JDK 1.0.
À l’origine, SecurityManager était une classe abstraite. Il a ensuite cessé d’être abstrait afin d’en faciliter l’accès et l’utilisation. Même s’il était possible d’instancier un nouvel objet SecurityManager pour chaque classe, cela ne respectait pas les bonnes pratiques de codage Java. Il fallait plutôt définir une propriété système au lancement de l’application :
Vous pouviez également le définir en instanciant directement un objet SecurityManager, puis en le configurant comme propriété système depuis votre code :
La propriété système SecurityManager pouvait ensuite être récupérée dans une autre classe à l’aide du code suivant :
La classe SecurityManager se compose principalement d’un ensemble de méthodes de vérification. Elles contrôlent si certaines opérations de l’application sont autorisées à accéder à des ressources données. La méthode checkPermission est sans doute la plus utile : elle vérifie si une opération est autorisée à utiliser certaines ressources. Les politiques d’autorisation sont définies et contrôlées à l’aide des sous-classes (directes et indirectes) de la classe java.security.Permission.
En somme, SecurityManager simplifie la sécurisation des applications Java et est facile à utiliser. Alors, pourquoi a-t-il été déprécié ?
L’histoire du SecurityManager
Chaque nouvelle version de Java SE apporte de nombreuses améliorations, dont beaucoup sont issues du Java Community Process (JCP) et des propositions d’amélioration du JDK. Ces dernières sont la principale raison pour laquelle la suppression du SecurityManager est prévue.
À ses débuts, la classe SecurityManager servait principalement à définir des politiques de sécurité pour les applets, qui ne sont plus prises en charge par la plupart des plateformes web. Le navigateur web fournissait le SecurityManager de chaque applet.
L’API Java Applet a finalement été dépréciée avec la sortie de Java 9 en 2017, conformément à JEP289. Toutefois, elle n’était pas dépréciée en vue de sa suppression. Avec la sortie de Java SE 17, l’API Applet et les classes associées ont finalement été dépréciées en vue de leur suppression, comme le précise JEP398.
Cette démarche visait à faire évoluer le langage de programmation et son API. Les API héritées comme celles-ci étaient devenues si obsolètes qu’elles n’avaient plus leur place dans les futures versions du JDK. Le SecurityManager étant étroitement lié à l’architecture des applets, il est supprimé pour des raisons similaires.
Pourquoi le SecurityManager est-il supprimé ?
Aujourd’hui, le SecurityManager n’est plus le moyen le plus efficace de sécuriser le code Java côté client et côté serveur. En fait, la plateforme Java fournit des mécanismes plus efficaces pour ces tâches.
Chaque nouvelle version du JDK vise à offrir une sécurité intrinsèque supérieure à la précédente. De nombreuses vulnérabilités accidentelles que le SecurityManager cherche à corriger ne sont donc plus pertinentes.
Comme les fonctionnalités du SecurityManager n’ont pas évolué depuis dix ans, il ne peut pas contrer nombre des menaces, faiblesses et vulnérabilités courantes auxquelles les programmeurs sont aujourd’hui confrontés. En réalité, il n’a jamais été conçu pour résoudre les problèmes de sécurité actuels. Pourtant, tant qu’il existe, il doit être testé avec toutes les classes auxquelles il est lié.
Cela représente une charge de maintenance inutile. Le temps et les efforts consacrés à maintenir le SecurityManager pourraient servir à tester des classes et des fonctionnalités aujourd’hui plus utiles aux développeurs. Si l’intuitivité est l’un des principaux atouts de son architecture, sa configuration peut être complexe.
Pour rappel, le SecurityManager se compose principalement d’un ensemble de méthodes de vérification. Par exemple, CheckPermission est une fonctionnalité de sécurité utile qui vous permet de valider les autorisations d’une application ou d’un système à l’aide de votre fichier de politiques Java. Une politique autorisant le code d’une application à lire un répertoire se présenterait ainsi :
Cette configuration autorise la base de code (chaque fichier de classe) située dans file:/home/source/ à accéder à toutes les ressources du répertoire relatif files. Pour vérifier une autorisation précise, vous devez instancier une sous-classe de la classe `Permission` ou `BasicPermission`. Celle-ci représente l’ensemble des autorisations définies dans le fichier de politiques. Dans ce cas, il s’agit de l’objet FilePermission :
Comme les politiques dépendent souvent du contexte, vous devez récupérer un objet représentant le contexte de contrôle d’accès actuel du code exécuté. Vous pouvez ensuite utiliser SecurityManager pour vérifier les autorisations en fonction de ce contexte :
Si vos politiques de lecture de fichiers n’autorisent pas votre base de code à lire le fichier de ressources, ce code déclenchera une SecurityException — l’`AccessControlException`.
Même si cette démarche semble simple, elle présente plusieurs inconvénients. Il peut être difficile de définir des autorisations et des politiques précises. Par exemple, comment autoriser certaines opérations ou classes à écrire dans un fichier précis d’un répertoire auquel vos politiques interdisent l’accès ?
Vous pouvez séparer les répertoires contenant vos fichiers de politiques, de code source et de ressources pour contourner le problème. Vous devrez alors faire soigneusement correspondre vos autorisations à chacune de vos politiques et en assurer le suivi. C’est très inefficace, surtout si vous développez une application avec des politiques et des autorisations complexes.
Il n’est pas non plus plus facile de développer des bibliothèques et des API qui utilisent SecurityManager. Les bibliothèques reposant sur l’architecture SecurityManager vous obligent à accorder à votre code certaines des mêmes autorisations qu’elles. Vous devez donc éplucher leur documentation pour savoir quelles autorisations elles utilisent — à condition que celle-ci soit détaillée.
Vous pouvez aussi simplement accorder toutes les autorisations aux fichiers de la dépendance de bibliothèque. Toutefois, cela ne respecte pas les principes modernes du zero trust (*c’est-à-dire* le principe du moindre privilège).
Vos applications doivent être fonctionnelles, sécurisées et capables d’utiliser efficacement les ressources afin de garantir leur portabilité. Le SecurityManager est gourmand en ressources, en particulier lorsque vous utilisez ou développez une application reposant sur un réseau complexe d’autorisations et de politiques. En fait, la JVM s’exécute toujours avec SecurityManager désactivé par défaut.
Non seulement SecurityManager est obsolète sur le plan fonctionnel, mais son architecture n’est plus pertinente. Il n’y aura donc pas de remplacement direct. Alors, que faire ?
L’avenir du SecurityManager
Au moment de la rédaction de cet article, JDK 20 venait tout juste d’être mis à la disposition du grand public, et une grande partie de l’architecture du SecurityManager était toujours présente. Trois versions sont sorties depuis que sa suppression a été proposée. Comme il est lié à de nombreuses classes et bibliothèques Java, il est difficile de le supprimer sans casser toute l’API Java. Même Jakarta EE comporte de nombreuses fonctions qui reposent sur l’architecture du SecurityManager.
Sa suppression complète ne sera donc pas simple. Elle se fera par étapes, en toute sécurité, et a déjà commencé avec le marquage du SecurityManager comme devant être supprimé dans JDK 17. En outre, la JVM avertit les utilisateurs lorsqu’un SecurityManager est créé dynamiquement ou autorisé.
À partir de JDK 18, SecurityManager était désactivé par défaut. Si les développeurs tentaient d’en créer et d’en définir un (setSecurityManger), une erreur UnsupportedOperationException était déclenchée. La compatibilité avec le code hérité qui utilise SecurityManager existe toujours, mais tous ceux qui s’appuient encore sur cette architecture devraient envisager de l’abandonner.
Le JDK propose des alternatives à de nombreuses fonctions du SecurityManager. Par exemple, pour contrôler les autorisations d’accès au code natif, vous pouvez utiliser l’API Foreign Function and Memory (FFM), introduite dans JDK 20.
Les alternatives au SecurityManager
Pour commencer à dissocier votre code du Security Manager de Java, repérez les endroits où il est utilisé. Il est encore disponible dans les versions à support à long terme (LTS) les plus récentes du JDK (17 et 21), mais il est déprécié. Les organisations qui prévoient de passer d’anciennes versions LTS, comme JDK 11 ou 8, doivent en tenir compte. En définitive, tout code déprécié doit être supprimé ou mis à jour : il n’est pas bien maintenu et peut présenter un risque de sécurité. Vous pouvez utiliser jdeprscan pour repérer tout le code déprécié dans vos fichiers de classe.
La seule véritable alternative prête à l’emploi au SecurityManager est la bibliothèque de sécurité du JDK. Les développeurs doivent se familiariser avec les principes de codage sécurisé d’Oracle pour Java SE. En définitive, écrire du code sécurisé dès le départ est la première étape pour réduire les vulnérabilités de votre projet.
S’il est important de détecter les API obsolètes, ce n’est pas la seule faille de sécurité à rechercher. Il est également essentiel de vérifier les dépendances et les bibliothèques de votre projet. Les développeurs utilisent souvent SecurityManager pour surveiller les ressources auxquelles leurs applications accèdent et en consigner l’utilisation. Une solution tierce comme Snyk peut être utilisée à cette fin.
Snyk est un outil de sécurité destiné aux développeurs, qui peut s’intégrer à votre environnement de développement pour vous aider à analyser la sécurité de votre code et de vos conteneurs. Il analyse les fichiers de configuration et les manifestes de votre projet pour détecter et signaler les dépendances directes et indirectes présentant des vulnérabilités connues. Snyk corrige automatiquement vos vulnérabilités en modifiant vos fichiers de configuration et en mettant à jour toutes les dépendances. Il peut être intégré à de nombreux outils et workflows de développement.
Snyk propose une interface en ligne de commande (CLI) qui permet aux développeurs de l’utiliser dans leur terminal ou dans un workflow d’intégration continue et de livraison continue (CI/CD). Vous pouvez télécharger et installer l’outil CLI Snyk autonome. Une fois l’outil configuré et votre compte authentifié, vous pouvez tester vos projets locaux avec la commande snyk test.
Vous pouvez également suivre les nouvelles vulnérabilités susceptibles d’apparaître avec la commande snyk monitor. Snyk réalise alors un instantané de votre projet (consultable dans l’application web) et vous envoie des notifications par e-mail pour vous informer de tout nouveau problème détecté dans vos composants.
Voici une courte démonstration des commandes snyk test et snyk monitor :

Néanmoins, même si Snyk peut détecter des vulnérabilités, il reste important de respecter les principes de base du codage sécurisé en Java. Comme le dit le vieil adage : « Mieux vaut prévenir que guérir. » Il est donc important d’utiliser Snyk CLI pendant le développement, ainsi qu’un outil CI, dans le cadre d’une démarche DevSecOps efficace.
Ces dernières années, le secteur a connu une forte hausse des vulnérabilités open source. Pour limiter les attaques et les empêcher, les développeurs doivent régulièrement évaluer la posture de sécurité de leurs projets et de leurs workflows. Des outils comme Snyk sont régulièrement mis à jour et vous permettent d’automatiser les contrôles de qualité et de sécurité en les intégrant à votre pipeline CI/CD.
Alors que SecurityManager est à bout de souffle, vous pourriez être tenté d’utiliser une bibliothèque Java ou une API tierce reposant sur une architecture ou une approche similaire. Les bibliothèques tierces ont toujours représenté l’un des risques de sécurité les plus élevés. Si vous choisissez cette option, pensez à utiliser Snyk Open Source pour vous assurer que les dépendances de votre projet sont sûres.
Conclusion
En définitive, SecurityManager est obsolète. Il est étonnant qu’il ait fallu autant de temps pour le supprimer officiellement. Et ce n’est pas une mauvaise nouvelle. Bien au contraire, la plateforme Java y gagnera en sécurité et en simplicité. SecurityManager n’a jamais été conçu pour servir d’outil général de cybersécurité.
Si vous souhaitez améliorer plus efficacement la posture de sécurité globale de vos projets, envisagez un outil comme Snyk. Il peut vous aider à intégrer le zéro confiance à votre workflow de développement. Vous pouvez également ajouter le plugin Snyk Code pour IntelliJ afin de sécuriser votre code et d’en vérifier la qualité en temps réel.
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.



