8 min de leitura

Sanitização de sequências de escape ANSI para terminais seguros

A sanitização de sequências de escape ANSI mantém controles de terminal, payloads OSC e truques de cursor fora do contexto de agentes de IA, preservando resultados úteis de comandos.

Sanitização de sequências de escape ANSI para terminais seguros

A saída do terminal é uma entrada. Assim que um agente pode ler o resultado de um comando, um arquivo do repositório, um registro de compilação, um banner SSH ou uma resposta de API, cada byte desse resultado pode tentar alterar o que o agente vê ou o comportamento de um terminal próximo. É um erro tratar o stdout como confiável só porque o seu próprio comando o produziu. Muitas vezes, o comando apenas repassa dados controlados por outra pessoa.

A sanitização de sequências de escape ANSI deve acontecer no limite em que a saída de uma ferramenta se transforma em contexto do agente. Faça isso antes de o modelo receber o texto, antes de uma pessoa abrir uma transcrição ao vivo e antes de um registro de sessão se tornar reproduzível. Remover os códigos de cor depois que o modelo já os leu apenas limpa as evidências.

Isso não significa transformar todo resultado de comando em um bloco estéril. Os agentes precisam de diagnósticos úteis. O objetivo é preservar o conteúdo semântico da saída e, ao mesmo tempo, impedir que instruções de terminal, movimentos do cursor, solicitações de clipboard, hiperlinks e outros controles atravessem um limite de confiança.

Uma transcrição de terminal é uma entrada não confiável

Um comando de shell não é dono da própria saída. git log exibe mensagens de commit. Um compilador exibe caminhos e trechos do código-fonte. Um executor de testes pode repetir um fixture. Um cliente SSH mostra um banner do servidor antes de exibir um prompt. Um gerenciador de pacotes lê nomes, versões, metadados e mensagens de erro de registros remotos. Em todos esses casos, alguém de fora pode influenciar o texto que depois chega a um agente.

A falha comum começa com uma conveniência útil: capturar stdout e stderr, concatená-los e anexar o resultado à conversa do agente. Esse desenho dá à saída duas funções. Ela relata o resultado de um programa e também funciona como instrução no contexto de um modelo de linguagem. Os controles de terminal tornam a primeira função menos confiável, e o conteúdo com aparência de prompt torna a segunda perigosa.

Considere um repositório que contém um nome de arquivo com retorno de carro e uma sequência de escape. Um comando que lista o arquivo pode produzir uma exibição que sobrescreve o próprio prefixo. O revisor vê um caminho inofensivo. O fluxo bruto de bytes contém outra coisa. Se uma ferramenta transformar esse fluxo em uma mensagem para o agente sem mostrar os limites dos bytes nem aplicar uma política de controle, o agente receberá um artefato ambíguo.

Não limite o modelo de ameaça a um colaborador mal-intencionado do repositório. Artefatos de compilação, rastreamentos de pilha de dependências, dispositivos de rede, erros de banco de dados e saídas de comandos remotos atravessam o mesmo limite. Um servidor comprometido não precisa de acesso ao shell do host do agente para devolver um banner criado para poluir uma transcrição.

Há dois riscos separados:

  • Um emulador de terminal pode executar instruções de controle quando uma pessoa visualiza a saída bruta.
  • Um agente pode interpretar texto visível, oculto ou reordenado como instrução, e não como dado.

Uma transcrição limpa do agente reduz o segundo risco. Um visualizador que nunca interpreta controles de terminal reduz o primeiro. Quando pessoas inspecionam a saída capturada, você precisa dos dois.

Os controles de terminal fazem mais do que adicionar cor

