O SecurityManager está sendo removido do Java: o que isso significa para você
15 de junho de 2023
0 minutos de leituraO pacote java.security da biblioteca do Java Development Kit (JDK) é um dos mais importantes, mas, apesar das atualizações constantes, continua muito pouco utilizado.
Diante da crescente ênfase em frameworks de cibersegurança, incluindo confiança zero, é fundamental que desenvolvedores Java conheçam as bibliotecas de segurança do Java SE.
Como qualquer outra área da tecnologia da informação, a cibersegurança é imprevisível. Afinal, ela precisa acompanhar as tendências mais recentes do cibercrime. Uma das mudanças na segurança do Java (para melhor ou pior, dependendo de quem você perguntar) é a remoção do SecurityManager. Mas por que isso é importante? Há motivos reais para se preocupar? Este artigo ajuda você a responder a essas perguntas.
A importância da segurança no Java
O Java é considerado uma linguagem segura por natureza, graças a recursos como a máquina virtual Java (JVM), o gerenciamento de memória, o tratamento robusto de exceções e a ausência de ponteiros explícitos (ou seja, referências). Apesar desses recursos integrados, usuários podem hesitar em adotá-lo por causa de vulnerabilidades de grande repercussão, como o Log4j.
No entanto, vale lembrar que muitas dessas vulnerabilidades estão relacionadas a produtos, terceiros e/ou desenvolvedores (ou seja, desenvolvedores que não escrevem código seguro). Embora o Java tenha (ou tenha tido) vulnerabilidades específicas do JDK, como exposição de dados confidenciais e problemas de desserialização, muitas já foram corrigidas ou estão em processo de correção. Por exemplo, o JDK 20 foi lançado com otimizações aprimoradas para intrínsecos de criptografia em plataformas específicas.
É claro que isso não significa que o Java cuide automaticamente de toda a segurança. Escrever código seguro ainda é responsabilidade de quem desenvolve. Isso exige conhecer os recursos e as limitações dos pacotes de segurança integrados ao Java. Muitas vezes, também não é necessário recorrer a APIs e bibliotecas de segurança de terceiros.
O JDK inclui recursos para segurança de plataformas, criptografia, controle de acesso e autenticação, comunicação e infraestrutura de chave pública. Você pode conhecer todos eles no Guia de segurança para desenvolvedores oficial.
Aprimorar qualquer plataforma ou ferramenta também significa remover recursos inseguros ou supérfluos. O SecurityManager é um desses recursos.
O que é o SecurityManager?
O Java SecurityManager foi criado como uma autoridade federada para a segurança de aplicações. Ele é (ou era) usado para definir políticas de segurança e regras para aplicações Java, garantindo que determinadas operações fossem seguras. A classe Java.lang.SecurityManager existe desde o JDK 1.0.
Originalmente, o SecurityManager era uma classe abstrata. Com o tempo, deixou de ser abstrata para facilitar o acesso e o uso. Embora fosse possível instanciar um novo objeto SecurityManager para cada classe, isso não estava de acordo com as práticas recomendadas de programação em Java. Em vez disso, era necessário definir uma propriedade do sistema ao executar a aplicação:
Outra opção era instanciar diretamente um objeto SecurityManager e, em seguida, defini-lo como uma propriedade do sistema no código:
Depois, era possível obter o SecurityManager do sistema em outra classe usando o seguinte:
A classe SecurityManager é composta principalmente por um conjunto de métodos de verificação. Eles conferem se determinadas operações da aplicação têm permissão para acessar certos recursos. Um dos métodos mais úteis é, sem dúvida, checkPermission, que verifica se uma operação pode usar certos recursos. As políticas de permissão são definidas e controladas por subclasses (diretas e herdadas) da classe java.security.Permission.
Em resumo, o SecurityManager simplifica a segurança de aplicações Java e é fácil de usar. Então, por que ele foi descontinuado?
A história do SecurityManager
Cada nova versão do Java SE traz diversas melhorias, muitas delas graças ao Java Community Process (JCP) e às propostas de aprimoramento do JDK. Estas últimas são o principal motivo da descontinuação do SecurityManager e de sua futura remoção.
No início, a classe SecurityManager era usada principalmente para definir políticas de segurança para applets, que já não são mais compatíveis com a maioria das plataformas web. O navegador fornecia o SecurityManager de cada applet.
A API Java Applet foi finalmente descontinuada com o lançamento do Java 9, em 2017, conforme definido pela JEP289. No entanto, a descontinuação não previa sua remoção. Com o lançamento do Java SE 17, a API Applet e suas classes relacionadas foram finalmente descontinuadas com previsão de remoção, conforme especificado pela JEP398.
Essa foi uma forma de fazer a linguagem de programação e a API avançarem. APIs antigas como essas se tornaram tão irrelevantes que deixaram de ser necessárias nas futuras versões do JDK. Como o SecurityManager está tão ligado à arquitetura de applets, ele está sendo removido por motivos semelhantes.
Por que o SecurityManager está sendo removido?
Hoje, o SecurityManager já não é a maneira mais eficiente de proteger código Java do lado do cliente e do servidor. Na verdade, a plataforma Java oferece mecanismos mais eficazes para essas tarefas.
Cada nova versão do JDK busca ser mais segura por natureza que a anterior. Isso significa que muitas das vulnerabilidades acidentais que o SecurityManager tentava resolver já não são relevantes.
Como a funcionalidade do SecurityManager não muda há uma década, ele não consegue lidar com muitas das ameaças, fragilidades e vulnerabilidades comuns enfrentadas atualmente por quem programa. Na verdade, ele nunca foi projetado para resolver os problemas de segurança de hoje. Ainda assim, como continua existindo, precisa ser testado junto com todas as classes às quais está conectado.
Isso gera uma carga de manutenção desnecessária. O tempo e o esforço dedicados a manter o SecurityManager poderiam ser usados para testar classes e recursos que hoje são mais relevantes para desenvolvedores. Embora uma das maiores vantagens da arquitetura do SecurityManager seja sua simplicidade, configurá-lo pode ser difícil.
Vale lembrar que o SecurityManager é composto principalmente por um conjunto de métodos de verificação. Um recurso de segurança útil, por exemplo, é o CheckPermission, que permite validar as permissões de uma aplicação ou sistema usando seu arquivo de políticas do Java. A estrutura de uma política que concede ao código de uma aplicação acesso de leitura a um diretório seria assim:
Essa configuração concede à base de código (todos os arquivos de classe) localizada em file:/home/source/ acesso a todos os recursos do diretório relativo files. Para verificar uma permissão específica, é necessário instanciar uma subclasse de `Permission` ou de `BasicPermission`. Ela representa, em última instância, o conjunto de permissões definido no arquivo de políticas. Neste caso, é o objeto FilePermission:
Como as políticas costumam depender do contexto, é preciso obter um objeto que represente o contexto de controle de acesso atual do código em execução. Em seguida, você pode usar SecurityManager para verificar as permissões nesse contexto:
Se suas políticas de leitura de arquivos não permitirem que seu código leia o arquivo de recurso, esse código lançará uma SecurityException — a `AccessControlException`.
Embora esse processo pareça simples, ele tem algumas desvantagens. Definir permissões e políticas detalhadas e granulares pode ser difícil. Por exemplo, e se você quiser que determinadas operações ou classes tenham acesso de gravação a um arquivo específico em um diretório cujo acesso é proibido pelas políticas?
Uma solução alternativa seria separar os diretórios das políticas, dos arquivos de código-fonte e dos arquivos de recursos. Para isso, seria preciso associar cuidadosamente cada permissão às políticas correspondentes e acompanhar essas relações. Isso é muito ineficiente, especialmente ao desenvolver uma aplicação com políticas e permissões complexas.
Desenvolver bibliotecas e APIs que usam SecurityManager também não é mais fácil. Bibliotecas baseadas na arquitetura SecurityManager exigem que você conceda ao seu código algumas das mesmas permissões que elas usam. Isso significa vasculhar a documentação da biblioteca para descobrir quais permissões ela concede — supondo que a documentação seja detalhada.
Outra opção é simplesmente conceder todas as permissões aos arquivos da dependência da biblioteca. No entanto, isso não está alinhado aos princípios modernos de segurança de confiança zero (ou seja, privilégio mínimo).
Para garantir a portabilidade, suas aplicações precisam ser funcionais, seguras e capazes de usar os recursos com eficiência. O SecurityManager consome muitos recursos, especialmente quando você usa ou desenvolve uma aplicação com uma rede complexa de permissões e políticas. Na verdade, a JVM sempre é executada com o SecurityManager desativado por padrão.
O SecurityManager não está apenas obsoleto em termos funcionais; sua arquitetura também se tornou irrelevante. Isso significa que não haverá substitutos diretos. E agora?
O futuro do SecurityManager
No momento em que este artigo foi escrito, o JDK 20 acabava de ser disponibilizado ao público, e grande parte da arquitetura do SecurityManager ainda permanecia intacta. Três versões foram lançadas desde que sua remoção foi proposta. Como ele se integra a tantas classes e bibliotecas Java, removê-lo sem comprometer toda a API Java é difícil. Até mesmo o Jakarta EE tem muitas funções que dependem da arquitetura do SecurityManager.
Isso significa que a remoção completa não será simples. O plano é realizá-la em etapas seguras, iniciadas quando o SecurityManager foi marcado para remoção no JDK 17. Além disso, a JVM avisa os usuários quando um SecurityManager é criado dinamicamente ou tem seu uso permitido.
No JDK 18, o SecurityManager passou a ser desativado por padrão. Se os desenvolvedores tentassem criar e definir um SecurityManager (setSecurityManger), seria gerado um erro UnsupportedOperationException. Embora ainda exista suporte para código legado que usa SecurityManager, quem ainda depende dessa arquitetura deve considerar abandoná-la.
O JDK oferece alternativas para muitas das funções do SecurityManager. Por exemplo, quem precisa controlar permissões de acesso ao código nativo pode usar a API Foreign Function and Memory (FFM), introduzida no JDK 20.
Alternativas ao SecurityManager
O primeiro passo para desvincular seu código do Java Security Manager é identificar onde ele é usado. Embora ainda esteja disponível nas versões com suporte de longo prazo (LTS) mais recentes do JDK (17 e 21), ele foi descontinuado. Organizações que planejam atualizar versões LTS anteriores, como o JDK 11 ou 8, precisam levar isso em conta. Em última análise, todo código descontinuado deve ser removido ou atualizado, pois não recebe manutenção adequada e pode representar um risco de segurança. Você pode usar o jdeprscan para encontrar todo o código descontinuado nos arquivos de classe.
A única alternativa realmente pronta para uso ao SecurityManager é a biblioteca de segurança do JDK. Desenvolvedores também precisam conhecer as Diretrizes de programação segura da Oracle para Java SE. Em última análise, escrever código seguro desde o início é o primeiro passo para reduzir as vulnerabilidades do seu projeto.
Embora seja importante procurar APIs obsoletas, essa não é a única vulnerabilidade de segurança que você deve identificar. Também é fundamental verificar as dependências e bibliotecas do seu projeto. Os desenvolvedores costumam usar o SecurityManager para monitorar e registrar os recursos acessados pelos aplicativos. Uma solução de terceiros, como o Snyk, pode ser usada para essa finalidade.
O Snyk é uma ferramenta de segurança para desenvolvedores que pode ser integrada ao seu ambiente de desenvolvimento, ajudando você a analisar a segurança do código e dos contêineres. A ferramenta examina os arquivos de configuração e os manifests do seu projeto para encontrar e sinalizar dependências diretas e indiretas com vulnerabilidades conhecidas. O Snyk corrige automaticamente as vulnerabilidades, aplicando patches aos arquivos de configuração e atualizando todas as dependências. Ele pode ser integrado a diversas ferramentas e fluxos de trabalho de desenvolvimento.
O Snyk oferece uma interface de linha de comando (CLI) que permite aos desenvolvedores usá-lo no terminal ou em um fluxo de trabalho de integração e entrega contínuas (CI/CD). Você pode baixar e instalar a ferramenta independente da CLI do Snyk. Depois de configurá-la e autenticar sua conta, você pode testar seus projetos locais usando o comando snyk test.
Além disso, você pode acompanhar novas vulnerabilidades que venham a surgir usando o comando snyk monitor. Com esse comando, o Snyk registra um snapshot do seu projeto, que pode ser consultado no aplicativo web, e envia notificações por e-mail para avisar você sobre novos problemas identificados nos componentes.
Confira uma breve demonstração dos comandos snyk test e snyk monitor:

