Políticas de segurança para execução de código
Restrições de capacidades, isolamento de rede, limites do sistema de arquivos e limites de tempo.
Políticas de segurança para execução de código é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.
Por que as políticas não são suficientes por si só
Dizer ao LLM 'não acesse a rede' não é um controle de segurança — é uma sugestão. O LLM pode ignorar isso, ser manipulado ou o código gerado pode violar a regra indiretamente.
As políticas de segurança reais devem ser aplicadas na camada de execução, não apenas no prompt.
Visão geral das restrições de capacidades
As restrições de capacidades limitam o que um processo em ambiente isolado pode fazer no nível do sistema operacional. As capacidades do Linux dividem os privilégios de root em permissões granulares que podem ser removidas individualmente.
Remover todas as capacidades, exceto o mínimo necessário, é chamado de princípio do menor privilégio.
import docker
client = docker.from_env()
# Drop all Linux capabilities
output = client.containers.run(
'python:3.12-slim',
'python -c "print(\"safe run\")"',
cap_drop=['ALL'],
network_disabled=True,
mem_limit='256m',
auto_remove=True
)
print(output.decode())Bloqueio de gravações em disco fora de /tmp
Use um sistema de arquivos raiz somente leitura e monte apenas /tmp como gravável. Isso impede que o código modifique arquivos do sistema ou persista dados fora da área temporária designada.
import tempfile, docker
client = docker.from_env()
with tempfile.TemporaryDirectory() as tmpdir:
output = client.containers.run(
'python:3.12-slim',
'python -c "open(\"/tmp/ok.txt\",\"w\").write(\"ok\"); print(open(\"/tmp/ok.txt\").read())"',
read_only=True,
tmpfs={'/tmp': 'size=64m,mode=1777'},
network_disabled=True,
mem_limit='128m',
auto_remove=True
)
print(output.decode()) # 'ok' — /tmp write allowed
# Writing anywhere else raises ReadOnlyFileSystemPerfis seccomp: filtragem de chamadas de sistema
O seccomp (modo de computação segura) permite especificar uma lista de permissões de chamadas de sistema. Qualquer chamada de sistema que não esteja na lista fará com que o processo seja encerrado com SIGSYS.
O Docker fornece um perfil seccomp padrão. Você pode fornecer um perfil JSON personalizado para aplicar restrições maiores.
import json, docker
client = docker.from_env()
# Minimal seccomp profile: only allow read, write, open, close, exit
seccomp_profile = json.dumps({
'defaultAction': 'SCMP_ACT_ERRNO',
'architectures': ['SCMP_ARCH_X86_64'],
'syscalls': [
{'names': ['read', 'write', 'open', 'openat', 'close',
'fstat', 'mmap', 'mprotect', 'munmap', 'brk',
'exit', 'exit_group', 'rt_sigaction',
'rt_sigprocmask', 'futex'],
'action': 'SCMP_ACT_ALLOW'}
]
})
output = client.containers.run(
'python:3.12-slim',
'python -c "print(1+1)"',
security_opt=[f'seccomp={seccomp_profile}'],
auto_remove=True
)
print(output.decode())Limites de recursos: CPU, memória e tempo
Três limites de recursos que todo ambiente isolado deve aplicar:
- Memória:
mem_limit— impede ataques de OOM - CPU:
nano_cpusoucpu_quota— impede o esgotamento da CPU - Tempo: limite de tempo de execução — impede loops infinitos
output = client.containers.run(
'python:3.12-slim',
'python -c "import time; time.sleep(100)"',
mem_limit='128m',
nano_cpus=500_000_000, # 0.5 CPU
network_disabled=True,
auto_remove=True,
timeout=10 # kill after 10 seconds
)
# Raises ReadTimeout after 10 secondsLista de permissões para importações do Python
Antes de executar o código, examine o AST em busca de instruções de importação. Rejeite qualquer importação que não esteja na lista de permissões. Essa é uma camada de defesa em profundidade — não substitui os controles no nível do sistema operacional, mas é útil para detectar violações evidentes das políticas logo no início.
import ast
ALLOWED_IMPORTS = {'math', 'statistics', 'json', 'csv', 'datetime', 'collections', 're'}
def check_imports(code: str) -> list[str]:
tree = ast.parse(code)
blocked = []
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
if alias.name.split('.')[0] not in ALLOWED_IMPORTS:
blocked.append(alias.name)
elif isinstance(node, ast.ImportFrom):
if node.module and node.module.split('.')[0] not in ALLOWED_IMPORTS:
blocked.append(node.module)
return blocked
print(check_imports('import socket; print(1)')) # ['socket']
print(check_imports('import math; print(math.pi)')) # []Detecção de padrões de código perigosos
Além das importações, verifique padrões que contornem as restrições de importação: __import__, exec(), eval(), compile(), open() com caminhos fora de /tmp.
import ast
DANGEROUS_CALLS = {'exec', 'eval', 'compile', '__import__', 'breakpoint'}
def check_dangerous_calls(code: str) -> list[str]:
tree = ast.parse(code)
found = []
for node in ast.walk(tree):
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
if node.func.id in DANGEROUS_CALLS:
found.append(node.func.id)
elif isinstance(node.func, ast.Attribute):
if node.func.attr in DANGEROUS_CALLS:
found.append(node.func.attr)
return found
print(check_dangerous_calls('exec("import os")')) # ['exec']Limites de tamanho da saída
Um loop de impressão descontrolado pode gerar gigabytes de saída. Limite a saída padrão e a saída de erro a um tamanho razoável (por exemplo, 1 MB) e trunque a saída ou encerre o contêiner se o limite for excedido.
MAX_OUTPUT_BYTES = 1 * 1024 * 1024 # 1 MB
def run_with_output_limit(client, code: str) -> dict:
container = client.containers.run(
'python:3.12-slim',
f'python -c "{code}"',
mem_limit='256m',
network_disabled=True,
detach=True
)
try:
container.wait(timeout=30)
logs = container.logs(stdout=True, stderr=True)
if len(logs) > MAX_OUTPUT_BYTES:
return {'success': False, 'error': 'Output too large'}
return {'success': True, 'output': logs.decode(errors='replace')}
finally:
container.remove(force=True)
if __name__ == '__main__':
class FakeContainer:
def wait(self, timeout=30): pass
def logs(self, stdout=True, stderr=True): return b'Analysis complete: 42 rows processed.'
def remove(self, force=True): pass
class FakeContainers:
def run(self, *args, **kwargs): return FakeContainer()
class FakeClient:
containers = FakeContainers()
result = run_with_output_limit(FakeClient(), 'print(42)')
print('Success:', result['success'])
print('Output :', result['output'])
Sinalizador no-new-privileges
A opção de segurança no-new-privileges impede que o processo obtenha privilégios adicionais por meio de binários setuid ou sudo. Mesmo que o código abra um shell, ele não pode elevar seus privilégios.
output = client.containers.run(
'python:3.12-slim',
'python -c "import os; print(os.getuid())"',
user='nobody', # run as non-root
security_opt=['no-new-privileges:true'], # no privilege escalation
cap_drop=['ALL'], # no capabilities
network_disabled=True,
mem_limit='128m',
auto_remove=True
)
print(output.decode()) # numeric UID of 'nobody'Combinação de todas as políticas
Um sandbox de nível de produção combina todas as camadas: recursos do sistema operacional removidos, perfil seccomp, sistema de arquivos somente leitura, no-new-privileges, rede desativada, limites de recursos e tempo limite. A defesa em profundidade garante que uma violação de uma camada seja impedida por outra.
import tempfile, json, docker
client = docker.from_env()
def maximum_security_run(code: str) -> dict:
with tempfile.TemporaryDirectory() as tmpdir:
try:
out = client.containers.run(
'python:3.12-slim',
f'python -c "{code}"',
user='nobody',
security_opt=['no-new-privileges:true'],
cap_drop=['ALL'],
network_disabled=True,
read_only=True,
tmpfs={'/tmp': 'size=32m,mode=1777'},
mem_limit='128m',
nano_cpus=500_000_000,
auto_remove=True,
timeout=15
)
return {'success': True, 'output': out.decode()}
except Exception as e:
return {'success': False, 'error': str(e)}Registro de violações de políticas
Quando uma violação de política é detectada (importação bloqueada, chamada perigosa ou tempo limite), registre o evento com o ID da sessão do agente, o hash do trecho de código e o tipo de violação. Essas informações alimentam um painel de segurança e ajudam a ajustar as políticas ao longo do tempo.
import hashlib, logging, time
logging.basicConfig(level=logging.INFO)
security_logger = logging.getLogger('sandbox.security')
def policy_check_and_run(code: str, session_id: str) -> dict:
violations = check_imports(code) + check_dangerous_calls(code)
code_hash = hashlib.sha256(code.encode()).hexdigest()[:16]
if violations:
security_logger.warning(
'POLICY_VIOLATION session=%s hash=%s violations=%s',
session_id, code_hash, violations
)
return {'success': False, 'error': f'Blocked: {violations}'}
result = maximum_security_run(code)
security_logger.info(
'EXEC session=%s hash=%s success=%s',
session_id, code_hash, result['success']
)
return resultO que a configuração 'defaultAction: SCMP_ACT_ERRNO' do perfil seccomp faz?
Os perfis seccomp controlam quais chamadas de sistema um processo pode fazer. O campo defaultAction determina o que acontece com as chamadas de sistema que não estão listadas explicitamente no perfil.
Recapitulação das políticas de segurança
A segurança eficaz na execução de código exige múltiplas camadas: recursos do Linux removidos, filtragem de chamadas de sistema pelo seccomp, sistema de arquivos somente leitura com espaço temporário tmpfs, no-new-privileges, rede desativada, limites de memória, CPU e tempo, e verificação de importações no nível do AST.
Nenhuma camada isolada é suficiente — a defesa em profundidade significa que cada camada compensa as violações das outras.
Perguntas Frequentes
A aula “Políticas de segurança para execução de código” é grátis?
Sim — o texto completo de “Políticas de segurança para execução de código” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.
O que vou aprender em “Políticas de segurança para execução de código”?
Restrições de capacidades, isolamento de rede, limites do sistema de arquivos e limites de tempo. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Agents?
Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Políticas de segurança para execução de código”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Agents?
Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Ambientes isolados para agentes baseados em Docker
- Isolamento por VM para agentes de código de alta segurança
- E2B e serviços de ambientes isolados na nuvem
- Políticas de segurança para execução de código