As sequências de controle do terminal podem mover o cursor, apagar texto anterior, definir o título da janela, criar um link clicável, colocar conteúdo no clipboard, consultar o terminal ou transmitir dados para um recurso do terminal. A cor SGR é apenas o subconjunto mais conhecido. Um filtro que remove ESC[ seguido de dígitos e m lida com cores, mas deixa intactas sequências muito mais poderosas.

A ECMA-48 define funções de controle e a forma geral das sequências CSI. Uma CSI normalmente começa com ESC seguido de [, depois traz bytes de parâmetros, bytes intermediários e um byte final. Ela também permite formas C1 de um único byte no intervalo de 0x80 a 0x9f. Os emuladores de terminal adicionam comportamentos privados a esse padrão. A documentação de xterm sobre sequências de controle descreve strings OSC, DCS, APC, PM e SOS, incluindo terminadores diferentes dos usados por uma sequência CSI.

Essa gramática importa porque os controles nem sempre chegam como uma linha de texto organizada. Um programa pode escrever ESC em um bloco e [ no seguinte. Um pseudo-terminal pode dividir a saída em qualquer byte. Uma ferramenta pode emitir uma string OSC terminada por BEL ou pela forma ST de dois bytes, ESC seguido de barra invertida. Um componente correto no limite precisa manter o estado entre leituras.

Alguns exemplos mostram por que um removedor de cores não basta:

  • ESC[2J pede ao terminal que apague a tela.
  • ESC[H move o cursor para a posição inicial.
  • ESC]8;;URI ESC\\ inicia um hiperlink OSC 8 nos terminais que oferecem suporte a ele.
  • ESC]52;... BEL é a operação de clipboard reconhecida por muitos emuladores de terminal.
  • Um retorno de carro leva o cursor à coluna zero e pode sobrescrever uma linha de status anterior.

Uma sequência não precisa ser aceita por todos os terminais para ser relevante. Um coletor de saída não pode prever qual terminal um engenheiro usará daqui a seis meses, qual visualizador reproduzirá um registro ou qual analisador transformará um byte de controle em um token visível. Remova a ambiguidade no momento da coleta.

Os caracteres de controle fora das sequências de escape também merecem atenção. Backspace, retorno de carro, alimentação de formulário, campainha e muitos bytes C1 podem mudar a apresentação ou confundir a análise orientada por linhas. Preserve apenas os controles necessários ao seu contrato de saída, normalmente alimentação de linha e talvez tabulação. Preserve o retorno de carro apenas quando um analisador atribuir a ele um significado explícito e testado.

Remova os controles antes de o texto chegar ao modelo

O padrão mais seguro é simples: colete os bytes, limite o tamanho, analise os controles de terminal como bytes, descarte as instruções de controle, decodifique o conteúdo imprimível restante com uma política de erro definida e envie o texto limpo ao agente. Não decodifique primeiro esperando que uma rotina de limpeza Unicode encontre o material perigoso. ESC é um byte ASCII, os controles C1 podem aparecer diretamente e sequências de bytes inválidas não podem fazer o coletor ignorar a filtragem.

Um caminho prático de saída tem quatro registros, mesmo que você exponha apenas um deles ao agente. Mantenha o fluxo bruto de bytes em armazenamento protegido para investigação. Produza texto simples normalizado para o contexto do modelo. Produza um relatório de remoção para operadores e registros. Armazene metadados como status de saída, duração, estado de truncamento, quantidade de bytes e um digest criptográfico do conteúdo bruto.

O relatório de remoção importa. A exclusão silenciosa pode esconder um problema da pessoa que precisa investigá-lo. Um relatório útil pode dizer que o coletor removeu duas sequências CSI, uma string OSC, três retornos de carro e uma sequência de bytes inválida. Ele não precisa reproduzir o payload. Repetir um payload OSC no relatório pode reintroduzir o mesmo risco.

Faça o limite se aplicar separadamente a stdout e stderr antes de mesclá-los. Os programas intercalam os fluxos de maneiras que não preservam a ordem de origem quando um wrapper os combina. Se o agente precisar de uma narrativa única, identifique os dois fluxos limpos e inclua um número de sequência atribuído pelo coletor. Isso preserva mais informação do que uma transcrição artificial que afirma uma ordem precisa que nunca foi observada.

Os limites de tamanho pertencem ao mesmo componente. Um invasor pode usar uma string OSC que nunca termina ou uma saída repetitiva para consumir memória e contexto. Defina um limite rígido para o total de bytes capturados e um limite menor para cada string de controle em andamento. Quando o limite for atingido, feche ou drene a fonte conforme a política do processo, marque o resultado como truncado e mantenha o artefato bruto parcial fora da mensagem do agente.

Não peça a um modelo que decida se uma sequência de escape é inofensiva. Modelos analisam texto, não protocolos de bytes, e a decisão pode variar conforme o contexto ao redor. Um analisador determinístico deve tomar essa decisão antes que o modelo veja a saída.

O isolamento preserva evidências sem preservar o comportamento

Remoção e isolamento resolvem problemas diferentes. A remoção cria texto utilizável ao eliminar instruções de apresentação. O isolamento mantém os bytes originais disponíveis para uma pessoa que tenha um motivo legítimo para inspecioná-los. Chamar uma captura bruta de «sanitizada» porque você a codificou em Base64 confunde transporte com autorização.

Em geral, um agente precisa das primeiras centenas de linhas de uma compilação que falhou, não de uma reprodução byte a byte de uma sessão de terminal. Forneça texto normalizado com marcadores explícitos para truncamentos e remoções. Se precisar de mais detalhes, permita que solicite um trecho limpo e limitado por intervalo de linhas ou termo de pesquisa. Não responda colando a captura bruta no mesmo contexto.

Quando um investigador precisar do original, abra-o em um visualizador orientado por bytes que mostre os controles de forma visível e nunca os envie a um terminal. Dumps hexadecimais funcionam bem porque deixam claros os limites dos bytes. Uma exibição que substitui ESC por ^[ pode ajudar, mas também precisa tratar corretamente caracteres C1 e payloads de strings. Um visualizador que executa cat sobre a evidência não é uma ferramenta forense.

Este comando de shell cria um arquivo de exemplo sem emitir os controles para o terminal atual. O arquivo contém SGR de texto vermelho, uma sequência CSI de subida do cursor, um hiperlink OSC 8 e um retorno de carro:

printf 'build: \\033[31mFAIL\\033[0m\\nnotice\\033[1A\\033]8;;https://example.invalid\\033\\\\open\\033]8;;\\033\\\\\\rPASS\\n' \u003e terminal-sample.bin
od -An -tx1c terminal-sample.bin

A saída de od deve conter 1b para ESC e 0d para retorno de carro. Ela nunca deve fazer o terminal seguir o link ou mover o cursor, porque od imprime uma representação dos bytes em vez de reproduzi-los.

O isolamento também precisa de controle de acesso. Um artefato bruto pode conter segredos que um comando exibiu por engano. Sanitizar controles de terminal não remove tokens, senhas nem dados pessoais. Execute a detecção e a remoção de segredos como uma etapa separada, com sua própria política para falsos positivos. Não misture as duas tarefas, porque um redator que não detecte uma credencial também não deve decidir se uma solicitação OSC 52 sobrevive.

Regex não é um analisador de terminal

Dê ações aos agentes, não segredos
Os agentes usam o shim sp mcp integrado, enquanto o Sallyport mantém as credenciais HTTP e SSH protegidas.

Uma expressão regular continua popular porque remove a saída colorida de uma compilação em uma linha. Ela falha como limite de segurança porque a gramática do terminal é orientada por estado e por fluxo. Muitos padrões também apresentam problemas de desempenho com entradas longas e malformadas, justamente o tipo de entrada que um adversário pode fornecer.

Use uma máquina de estados de bytes com comportamento explícito para ESC, CSI e controles de string. A função Python a seguir é deliberadamente restrita. Ela preserva tabulação e alimentação de linha, transforma o retorno de carro em uma política de quebra de linha visível, descarta outros controles C0 e C1 e remove sequências ESC, incluindo strings OSC, DCS, APC, PM e SOS. Ela aceita blocos apenas depois que o chamador os combinou, portanto uma versão de produção deve manter os campos de estado entre leituras.

def clean_terminal_bytes(data: bytes) -\u003e tuple[str, dict[str, int]]:
    out = bytearray()
    counts = {\"esc\": 0, \"csi\": 0, \"string\": 0, \"control\": 0}
    i = 0

    while i \u003c len(data):
        b = data[i]

        if b == 0x1b:  # ESC
            counts[\"esc\"] += 1
            i += 1
            if i \u003e= len(data):
                break
            nxt = data[i]

            if nxt == ord('['):  # CSI
                counts[\"csi\"] += 1
                i += 1
                while i \u003c len(data):
                    c = data[i]
                    i += 1
                    if 0x40 \u003c= c \u003c= 0x7e:
                        break
                continue

            if nxt in b']P_^X':  # OSC, DCS, APC, PM, SOS
                counts[\"string\"] += 1
                i += 1
                while i \u003c len(data):
                    c = data[i]
                    if c == 0x07:  # BEL
                        i += 1
                        break
                    if c == 0x1b and i + 1 \u003c len(data) and data[i + 1] == ord('\\\\'):
                        i += 2
                        break
                    i += 1
                continue

            i += 1  # Two-byte ESC function or unknown ESC form
            continue

        if b == 0x9b:  # Single-byte C1 CSI
            counts[\"csi\"] += 1
            i += 1
            while i \u003c len(data):
                c = data[i]
                i += 1
                if 0x40 \u003c= c \u003c= 0x7e:
                    break
            continue

        if 0x80 \u003c= b \u003c= 0x9f or b \u003c 0x20 and b not in (0x09, 0x0a):
            counts[\"control\"] += 1
            i += 1
            continue

        out.append(b)
        i += 1

    return out.decode(\"utf-8\", errors=\"replace\"), counts

Este exemplo tem limites. Ele não modela todas as funções de controle da ECMA-48 e trata formas ESC desconhecidas como removíveis. Essa abordagem conservadora é adequada quando a saída entra no contexto de um agente. Um emulador de terminal precisa de ampla compatibilidade. O limite do agente precisa de uma superfície aceita pequena.

Não copie essa função e considere o trabalho concluído. Adicione comprimentos máximos para parâmetros CSI e controles de string. Preserve o estado do analisador entre os limites de leitura. Conte sequências malformadas e sem terminador. Acima de tudo, escreva testes que garantam que o payload bruto nunca apareça no resultado limpo. Um filtro de segurança precisa de testes negativos, não apenas de capturas de tela atraentes mostrando o antes e o depois.

As sequências OSC merecem tratamento especial

As strings OSC são o ponto em que muitas equipes descobrem que a saída do terminal transporta mais do que formatação. O xterm documenta comandos OSC para funções como títulos de janelas e hiperlinks. Os emuladores modernos implementam subconjuntos diferentes, o que torna inadequadas as listas de permissões baseadas no terminal local de hoje.

Os links OSC 8 podem transformar um texto aparentemente inofensivo em um destino clicável. O rótulo visível pode dizer build report, enquanto o destino leva a outro lugar. Uma pessoa que lê uma transcrição limpa do agente não precisa de um link ativo. Se puder analisá-lo com segurança, mantenha o rótulo como texto comum; caso contrário, remova todo o wrapper OSC e preserve apenas os bytes imprimíveis seguintes. Não mantenha os destinos URI, a menos que seu produto tenha uma política separada para validação e exibição de URLs.

O OSC 52 pode pedir ao terminal que defina o conteúdo do clipboard. Alguns terminais o desativam ou exigem uma configuração, mas o coletor não pode depender disso. Se um registro bruto for reproduzido em um terminal permissivo, o comando poderá colocar conteúdo escolhido pelo invasor no clipboard do operador. O próximo paste pode cair em um shell, chamado, chat ou campo de credenciais.

As sequências que definem títulos criam um problema mais discreto. Elas podem alterar o título da janela exibido em um multiplexador de terminal, no alternador de tarefas do sistema operacional ou em uma gravação. Um título parecido com uma solicitação de aprovação ou uma implantação bem-sucedida pode induzir ao erro um operador que examina muitas janelas. Remover todo o tráfego OSC elimina essa classe inteira sem exigir uma lista que ficará desatualizada.

Não tente preservar strings OSC para facilitar a compreensão do modelo. Um agente não precisa legitimamente executar uma atualização de título do terminal, clicar em um hiperlink de terminal ou receber uma operação de clipboard. Se o resultado de um comando contiver uma URL útil, faça o comando imprimi-la como texto comum ou extraia-a de uma resposta estruturada antes que ela entre no caminho do terminal.

A mesma regra vale para strings de controle de dispositivos e comandos de programas de aplicação. Alguns emuladores os ignoram. Outros podem adicionar comportamentos com o tempo. Um limite de saída deve falhar de forma segura: se reconhecer um introdutor de string de controle, consuma até um terminador válido ou até o comprimento máximo configurado, registre a anomalia e mantenha o payload fora do contexto normal.

Defina um contrato de saída para cada ferramenta

Interrompa uma sessão imediatamente
Revogue instantaneamente uma execução de agente quando as ações dela já não merecerem acesso.

Um sanitizador não consegue consertar uma interface de saída que pede a uma transcrição de terminal que transporte um banco de dados, um relatório e uma interface de usuário ao mesmo tempo. As ferramentas devem declarar o que devolvem a um agente: texto UTF-8 simples, JSON estruturado produzido em um canal que não seja de terminal ou uma referência a um artefato isolado. Faça da saída semelhante à de um terminal a exceção, e não o formato padrão de intercâmbio.

Para os comandos que você controla, desative a decoração quando um agente os chamar. Muitos programas oferecem uma opção sem cores, um modo legível por máquina ou uma configuração de ambiente. Prefira a saída estruturada apenas quando controlar o esquema e limitar o tamanho. O JSON ainda pode conter injeção de prompt em campos de string, portanto identifique cada campo como dado e mantenha descrições não confiáveis separadas das instruções.

Para comandos que você não controla, execute-os com pipes em vez de um pseudo-terminal, a menos que o comando exija comportamento de terminal. Um pseudo-terminal estimula barras de progresso, reescritas do cursor, controles de título e caminhos de execução diferentes. Pipes não tornam a saída segura, mas reduzem a quantidade de protocolo de terminal que você precisa tratar.

Registre a proveniência junto do resultado. O agente e o revisor devem conseguir ver o executável chamado, o diretório de trabalho, o código de saída, o fluxo de origem, o limite de captura e se o sanitizador removeu conteúdo. Não permita que a saída da ferramenta se passe por esses campos. Coloque os metadados gerados pelo coletor em um envelope distinto, fora do texto não confiável.

Um envelope útil pode ter esta aparência:

{
  \"command\": \"test-runner --report plain\",
  \"exit_code\": 1,
  \"stdout\": \"142 tests passed\\n\",
  \"stderr\": \"fixture failed at tests/login.txt:18\\n\",
  \"sanitizer\": {\"removed_controls\": 4, \"truncated\": false},
  \"raw_artifact\": \"restricted:sha256:...\"
}

O campo raw_artifact deve ser uma referência que o agente comum não possa consultar. Se você devolver o conteúdo mediante solicitação sem uma nova decisão de autorização, a referência era apenas decorativa.

Teste saídas hostis fora do seu shell diário

Um sanitizador que passa em um teste com códigos de cor verde e vermelho apenas começou. Teste bytes que atravessam estados do analisador, terminam de forma inesperada e interagem com controles de exibição. Execute o corpus pelo caminho exato de captura usado pelos agentes, incluindo criação de processos, buffering, armazenamento de registros e renderização da transcrição.

Comece com um corpus pequeno que contenha um byte ESC no final de um bloco e [ no início do seguinte. Adicione sequências CSI com comprimentos incomuns de parâmetros, strings OSC terminadas por BEL e ST, uma string OSC sem terminador, bytes CSI C1, backspaces, retornos de carro repetidos e UTF-8 inválido ao redor de uma sequência de escape. Garanta que o texto voltado ao agente não contenha ESC, bytes do intervalo C1 nem payload de strings removidas.

Depois teste a semântica da exibição. Envie uma linha de status como working 10%\\rworking 20%\\rfailure pela política de retorno de carro escolhida. Se você a preservar como uma nova linha, o agente verá o histórico. Se simular a sobrescrita, o agente verá apenas failure. As duas políticas podem funcionar, mas documente e teste a escolha. Mudanças silenciosas durante uma atualização do analisador tornam a análise de incidentes difícil.

Fuzzing é útil aqui porque as gramáticas de escape têm poucos estados e um espaço enorme de entradas malformadas. Gere fluxos de bytes aleatórios com ênfase em ESC, BEL, barra invertida, bytes C1 e strings longas sem terminador. As propriedades são diretas: o filtro termina dentro dos limites de tempo e memória, não lança exceções e sua saída não contém bytes de controle proibidos.

Teste também o caminho humano. Uma página de registro, uma notificação da área de trabalho, um painel de terminal e uma transcrição copiada podem interpretar o conteúdo de maneiras diferentes. Renderize o corpus bruto apenas em um visualizador seguro de bytes. Renderize o texto limpo em todas as interfaces normais. Se um engenheiro puder copiar uma entrada bruta de registro para um terminal interativo durante uma investigação rotineira, há uma falha no limite de isolamento.

A aprovação humana não sanitiza uma transcrição

Mantenha as decisões junto da atividade
O Sessions registra as execuções dos agentes separadamente das chamadas individuais que eles fazem.

Um prompt de aprovação decide se um agente pode executar uma ação. Ele não decide se os bytes retornados pela ação são seguros para exibição ou inclusão em um prompt de modelo. Mantenha esses controles separados, ou alguém poderá presumir que aprovar ssh host command também significa aprovar cada banner, nome de arquivo e erro remoto devolvido pelo host.

Essa distinção importa para gateways de ações. O Sallyport pode manter as credenciais fora do alcance do agente e exigir autorização humana para uma ação, mas qualquer integração que envie resultados de ações a um agente ainda precisa de um limite de normalização de saída. A custódia de credenciais e a segurança da transcrição respondem a perguntas diferentes.

Não use aprovações repetidas para compensar um tratamento fraco da saída. Uma pessoa solicitada a aprovar cada leitura não inspecionará todos os caracteres de uma resposta longa, e a resposta pode chegar depois da aprovação. A revisão por chamada tem seu lugar em ações sensíveis. Ela não transforma uma saída não confiável em contexto confiável.

Mantenha o registro da decisão junto do resultado sanitizado. Registre que o operador aprovou um processo ou uma chamada e, depois, registre o resultado real do comando como dado não confiável da ferramenta, junto do relatório do sanitizador. Essa separação ajuda uma análise de incidente a responder a duas perguntas sem misturá-las: quem autorizou a operação e quais dados a operação devolveu?

A captura bruta deve permanecer fora do alcance comum dos agentes

Uma saída comum destrói um desenho que, de outra forma, seria sólido: quando o resultado limpo parece incompleto, o agente recebe uma ferramenta chamada read_raw_output. Essa ferramenta transforma um limite de segurança em um pequeno obstáculo. Basta que um invasor faça o resumo limpo parecer confuso o suficiente para o agente pedir o original.

Use recuperação restrita. Permita que uma pessoa abra o artefato em um visualizador seguro. Permita que um extrator dedicado devolva um intervalo hexadecimal limitado, uma comparação de digest ou texto imprimível depois de aplicar o mesmo analisador. Se um fluxo realmente exigir a inspeção do protocolo bruto, exija uma decisão humana explícita e use um visualizador que não execute controles de terminal.

Mantenha políticas de retenção distintas para dados brutos e limpos. A saída bruta pode exigir uma retenção mais curta porque pode conter segredos e payloads hostis. As transcrições limpas podem continuar úteis para revisar sessões de agentes, mas ainda contêm dados empresariais. Hashes conectam os dois registros sem obrigar usuários comuns a recuperar os bytes brutos.

A primeira tarefa de implementação não é uma regra de prompt que instrua os agentes a ignorar comandos de terminal. Coloque um analisador de bytes entre a saída do processo e toda transcrição voltada ao agente, faça a sintaxe de controle desconhecida desaparecer e preserve o original apenas onde os agentes comuns não possam buscá-lo. Essa mudança elimina uma classe inteira de ambiguidades antes que um modelo, um terminal ou um operador cansado precise raciocinar sobre ela.

FAQ

Os códigos de escape ANSI são as únicas sequências de controle do terminal que preciso remover?

Não. ANSI é uma abreviação imprecisa que geralmente se refere às sequências de controle ECMA-48, mas os emuladores de terminal também oferecem extensões privadas. Comandos OSC, sequências de controle de dispositivos, controles C1 e sequências específicas de cada emulador também precisam ser considerados.

Posso manter as cores do terminal e ainda proteger um agente de IA?

As cores podem permanecer se um renderizador confiável as aplicar depois que o agente processar o texto simples. Não passe as sequências SGR originais apenas para preservar a aparência. A ordem segura é analisar, remover os controles e só então aplicar opcionalmente uma camada de apresentação limitada para uma pessoa.

A saída de comandos codificada em Base64 é segura para um agente inspecionar?

Trate-o como dados inseguros até que um analisador normalize o conteúdo. A codificação Base64 impede que um terminal interprete os bytes durante o transporte, mas um agente pode decodificá-los e reproduzir o fluxo de controle original. Mantenha os dados brutos fora do contexto do agente, a menos que uma investigação específica exija o contrário.

Por que uma sequência de escape importa se o modelo não tem um emulador de terminal?

Um emulador de terminal aplica os controles, enquanto um agente pode lê-los como texto literal, tokens decodificados ou uma transcrição limpa. São consumidores diferentes, com modos de falha diferentes. A sanitização protege o contexto do agente; um visualizador seguro protege o terminal do operador humano.

Quando devo remover a saída em vez de colocá-la em quarentena?

Remova por padrão quando o agente precisar de status, diagnósticos e resultados comuns de comandos. Isole quando os bytes originais forem importantes para depuração, análise de incidentes ou uma ferramenta cuja saída não possa ser reduzida com segurança. Nunca use um painel de terminal bruto como mecanismo de isolamento.

Por que uma expressão regular não basta para remover escapes do terminal?

A maioria das expressões regulares falha quando uma sequência atravessa vários blocos, usa formas C1, contém um payload OSC ou termina com ST em vez de BEL. Uma pequena máquina de estados é mais fácil de auditar porque explicita os estados e as regras de término. Alimente-a com bytes, não com texto já decodificado.

A injeção de terminal pode persistir em transcrições ou registros de agentes?

Sim. Em um contexto compartilhado, ela pode induzir o próximo processo de agente ao erro tão facilmente quanto o atual. Os registros de sessão precisam das mesmas regras de normalização aplicadas à saída de ferramentas em tempo real. Mantenha um registro bruto protegido separado se os investigadores precisarem preservar os bytes exatamente.

Os pedidos de aprovação humana impedem a injeção de prompts pela saída do terminal?

A aprovação prova que uma pessoa permitiu uma ação, mas não torna confiáveis os bytes retornados. Um comando aprovado ainda pode ler conteúdo hostil de um repositório, banners remotos, metadados de pacotes ou linhas de registro. Trate a saída depois de cada ação aprovada.

Como devo guardar a saída bruta de comandos para análise forense?

Armazene os bytes brutos em um repositório de artefatos com controle de acesso ou em um registro de auditoria criptografado. Depois, forneça ao agente apenas uma referência e um resumo limpo. Registre o tamanho em bytes, o digest, a versão do analisador e a quantidade de remoções junto do artefato. Assim, um investigador pode reconstruir o ocorrido sem entregar bytes hostis às execuções comuns dos agentes.

Quais casos de teste um sanitizador de terminal para agentes deve incluir?

Teste sequências fragmentadas, links OSC 8, solicitações de clipboard OSC 52, reescritas com retorno de carro, backspaces, bytes de controle C1, UTF-8 inválido e strings sem terminador. Execute o mesmo corpus por pipes e pseudo-terminais, porque as ferramentas costumam mudar de comportamento quando detectam um TTY. Um sanitizador que lida apenas com um erro colorido de compilador ainda não merece confiança.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov