◇ OpenCyber Academy
Graduação · Capítulo 8 · Português

Capítulo 8 — Programação II

Ensino gratuito e aberto para quem deseja proteger pessoas e tecnologias. Não é preciso criar uma conta para estudar ou consultar as respostas.

Capítulo 8 — Programação II

Mapa da aula

Aula 08 publicada. Mapa, exemplo, EX022.

flowchart TD
  N0["8.1 Módulos e responsabilidades"]
  N1["8.2 JSON e arquivos"]
  N2["8.3 Pacotes e arquivos de modelo"]
  N3["8.4 Testes adversariais"]
  N4["8.6b Testes que protegem o analisador"]
  N5["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Exemplo resolvido"]
  EX --> Q["Exercício EX022"]

Desenho lógico

flowchart LR
  N0["8.1 Módulos e responsabilidades"]
  N1["8.2 JSON e arquivos"]
  N2["8.3 Pacotes e arquivos de modelo"]
  N3["8.4 Testes adversariais"]
  N4["8.6b Testes que protegem o analisador"]
  N5["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX022"]
[8.1 Módulos e responsabilidades]
    |
    v
[8.2 JSON e arquivos]
    |
    v
[8.3 Pacotes e arquivos de modelo]
    |
    v
[8.4 Testes adversariais]
    |
    v
[8.6b Testes que protegem o analisador]
    |
    v
[Síntese]
    |
    v
[Exemplo resolvido] --> [Exercício EX022]

Objetivos de aprendizagem

Você vai (1) organizar programas em módulos e funções com responsabilidades claras; (2) usar JSON e arquivos com segurança; (3) gerenciar pacotes de terceiros e arquivos de modelo com verificações de integridade; e (4) escrever testes que incluam casos adversariais.

8.1 Módulos e responsabilidades

Divida os programas de modo que cada parte tenha uma única tarefa. Numa aplicação com LLM: tratamento de entradas, recuperação, chamada ao modelo, verificação de política, execução de ferramentas, registro em log. Manter a verificação de política em seu próprio módulo pequeno permite revisá-la e testá-la independentemente do modelo. A separação também limita o dano: se o módulo de recuperação for manipulado para devolver um documento hostil, a verificação de política continua decidindo de forma independente se alguma chamada de ferramenta resultante é permitida. No Ask Lumen, as verificações de marcação que Rina escreveu no capítulo de programação ficam num módulo assim, com testes que rodam a cada mudança. Um revisor consegue ler o módulo inteiro em poucos minutos.

8.2 JSON e arquivos

Analise dados estruturados com analisadores estritos (json.loads) e valide campos, tipos e intervalos. Rejeite campos desconhecidos. Nunca use eval sobre dados. Quando se pede ao modelo que produza JSON, valide-o da mesma forma, porque o modelo pode produzir saídas malformadas ou manipuladas. No Ask Lumen, pede-se ao modelo que devolva uma marcação em JSON com um código de clínica, uma data e um identificador de paciente. O analisador rejeita qualquer campo extra, como uma instrução para cancelar outras consultas, e qualquer valor fora dos intervalos permitidos. Uma resposta malformada leva a uma mensagem educada de falha para o paciente, nunca a uma ação parcial.

8.3 Pacotes e arquivos de modelo

Instale pacotes de fontes confiáveis, com versões fixadas. Arquivos de modelo são riscos parecidos com código: alguns formatos de serialização podem executar código ao serem carregados. Verifique o hash SHA-256 de um arquivo contra um manifesto confiável antes de carregá-lo; o laboratório detecta adulterações dessa forma.

"""Lab H: integrity of model artefacts with SHA-256 manifests (stdlib only).
Creates synthetic 'artefact' bytes, records a manifest, then detects a
one-byte tampering and a swapped file. No real models are involved."""
import hashlib, json
files = {"model.bin": bytes(range(256)) * 40, "tokenizer.json": b'{"vocab": ["a", "b"]}',
         "config.yaml": b"layers: 4\nheads: 8\n"}
