Pdf.js: A micro-otimização de estilo de camada de texto resultou na exigência de style-src 'unsafe-inline' na Política de Segurança de Conteúdo

Criado em 13 fev. 2017  ·  11Comentários  ·  Fonte: mozilla/pdf.js

https://github.com/mozilla/pdf.js/commit/cb5f9df0c8932fe0db9f783ede7893b7efcadcdb começou a gerar strings de estilo automaticamente, o que é proibido por uma Política de Segurança de Conteúdo padrão. Seria bom ter uma alternativa ou talvez reconsiderar a abordagem.

Para reproduzir, use style-src 'self' no CSP:

    <meta http-equiv="Content-Security-Policy" content="style-src 'self'" />
2-performance 4-text-selection

Comentários muito úteis

No caso de alguém descobrir isso e quiser uma solução, este é o meu patch atual, voltando à maneira antiga de fazer, então style-src: 'unsafe-inline' pode ser evitado:

https://github.com/GrapheneOS/pdf.js/commit/021d2fddb03883054ef4399d1d3df87e0c6ab9ca

Definitivamente, ele pode ser um pouco otimizado, mas como isso não importa para o meu uso, estou mantendo o patch o mínimo possível para facilitar a manutenção. Acho que esperar que alguém que quer esse problema de segurança resolvido se preocupe com a otimização do desempenho é um pouco atrasado. A otimização de desempenho deveria ser restrita ao que pode ser feito sem quebrar a higiene básica de segurança. Pode até ser mais rápido abordar isso de uma maneira diferente, como mencionei acima. A mensagem de confirmação para a otimização menciona como foi difícil até mesmo medir uma diferença, mas a regressão de segurança é facilmente medida.

O motivo pelo qual estou usando o pdf.js em primeiro lugar é a segurança. Ele permite reutilizar a renderização do navegador protegida / em área restrita com toda a renderização específica do PDF em uma linguagem de memória segura (JavaScript). Como parte disso, estou usando o CSP para mitigar a injeção dinâmica de código / estilo, o que poderia aumentar enormemente a superfície de ataque para ser como uma página da web, o que é muito contrário aos objetivos. Acho que muitas outras pessoas têm um caso de uso semelhante para pdf.js para evitar bibliotecas nativas de renderização de PDF perigosas. Evitar estilos unsafe-inline faz parte da garantia de que um bug não pode resultar na injeção acidental de estilos arbitrários, abrindo uma grande quantidade de superfície de ataque do renderizador. Para um caso de uso em que está embutido em um site real, é ainda mais importante, já que muitas coisas ruins podem ser feitas com CSS.

Eu considero isso no mesmo nível de esperar que binários / bibliotecas nativas tenham SSP, ASLR (PIE), _FORTIFY_SOURCE=2 , -fstack-clash-protection e outras mitigações de linha de base. É higiene de segurança básica versus coisas mais avançadas como CFI baseado em tipo, trapping de sanitizadores de inteiros, ShadowCallStack, etc. onde eu espero que projetos maiores pensem nisso e talvez já estejam trabalhando nisso, mas não faz parte do mínimo. Uma política CSP básica com JavaScript / CSS estático qualifica-se como higiene de segurança básica na minha opinião.

Todos 11 comentários

... ou talvez reconsidere a abordagem.

O PR # 7632 foi necessário para melhorar o desempenho do modo enhanceTextSelection em particular, que é parte do problema # 7584, portanto, em minha opinião, não acho que reverter isso deva sequer ser considerado.

Estou apenas sugerindo outras rotas para otimizá-lo. Por exemplo, por que usar 4 atributos de preenchimento e aplicá-los com style vez de mesclá-los?

Também pode usar a abordagem de matriz estática para definir propriedades de estilo individuais em vez de fazer tudo por meio de style . As propriedades font-family e font-size podem ser mescladas como padding .

Estou apenas sugerindo outras rotas para otimizá-lo. Por exemplo, por que usar 4 atributos de preenchimento e depois aplicá-los com estilo em vez de mesclá-los?

Em geral, não há garantia de que um determinado textDiv precise de todos os quatro valores de preenchimento atualizados com enhanceTextSelection , e o código atual forneceu uma maneira simples de lidar com esse caso (muito comum).

Também pode usar a abordagem de matriz estática para definir propriedades de estilo individuais em vez de fazer tudo por meio de estilo.

A linha geral de raciocínio por trás de atualizar tudo de uma vez usando style , era tentar evitar invalidar desnecessariamente o DOM ao criar / atualizar o textDiv s, uma vez que parecia ser um dos maiores contribuidores para desempenho ruim do modo enhanceTextSelection .

Em geral, não há garantia de que um textDiv específico precise de todos os quatro valores de preenchimento atualizados com enhanTextSelection, e o código atual forneceu uma maneira simples de lidar com esse caso (muito comum).

Isso não significa que padding não possa ser usado com eficiência. Não é necessário construir novas strings para as partes que não está atualizando e o resultado final será menor. Ele pode substituir um único conjunto de atributos style por um único conjunto style.padding e "0" pode ser reutilizado.

