Skip to content

v0.6.0 — O gatilho é qualquer cor hexadecimal em style, não só o #333

Latest

Choose a tag to compare

@opedrosoares opedrosoares released this 31 Jul 01:26

Contexto

A v0.5.0 identificou a cor #333 do rodapé do template como gatilho do 403-WAF e destravou a edição. Um dia depois o mesmo documento voltou a ficar inescrevível — inclusive reenviando o conteúdo exatamente como estava gravado, sem alterar nada. O diagnóstico anterior estava certo no mecanismo e incompleto no alcance.

O que mudou no diagnóstico

O gatilho é qualquer cor hexadecimal em atributo style, não o #333 do rodapé em particular. Desta vez foram dois color:#000000 no corpo do documento. Como o padrão vem tanto do template do SEI quanto de conteúdo colado (Word cola hex o tempo todo), não é um documento com defeito — é uma classe inteira de documentos.

Duas hipóteses foram testadas e descartadas antes de chegar lá:

Não é reputação de origem. Havia a suspeita de que requisições saindo de datacenter nos EUA (IAD) fossem pontuadas pior que as de origem brasileira (GIG). O bloqueio foi reproduzido do Brasil com o mesmo corpo — a diferença não estava no caminho.

Não é score puramente acumulativo. Removendo janelas de mesmo tamanho em offsets diferentes, apenas 2 de 10 remoções faziam o corpo passar, e ambas continham as cores hex. Se fosse limiar de massa, qualquer corte equivalente resolveria.

Uma correção de método que vale registrar

A bissecção por prefixo usada na v0.5.0 produz fronteiras artificiais. Ela corta no meio de tags e palavras: num dos casos o limite "exato" caiu entre oportunam e oportuname, o que não é fronteira de padrão nenhum — é artefato de truncamento.

A substituição é remoção por janelas de mesmo tamanho em offsets diferentes, que separa o que a bissecção confunde: poucas remoções fazendo passar indica culpado local; quase todas passando indica score acumulativo. Junto com isso, passou a valer verificar determinismo (repetir o payload idêntico três vezes) antes de concluir qualquer coisa — sem isso, flutuação de pontuação vira "padrão descoberto".

Degrau novo: cores hexadecimais → rgb()

No 403-WAF, a tool reescreve as cores hex como rgb() equivalente e refaz o POST. A troca é neutra na renderização, então o documento não muda aos olhos de quem o lê.

A reescrita é restrita ao valor de atributos style, de propósito: um regex solto casaria entidades numéricas como é e corromperia o texto do documento. Há teste cobrindo exatamente isso.

Correção de regressão: validação de âncora

A checagem validar_referencias perguntava se o número da âncora era protocoloFormatado de algum documento e, em caso afirmativo, declarava a âncora errada. A regra real do core é outra — EditorRN::processarLinkProtocolo exige que o texto do link seja o protocoloFormatado do id, e descarta a tag quando não são iguais. E idProtocolo abrange processos, não só documentos.

Resultado: a âncora <a id="lnkSei2378553">50300.004460/2024-86</a> estava correta o tempo todo — 2378553 é o id do processo. O aviso era falso positivo por colisão de namespace (2378553 também existe como nº SEI de um documento), e agir sobre ele fez o SEI descartar a tag e o link desaparecer do documento.

A checagem agora parte do texto do link, que é o que o usuário vê, e se cala diante de âncora de processo. Teste de regressão cobrindo o caso.

Validação

Na Nota Técnica 105 (SEI 2979052): v15 gravada exercitando o degrau hex→rgb() ao vivo — tentativa 1 barrada pelo WAF, tentativa 2 gravou; e v16 com a âncora restaurada, que sobreviveu ao salvamento, provando que era válida desde o início. Documento íntegro: 9 títulos, 6 âncoras SEI, 4 links externos, brasão e rodapé regenerados. 73/73 testes passando.

O conserto durável continua sendo do lado da infraestrutura

Trocar #333 no modelo do SEI, sugerido na v0.5.0, resolve um sintoma. Com o gatilho agora entendido como "qualquer hex em style", fica claro que não escala: milhares de documentos carregam cor hexadecimal colada de editor externo, e cada um vira um documento que a API não consegue salvar.

A exceção de WAF em /sei/modulos/wssei/, restrita por IP de origem conhecido, é o que fecha a classe inteira.