HTML, chmod, contêineres e cron
O raciocínio por trás de quatro utilitários: por que um editor HTML precisa de uma lista de permissões e uma sandbox, por que o S maiúsculo em uma string chmod é importante, o que um comando docker run não pode expressar no compose e as duas regras cron que atendem a todos.
O editor HTML: uma lista de permissões, não um filtro
O editor produz HTML, e HTML que veio de uma caixa de texto é o vetor de injeção mais antigo que existe. Duas questões diferentes se confundem aqui, por isso vale a pena separá-las. A primeira é "este editor pode ser induzido a emitir marcação que executa código na página que o exibe?" A segunda é "esta é uma maneira segura de limpar HTML hostil de uma fonte não confiável?" Esta ferramenta responde sim à primeira e não à segunda, e diz isso no painel, em vez de permitir que você presuma o contrário.
O mecanismo é uma lista de permissões. É permitida uma lista de elementos; todos os outros elementos são desembrulhados, portanto seu texto sobrevive e sua tag não. É permitida uma lista de atributos por elemento; todo o resto é descartado, o que torna todo manipulador de eventos impossível, em vez de simplesmente bloqueado. Os nomes dos atributos estão em letras minúsculas antes desse teste, então oNeRrOr e ONERROR são o mesmo nome rejeitado que onerror. Elementos cujo conteúdo o analisador HTML trata como texto bruto — script, estilo, área de texto, iframe, título — são removidos junto com seu conteúdo, porque desembrulhá-los colaria a fonte do script no documento como marcação.
Os endereços dos links recebem sua própria verificação. O valor é decodificado pela entidade e sem espaços em branco e caracteres de controle antes de seu esquema ser lido, porque é isso que um navegador faz quando navega: javascript:alert(1) e jav ascript:alert(1) ambos alcançam o mesmo lugar. Somente endereços http, https, mailto, tel, ftp e relativos sobrevivem. Uma referência de caractere que a ferramenta não consegue resolver - : é o clássico - faz com que todo o endereço seja recusado em vez de passado, porque um filtro que entende menos da entrada do que o navegador é um filtro com um buraco.
Não há botão de imagem e img não está na lista de permissões. Uma tag de imagem permitida é uma solicitação de saída de onde quer que o documento termine e uma superfície onerror. Para um editor que produz prosa também não vale.
A defesa que não depende de nada disso ser perfeita é a prévia. Ele é renderizado em um iframe com um atributo sandbox que não concede absolutamente nada – nenhum script, nenhum formulário, nenhum acesso à mesma origem. Se uma carga sobrevivesse à lista de permissões, o navegador ainda se recusaria a executá-la lá. Esta é uma garantia estrutural e não uma promessa sobre o nosso código.
A limitação honesta: este é um desinfetante baseado em string, não um analisador HTML5 completo. Diferenciais do analisador – entradas onde um navegador constrói uma árvore diferente da que este tokenizador fez – são o ponto fraco conhecido de todo higienizador construído dessa forma. Para a saída, você mesmo gera neste editor, o que é bom. Para limpar HTML que chegou de um estranho, use um desinfetante executado em um analisador real, em um servidor que você controla.
Chmod: a letra maiúscula é toda a mensagem
Um modo de arquivo Unix tem doze bits: três bits de permissão para cada proprietário, grupo e outro, além de setuid, setgid e o sticky bit. A forma octal é uma leitura direta desses bits, por isso 4 + 2 + 1 = 7 significa ler, escrever e executar.
A forma simbólica que ls imprime é onde os bits especiais se tornam interessantes, pois não possuem coluna própria. setuid substitui o caractere de execução do proprietário, setgid substitui o caractere de execução do grupo e sticky substitui o outro caractere de execução. A letra é minúscula quando o bit de execução subjacente também está definido e UPPER maiúscula quando não está.
Então 4755 é rwsr-xr-x — um programa setuid que pode ser executado — enquanto 4644 é rwSr--r--, um arquivo setuid que ninguém pode executar. O S maiúsculo é o sistema que informa que o bit está inerte e quase sempre é um erro e não uma escolha. O mesmo se aplica a 1644, que mostra rw-r--r-T: um sticky bit em um arquivo normal onde o outro bit de execução está claro, o que em um kernel moderno não faz exatamente nada.
Mais duas distinções que vale a pena manter em linha reta. A string de nove caracteres que ls prints não é o argumento que chmod usa: chmod deseja uma lista de atribuições como u=rwx,g=rx,o=rx,u+s. E os mesmos bits significam coisas diferentes em um diretório e em um arquivo - executar significa "pode entrar e percorrer", setgid significa "novos arquivos herdam este grupo" e o sticky bit significa "qualquer um pode criar, apenas o proprietário pode excluir", que é a razão pela qual /tmp é 1777.
docker executado para compor: análise e o que não converte
O conversor divide o comando com um tokenizador com reconhecimento de cotação escrito para esta ferramenta. Nada é executado, avaliado ou entregue a um shell. Um comando contendo crases, $(...) ou ponto e vírgula é lido como caracteres literais, porque a única coisa que esta ferramenta faz com sua entrada é lê-la.
A maioria dos sinalizadores são mapeados de forma limpa: portas, volumes, ambiente, rótulos, política de reinicialização, recursos, verificações de integridade, limites de recursos, DNS e hosts extras, todos possuem chaves compostas com o mesmo significado. Volumes nomeados e redes definidas pelo usuário precisam de uma declaração de nível superior, bem como a referência de serviço, portanto, a saída carrega uma - com external: true nas redes, porque uma rede docker run poderia ingressar em uma que já existisse.
Alguns sinalizadores não têm equivalente de composição e é aqui que os conversores geralmente falham silenciosamente. --rm não é uma propriedade de serviço: um serviço de composição não é removido quando sai. -d descreve como você invocou CLI, não qual é o serviço. --link é legado, --mount precisa de um formato longo que esta ferramenta não grava, --gpus depende do seu driver. Cada um deles produz um aviso nomeado em vez de desaparecer. Um sinalizador desconhecido também produz um aviso e é tratado como se não tivesse valor, porque adivinhar que seria necessário transformaria o nome da sua imagem em um argumento e produziria um arquivo confiantemente errado.
A saída não traz nenhuma versão de nível superior: key. O Compose v2 o ignora e as versões atuais alertam sobre isso; está obsoleto desde que a especificação Compose substituiu as versões antigas de formato de arquivo.
Citar não é cosmético. Um mapeamento de porta escrito como 8080:80 sem aspas é lido como um número pelos analisadores YAML 1.1 e sim, não, on e off são booleanos no mesmo dialeto. Qualquer coisa que possa ser mal interpretada é citada; qualquer coisa que seja lida corretamente como uma string é deixada em paz, para que o arquivo permaneça legível.
Cron: duas regras que pegam todo mundo
A primeira é a regra do dia. Quando o dia do mês e o dia da semana são definidos como algo diferente de *, o cron executa o trabalho quando EITHER corresponde - não quando ambos correspondem. Portanto, 0 0 13 * 5 é "meia-noite do dia 13 e meia-noite de toda sexta-feira", que é aproximadamente cinco vezes por mês, e não "sexta-feira 13", que é uma ou duas vezes por ano. O gerador avisa sempre que ambos os campos são restritos e a frase que ele escreve diz "ou" em vez de "e".
O segundo é o fuso horário. O Cron usa a zona da máquina em que é executado, que frequentemente é UTC em um servidor e quase nunca a zona da pessoa que escreve o crontab. A visualização da próxima execução, portanto, pergunta qual zona usar, em vez de assumir a sua. Os horários são calculados como horários de relógio naquela zona, portanto, um trabalho diário permanece no mesmo horário local durante uma mudança de horário de verão, em vez de variar em uma hora - e um horário local que não existe, na hora ignorada a cada primavera, é deixado de fora da lista, porque o cron também não será executado.
A sintaxe em si é pequena: uma estrela, um número, um intervalo a-b, uma lista a,b,c, uma etapa */n ou a-b/n, e os nomes de mês e dia JAN-DEC e SUN-SAT. Ambos 0 e 7 significam domingo. Um valor simples com uma etapa, como 5/15 no campo de minuto, significa "de 5 até o final do intervalo, a cada 15", que é o minuto 5, 20, 35 e 50.
A validação é rigorosa de propósito. 60 * * * * é recusado porque os minutos param em 59; * * * * 8 foi recusado porque o campo do dia para em 7; */0 * * * * foi recusado porque um passo zero não corresponde a nada. Seis campos geralmente significam uma expressão Quartz ou systemd cujo primeiro campo é segundos, então o erro diz isso em vez de apenas contar. Uma programação que é sintaticamente válida, mas nunca pode ser executada — 0 0 30 2 * solicita o dia 30 de fevereiro — é aceita e sinalizada, porque recusar seria errado e ficar em silêncio seria pior.
O que acontece com o que você cola
- Cada conversão, hash, decodificação e comparação é executada na guia do seu navegador. Nenhuma entrada é carregada, registrada ou armazenada em um servidor, porque não há nenhum servidor envolvido depois que a página é carregada.
- Hashes vêm da implementação de criptografia da Web do próprio navegador e UUIDs de seu gerador aleatório criptograficamente seguro. Nenhum dos dois envolve uma chamada de rede.
- Nada do que você digita é gravado no armazenamento local ou em um cookie. Recarregar a página a descarta; fechar a guia a descarta.
- A análise de todo o site é executada apenas no host de produção canônico configurado e é divulgada na Política de Privacidade; hosts locais e de visualização recusam. Valores colados, tokens, URLs e conteúdos de arquivos são excluídos dos próprios eventos analíticos de ToolAcre. A publicidade está desativada na configuração atual.
- Dito isto: uma chave JWT ou API é uma credencial ativa. O hábito seguro é nunca colar um em uma página da web que você não escreveu, por mais confiáveis que sejam suas afirmações – incluindo esta.
Questões
Posso colar HTML hostil no editor para limpá-lo?
Você pode colá-lo e nada será executado: o manipulador de colagem limpa a carga útil da área de transferência antes que qualquer coisa seja inserida, e a visualização é um iframe em área restrita sem scripts de permissão. Mas não use o resultado como controle de segurança para entradas não confiáveis. Esta é uma lista de permissões baseada em string para a saída do próprio editor, não um filtro XSS de uso geral, e o analisador de um navegador pode alcançar uma árvore diferente de um tokenizador como este. Para conteúdo não confiável, limpe em um servidor com um analisador HTML5 real.
Por que o editor exclui minhas imagens e tabelas?
Porque eles não estão na lista de permissões. As imagens são uma solicitação de saída e uma superfície onerror; tabelas estão simplesmente fora da finalidade deste editor. O conteúdo do texto sobrevive, as tags não. Essa é a lista de permissões funcionando, e não um bug – mas significa que esta não é a ferramenta certa para editar um documento complexo existente.
Por que chmod 4644 mostra S maiúsculo?
Porque setuid está definido e o bit de execução do proprietário não. A letra maiúscula significa que o bit especial não tem nada sobre o que agir: é um arquivo setuid que não pode ser executado. S minúsculo significa que ambos os bits estão definidos. A mesma regra fornece S para setgid e T para o sticky bit, e retroceder é o erro mais comum nas calculadoras de modo.
O conversor docker executa meu comando?
Não, e não pode. O comando é dividido por um tokenizador que entende citações e nada mais. Não há avaliação, shell ou processo filho - a página não tem como iniciar um. Tudo o que você cola permanece na guia.
Por que o conversor avisa em vez de apenas descartar um sinalizador que não consegue controlar?
Porque um arquivo de composição que silenciosamente faz menos do que o comando de onde veio é pior do que nenhuma saída: você descobre na produção. Cada bandeira que não está representada é nomeada e o que fazer a respeito. Se você não vir nenhum aviso, nada foi perdido.
Por que as próximas execuções do cron são diferentes das que meu servidor faz?
Quase sempre o fuso horário. Cron usa a zona da máquina que o executa; a visualização usa a zona que você escolheu no menu suspenso. Defina-o para a zona do seu servidor – geralmente UTC – e eles deverão concordar. A outra candidata é a regra do dia: se o dia do mês e o dia da semana forem definidos, o cron será executado em qualquer um deles, o que ocorre com mais frequência do que a maioria das pessoas pretende.
Limitações
- O sanitiser HTML é uma lista de permissões para a saída deste editor, implementada como um tokenizador de string em vez de um analisador HTML5 completo. Não é um filtro XSS de uso geral e não deve ser usado como tal.
- O editor não possui imagens, tabelas, cores ou controles de fonte, e não há como adicioná-los: tudo que estiver fora da lista de permissões será removido.
- A superfície de edição usa document.execCommand, que está obsoleto e não tem substituição implementada. Os navegadores ainda oferecem suporte; o comportamento difere ligeiramente entre eles, especialmente em torno do aninhamento de listas.
- A calculadora chmod cobre apenas os doze bits de permissão. Listas de controle de acesso, atributos estendidos, contextos SELinux, aritmética umask e ACLs do Windows estão todos fora do escopo.
- O conversor docker traduz um único comando docker run em um único serviço. Ele não lê Dockerfiles, não resolve imagens e não pode expressar --mount, --gpus, --device, --link ou --volumes-from; cada um deles produz um aviso nomeado.
- Os sinalizadores que o conversor não reconhece são tratados como sem valor. Se tal sinalizador aceitar um, o valor será mal interpretado - o aviso diz isso, e remover o sinalizador é a solução.
- O gerador cron lê apenas o formato crontab de cinco campos. Expressões Quartz e systemd de seis campos, @reboot e as expressões não padrão L, W, # e ? os operadores são recusados em vez de adivinhados.
- Os horários da próxima execução vêm do banco de dados de fuso horário do próprio navegador por meio do Intl. Eles são uma prévia, não uma garantia: a máquina que executa o cron pode ter uma zona diferente, uma versão de banco de dados diferente ou um daemon que não estava em execução quando chegou a hora.