manifest = {n: hashlib.sha256(b).hexdigest() for n, b in files.items()}
print(json.dumps({k: v[:16] for k, v in manifest.items()}, indent=1))
received = dict(files)
tampered = bytearray(received["model.bin"]); tampered[5000] ^= 1
received["model.bin"] = bytes(tampered)
received["config.yaml"] = b"layers: 4\nheads: 8\ntrust_remote_code: true\n"
for n, b in sorted(received.items()):
    ok = hashlib.sha256(b).hexdigest() == manifest[n]
    print(f"{n:15s} {'OK' if ok else 'MISMATCH'}")

Saída esperada:

{
 "model.bin": "e96760a87768717b",
 "tokenizer.json": "f63d2ddabc61f2d9",
 "config.yaml": "e5bbb570ca0fcb87"
}
config.yaml     MISMATCH
model.bin       MISMATCH
tokenizer.json  OK

No Lab H, um único bit invertido em model.bin e uma linha acrescentada em config.yaml mudam os respectivos hashes, enquanto o tokenizer.json intocado continua correspondendo. O manifesto precisa vir de uma fonte confiável, como a versão assinada do fornecedor, ou um atacante que altera um arquivo poderia alterar também o manifesto.

8.4 Testes adversariais

Acrescente testes que tentem quebrar seu código: entradas grandes demais, tipos errados, cadeias que parecem injeção, pedidos de dados de outros usuários. Mantenha-os permanentemente na suíte de testes. No analisador de marcações, os testes adversariais incluem uma data escrita por extenso, um identificador de paciente que pertence a outra pessoa, um código de clínica com espaços no final e uma saída do modelo contendo duas marcações. Cada teste registra a rejeição esperada. Uma vez acrescentados, esses testes protegem contra regressões: uma mudança posterior que afrouxe por acidente uma verificação falha na hora, antes de chegar aos pacientes.

8.5 Exemplo resolvido (caso sintético da LCH)

O fornecedor do DocSort enviou um modelo atualizado. A verificação de integridade de Rina comparou o hash com o manifesto assinado do fornecedor e encontrou uma divergência no arquivo de configuração. A investigação mostrou que um terceirizado havia editado o arquivo para ativar um modo de depuração que registrava o texto completo das cartas. A mudança foi revertida, e a LCH passou a exigir que toda mudança de modelo chegasse pelo processo de versões assinadas. O modo de depuração corresponde, em espírito, à linha de configuração adulterada do Lab H: uma pequena mudança de texto com grande efeito sobre a privacidade.

8.6 Erros e limites

Três erros são comuns: lógica de política misturada ao texto do prompt; carregar arquivos de modelo sem verificação de integridade; e testes apenas com entradas benignas. Uma política escrita no prompt pode ser contornada por uma mensagem habilidosa, enquanto uma política em código não pode. Carregar arquivos de modelo sem verificar hashes teria deixado o modo de depuração do terceirizado chegar à produção na LCH. Testes apenas com entradas benignas passam mesmo quando o analisador aceita saídas perigosas; o arquivo de testes hostis do analisador de marcações existe precisamente para evitar isso, e cresce a cada incidente.

8.6b Testes que protegem o analisador

O módulo que transforma a saída do modelo num pedido de marcação é o código mais relevante para a segurança no Ask Lumen, porque uma resposta malformada ou manipulada poderia cancelar a consulta errada. A LCH mantém um arquivo de testes com saídas hostis — campos extras, datas erradas, dois identificadores de consulta — e toda mudança no analisador precisa passar por ele antes da integração. Cada saída hostil do arquivo vem de uma falha real ou de um achado de revisão, então o arquivo registra o histórico de ataques ao analisador, além de protegê-lo contra eles. Quando aparece um novo tipo de falha, um teste para ela é acrescentado antes da correção.

Exercícios

Síntese

Programas estruturados, análise estrita, dependências verificadas e testes adversariais tornam as aplicações de IA mais difíceis de quebrar e mais fáceis de confiar.

Continue estudando — capítulo 08 de 40

← Capítulo 07 (rascunho) · Índice de capítulos do curso · Capítulo 09 (rascunho) →