A linha geral de raciocínio por trás de atualizar tudo de uma vez usando o estilo era tentar evitar invalidar desnecessariamente o DOM ao criar / atualizar os textDivs, uma vez que isso parecia ser um dos principais contribuintes para o mau desempenho do modo enhanTextSelection.

Não está acontecendo em um fragmento, não no DOM real?

Isso não significa que o preenchimento não pode ser usado de forma eficiente.

@thestinger concorda, ajudará a resolver o problema se benchmarks com alguns dados de desempenho estiverem disponíveis.

Não sou realmente capaz de medir a diferença entre as diferentes abordagens aqui. No entanto, as diferentes abordagens podem ser avaliadas por micro-referência fora do contexto.

Acho que o conflito com unsafe-inline pode ser reduzido sem perda de desempenho ajustando isso e, em seguida, a otimização pode ser feita condicional se mantê-la for importante.

É fácil para mim apenas reverter este commit, então não é uma alta prioridade para mim, mas tentarei encontrar alguém para trabalhar nisso. Seria ótimo ter testes para coisas de CSP, para que não sejam interrompidos no futuro (otimizações como essa ainda podem acontecer se forem importantes, elas só precisam ser condicionais).

Pode haver uma solução que permite a otimização no estado em que se encontra, ao mesmo tempo em que oferece suporte a sites que usam CSP.

Existem três maneiras de definir o estilo embutido como uma string:

  • element.setAttribute('style', someStyle) , que não funciona quando há um CSP que não permite inline inseguro
  • element.style = someStyle , que não é compatível com o IE (testado no IE 11, não testei no Edge, então pode estar quebrado lá também)
  • element.style.cssText = someStyle , que é compatível a partir do DOM nível 2, portanto, até mesmo o IE oferece suporte (verificado no IE 11)

Plunker para mostrar os três métodos: https://plnkr.co/edit/T8xrUmR5eSuqDukSEVuw?p=preview

Eu estaria mais do que disposto a fazer uma solicitação de pull mudando element.setAttribute('style', ...) para element.style.cssText = ... se você concordar com esta solução.

No caso de alguém descobrir isso e quiser uma solução, este é o meu patch atual, voltando à maneira antiga de fazer, então style-src: 'unsafe-inline' pode ser evitado:

https://github.com/GrapheneOS/pdf.js/commit/021d2fddb03883054ef4399d1d3df87e0c6ab9ca

Definitivamente, ele pode ser um pouco otimizado, mas como isso não importa para o meu uso, estou mantendo o patch o mínimo possível para facilitar a manutenção. Acho que esperar que alguém que quer esse problema de segurança resolvido se preocupe com a otimização do desempenho é um pouco atrasado. A otimização de desempenho deveria ser restrita ao que pode ser feito sem quebrar a higiene básica de segurança. Pode até ser mais rápido abordar isso de uma maneira diferente, como mencionei acima. A mensagem de confirmação para a otimização menciona como foi difícil até mesmo medir uma diferença, mas a regressão de segurança é facilmente medida.

O motivo pelo qual estou usando o pdf.js em primeiro lugar é a segurança. Ele permite reutilizar a renderização do navegador protegida / em área restrita com toda a renderização específica do PDF em uma linguagem de memória segura (JavaScript). Como parte disso, estou usando o CSP para mitigar a injeção dinâmica de código / estilo, o que poderia aumentar enormemente a superfície de ataque para ser como uma página da web, o que é muito contrário aos objetivos. Acho que muitas outras pessoas têm um caso de uso semelhante para pdf.js para evitar bibliotecas nativas de renderização de PDF perigosas. Evitar estilos unsafe-inline faz parte da garantia de que um bug não pode resultar na injeção acidental de estilos arbitrários, abrindo uma grande quantidade de superfície de ataque do renderizador. Para um caso de uso em que está embutido em um site real, é ainda mais importante, já que muitas coisas ruins podem ser feitas com CSS.

Eu considero isso no mesmo nível de esperar que binários / bibliotecas nativas tenham SSP, ASLR (PIE), _FORTIFY_SOURCE=2 , -fstack-clash-protection e outras mitigações de linha de base. É higiene de segurança básica versus coisas mais avançadas como CFI baseado em tipo, trapping de sanitizadores de inteiros, ShadowCallStack, etc. onde eu espero que projetos maiores pensem nisso e talvez já estejam trabalhando nisso, mas não faz parte do mínimo. Uma política CSP básica com JavaScript / CSS estático qualifica-se como higiene de segurança básica na minha opinião.

Corrigido pela solicitação de pull acima.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

zerr0s picture zerr0s  ·  3Comentários

BrennanDuffey picture BrennanDuffey  ·  3Comentários

timvandermeij picture timvandermeij  ·  4Comentários

liuzhen2008 picture liuzhen2008  ·  4Comentários

dmisdm picture dmisdm  ·  3Comentários