Segurança
Como o OnlineCompiler.io roda com segurança o código enviado pelos usuários
Cada requisição roda código de alguém que não conhecemos. Esta página descreve como uma execução fica contida, como as chaves e as contas são protegidas, o que armazenamos e o que não afirmamos, para você avaliar se o serviço combina com o seu produto.
Pela equipe do OnlineCompiler.io. Atualizado em .
Also in EnglishTambién en español
Cada execução ganha o próprio sandbox
Uma execução inicia um contêiner novo, roda o programa e remove o contêiner. Nada é reaproveitado entre execuções, então um programa não consegue deixar arquivos ou processos para o próximo.
- gVisor: os contêineres rodam sob o gVisor (runsc), que trata as chamadas de sistema do programa num kernel em espaço de usuário, em vez de repassá-las ao kernel do host. Não existe alternativa de reserva: se o gVisor estiver indisponível, a execução falha em vez de começar num runtime menos isolado.
- Sem rede: a rede fica desativada, então os programas não alcançam a internet, nem os nossos servidores, nem os seus.
- Sem privilégios: os programas rodam como usuário sem privilégios (uid 65534), com todas as capabilities do Linux removidas e a escalação de privilégios desligada.
- Sistema de arquivos somente leitura: a imagem da linguagem é somente leitura. O único espaço gravável é um espaço de trabalho de 256 MB e 128 MB para arquivos temporários, os dois em memória e montados sem setuid nem arquivos de dispositivo. O código e o stdin são montados somente leitura a partir de um diretório privado criado para aquela tarefa.
- Limites fixos: 512 MB de memória sem swap, 2 CPUs, 16 processos, 256 arquivos abertos e nenhum core dump. Depois de 30 segundos o programa é interrompido, e o contêiner é encerrado à força se não sair.
- Saída limitada: até 64 KB por fluxo são guardados, e um programa que imprime mais de 8 MB é interrompido, para que uma enxurrada de saída não esgote os nossos workers.
A lista completa de limites, e os códigos de saída que uma execução devolve quando atinge um deles, está na documentação da API (em inglês).
O Docker basta? Docker, gVisor e microVMs comparados
Sozinho, não. As três formas comuns de isolar um programa diferem em quem trata as chamadas de sistema dele e, portanto, em quanto do kernel do host um programa hostil consegue alcançar:
| Docker (runc) | gVisor (runsc), o que usamos | MicroVM (Firecracker) | |
|---|---|---|---|
| Quem trata as chamadas de sistema | O kernel do host, filtrado pelo seccomp | O próprio kernel em espaço de usuário do gVisor; só um conjunto restrito chega ao host | Um kernel convidado dentro de uma máquina virtual |
| O que uma fuga exige | Um bug no kernel do host alcançável pelas chamadas permitidas | Um bug no gVisor e depois outro na interface mais restrita do host | Um bug no monitor de máquina virtual ou no KVM |
| Custo | Nenhum além do próprio programa | Programas que fazem muitas chamadas de sistema rodam mais devagar | Cada sandbox inicializa um kernel; o host precisa de KVM |
Uma microVM traça a linha mais rígida. O gVisor mantém a inicialização de um contêiner e, ao mesmo tempo, tira a maior parte do kernel do host do alcance do programa, e cada execução aqui ainda roda sem rede, sem privilégios e numa imagem somente leitura. O modelo de segurança do gVisor (em inglês) explica o design.
Chaves e contas
- Dois tipos de chave. As chaves de API chamam a API REST e o servidor MCP, e devem ficar no seu servidor. As chaves de widget são feitas para páginas públicas: só funcionam pelo WebSocket do widget, não chamam a API REST e podem ser restritas ao seu domínio, o que verificamos em toda conexão. Um iframe com uma chave restrita só pode ser incorporado por páginas desse domínio.
- Os limites da conta contêm uma chave vazada. Toda conta tem uma taxa por minuto (30 execuções por padrão), um limite de execuções pendentes (8), um limite de execuções num sandbox ao mesmo tempo (2, para que uma conta não ocupe todos os sandboxes) e uma cota mensal, compartilhados por todas as chaves dela. Desative uma chave no painel para cortar o acesso dela.
- Callbacks só vão para endereços públicos. O endpoint assíncrono envia os resultados para a URL HTTP ou HTTPS da sua chave de API. Endereços privados, de loopback e link-local são recusados, redirecionamentos não são seguidos, e o endereço é verificado de novo na entrega, para que uma mudança de DNS não consiga apontá-lo para dentro da nossa rede.
- Criptografado em trânsito. A API e o WebSocket são servidos por HTTPS e WSS; requisições HTTP sem criptografia são redirecionadas.
O que armazenamos
Cada execução fica armazenada como histórico de execuções: o código, a entrada, a saída, os erros, o código de saída, o tempo, a chave que a enviou e o endereço IP do cliente. Você vê o histórico da sua conta no painel. Por quanto tempo ele é mantido, e como pedir a exclusão, está na Política de Privacidade (em inglês). Os próprios programas não conseguem armazenar nada: o espaço de trabalho deles desaparece com o contêiner.
O que não afirmamos
- Não temos certificação SOC 2 nem ISO 27001, e não publicamos uma auditoria de terceiros.
- Nenhum sandbox é perfeito. O gVisor reduz a parte do kernel que um programa consegue alcançar, e os limites acima contêm o que ele consegue fazer, mas nenhum dos dois é uma garantia.
- O OnlineCompiler.io só existe como serviço hospedado. Se a sua política exige que o código rode nos seus próprios servidores, ele não é a escolha certa.
Como relatar uma vulnerabilidade
Se você encontrar uma forma de sair do sandbox, de contornar um limite ou de entrar nos dados de outra conta, fale com a gente e mande os passos para reproduzir antes de divulgar publicamente. Teste só na sua própria conta e não prejudique o serviço para os outros usuários.
Perguntas frequentes
É seguro rodar código não confiável com o OnlineCompiler.io?
Sim, ele foi feito para isso. Cada execução ganha um contêiner novo sob o gVisor, sem rede, com um usuário sem privilégios, sistema de arquivos somente leitura e limites fixos (512 MB de memória, 2 CPUs, 16 processos, 30 segundos). O código roda nos nossos servidores, nunca nos seus.
O Docker basta para rodar código não confiável?
Sozinho, não. Um contêiner Docker comum compartilha o kernel do host, então um bug do kernel alcançável pelas chamadas de sistema que ele permite pode levar para fora do contêiner. O gVisor coloca um kernel em espaço de usuário no meio, e uma microVM como o Firecracker dá ao programa um kernel só dele. Rodamos todos os programas sob o gVisor.
O código no sandbox consegue acessar a internet ou os meus servidores?
Não. Os contêineres começam com a rede desativada, então os programas não conseguem abrir conexões, baixar pacotes nem se conectar de volta aos seus sistemas. Os resultados só chegam até você pela nossa API.
O código de um usuário consegue ver o de outro?
Cada execução fica separada das outras: ela ganha o próprio contêiner, com o próprio espaço de trabalho em memória, e o código e a entrada dela são montados somente leitura a partir de um diretório privado daquela tarefa. O contêiner é removido quando a execução termina, então nada passa para a próxima.
A chave do widget é secreta?
Não. As chaves de widget ficam no HTML público por design. Elas só funcionam pelo WebSocket que o widget usa, não chamam a API REST e podem ser restritas ao seu domínio. Mantenha as chaves da API REST no seu servidor.
Vocês guardam o código que roda?
Sim. Cada execução fica armazenada com a entrada, a saída e o tempo, como histórico de execuções, que você vê no seu painel. A Política de Privacidade, em inglês, diz por quanto tempo ele é mantido; peça para excluirmos a sua conta e os dados dela quando quiser.