Ainda assim, embora o Snyk encontre vulnerabilidades, é importante seguir os princípios básicos de programação segura para Java. Como diz o ditado: “É melhor prevenir do que remediar”. Por isso, é importante usar a CLI do Snyk durante o desenvolvimento junto com uma ferramenta de CI, como parte de um processo de DevSecOps bem estruturado.
Nos últimos anos, o setor registrou um aumento expressivo nas vulnerabilidades de código aberto. Para reduzir o risco e prevenir ataques, os desenvolvedores devem revisar regularmente a postura de segurança de seus projetos e fluxos de trabalho. Ferramentas como o Snyk são atualizadas com frequência e permitem automatizar as verificações de qualidade e segurança ao integrá-las ao pipeline de CI/CD.
Com o SecurityManager perto do fim, você pode se sentir tentado a usar uma biblioteca Java ou API de terceiros com arquitetura ou abordagem semelhante. As bibliotecas de terceiros sempre estiveram entre os maiores riscos de segurança. Se optar por esse caminho, considere usar o Snyk Open Source para garantir que as dependências do seu projeto sejam seguras.
Conclusão
Em resumo, o SecurityManager está obsoleto. É surpreendente que tenha demorado tanto para removê-lo oficialmente. E isso não é uma má notícia. Pelo contrário: a plataforma Java ficará muito mais segura e menos complexa. O SecurityManager nunca foi feito para servir como uma ferramenta geral de cibersegurança da qual se pudesse depender.
Se você busca uma maneira mais eficaz de melhorar a postura geral de segurança dos seus projetos, considere usar uma ferramenta como o Snyk. Ela pode ajudar você a incorporar o modelo de confiança zero ao seu fluxo de trabalho de desenvolvimento. Além disso, você pode adicionar o plugin do Snyk Code para IntelliJ para proteger seu código e garantir sua qualidade em tempo real.
Comece a jogar Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.



