💡 Exemplo completo funcionando disponível no GitHub:
merge-untrusted-html-uploads-dotnet
Mesclar com segurança documentos HTML não confiáveis é um fluxo de trabalho do GroupDocs.Merger para .NET que nega os recursos externos que um upload referencia – URLs remotas, caminhos UNC e arquivos locais – a menos que você os permita explicitamente.
O Método Antigo Era Doloroso
Imagine que seu portal de faturamento mescla o upload de uma fatura do cliente com uma nota de entrega do mesmo pedido em um único documento HTML para arquivamento. A fatura é HTML simples – um link de folha de estilo, uma imagem de logotipo, alguns parágrafos – exceto que você não a escreveu, foi o navegador ou a ferramenta de exportação do cliente que a gerou. Antes do GroupDocs.Merger 26.10, a mesclagem carregava os recursos externos que o HTML referenciava – folhas de estilo remotas, imagens remotas, caminhos absolutos de arquivos locais – e não havia opção para impedir isso.
Isso se torna um problema no momento em que o upload não é totalmente confiável. Uma URL de folha de estilo pode ser também um pixel de rastreamento. Um src de imagem pode apontar para http://169.254.169.254/latest/meta-data/iam/security-credentials/ – um endereço de metadados de nuvem – e sua etapa de mesclagem faria a solicitação em nome do uploader. Um caminho absoluto file:/// também era lido, de modo que uma referência ao upload de outro cliente poderia puxar esse arquivo para a saída mesclada.
O custo real de mesclar às cegas: um trabalho de mesclagem que busca tudo o que um upload solicita transforma seu servidor em um proxy para SSRF, e uma referência
file:///em um meio para que a mesclagem de um cliente leia o arquivo de outro cliente.
Existe um Caminho Melhor
GroupDocs.Merger para .NET corrige isso por padrão. Desde a versão 26.10, todo construtor de LoadOptions define SkipExternalResources = true, e um Merger criado sem opções de carregamento usa esse mesmo padrão – nada externo é carregado a menos que você indique o contrário.
Pré-requisitos:
- .NET (qualquer um dos quatro frameworks de destino que o GroupDocs.Merger para .NET suporta)
- GroupDocs.Merger para .NET 26.10 ou posterior (obter uma licença temporária)
- Dois documentos HTML para juntar, pelo menos um de uma fonte que você não confia totalmente
Instale com um comando:
dotnet add package GroupDocs.Merger --version 26.10.0
O Novo Caminho: Mesclando HTML Sem Confiar Nele
Veja como a junção de dois uploads HTML se parece com as configurações seguras, um manipulador que registra cada decisão e – em uma segunda passagem – um manipulador que fornece um recurso confiável.
Etapa 1 - Criar Opções de Carregamento para o Formato
LoadOptions não possui construtor sem parâmetros e é selado desde 26.10; o exemplo nomeia o formato explicitamente.
// LoadOptions(FileType.HTML) already denies everything external by default
var audit = new ResourceAudit();
var loadOptions = new LoadOptions(FileType.HTML) { ExternalResourceHandler = audit };
Etapa 2 - Unir os Uploads e Inspecionar as Decisões
// Both uploads follow the options of the Merger they are joined to
using (var merger = new Merger(firstUpload, loadOptions))
{
merger.Join(secondUpload);
merger.Save(outputPath);
}
foreach (string decision in audit.Decisions)
{
Console.WriteLine(decision);
}
Pontos-chave:
SkipExternalResources: implicitamentetrueaqui, portanto toda URL remota, caminho UNC e referência a arquivo local são negados, inclusive um arquivo na própria pasta do upload.- Um
LoadOptionspor junção: o segundo upload não recebe suas próprias opções – ele herda o que oMergerao qual foi unido foi criado.
Etapa 3 - Permitir Exatamente Um Recurso Confiável
// Supply the logo's bytes directly instead of requesting it over the network
var trustedAssets = new Dictionary<string, byte[]>
{
[logoUrl] = File.ReadAllBytes(logoPath)
};
var audit = new ResourceAudit(trustedAssets);
var loadOptions = new LoadOptions(FileType.HTML) { ExternalResourceHandler = audit };
O método OnLoading do manipulador define args.Skipped = false e args.Data para esses bytes quando o URI solicitado corresponde, de modo que o documento obtém o logotipo sem que o GroupDocs.Merger faça qualquer requisição.
Quando executamos a mesclagem padrão contra os uploads de fatura e nota de entrega, todas as sete referências externas nos dois arquivos foram bloqueadas – a folha de estilo remota, o logotipo remoto, a URL no estilo de metadados, a imagem da pasta irmã, um caminho file:///, um caminho UNC e uma URL de rastreamento com string de consulta. joined.html mantém o texto de ambos os uploads; um placeholder substitui cada imagem bloqueada. Com o manipulador de logotipo confiável anexado, o logotipo foi supplied e as outras seis permaneceram blocked.
Lado a Lado: Antes vs. Depois
| Antes (sem opção) | Depois (GroupDocs.Merger 26.10) | |
|---|---|---|
| Solicitações externas | Cada referência carregada automaticamente | Negado a menos que explicitamente permitido |
| Caminhos absolutos de arquivos locais | Carregados na saída | Negados como qualquer outra referência |
| Exceções confiáveis | Não necessárias – tudo carregado | Um recurso via manipulador, ou um prefixo na lista branca |
| Entrada inválida na lista branca | Não existia lista branca | Rejeitado com ArgumentException na construção |
| Código necessário | Não há como restringir o carregamento | Algumas linhas em LoadOptions |
O contraste está no que é possível, não apenas no que é conveniente: antes da 26.10 não havia configuração que interrompesse o carregamento; depois, negar é o padrão e cada exceção deve ser explícita.
Isso quebrará HTML que já dependia do carregamento de imagens remotas?
Se esse HTML ainda for mesclado com LoadOptions padrão, sim – as imagens não serão carregadas, e um placeholder ocupará seu lugar na saída. A solução é explícita, não uma solução alternativa: liste as fontes confiáveis em WhitelistedResources, ou anexe um IExternalResourceHandler que forneça os ativos específicos que ainda deseja renderizar. De qualquer forma, a mesclagem continua; ela apenas deixa de buscar tudo que não foi nomeado.
Exemplo do Mundo Real: Consolidação de Fatura e Nota de Entrega
Um pipeline de documentos que mescla HTML enviado pelo cliente em uma cópia de arquivo é exatamente o cenário que o projeto‑exemplo desta página modela: um upload de fatura e uma nota de entrega do mesmo pedido, unidos em um único arquivo. Nenhum dos uploads foi escrito pela própria equipe do pipeline, portanto nenhum pode ser considerado seguro para leitura literal. A fatura indica um valor devido e um cliente, Northwind Traders, e contém referência a logotipo, folha de estilo de rastreamento, URL no estilo de metadados de nuvem, referência a imagem na mesma pasta e um caminho file:/// – sete referências externas entre os dois uploads, nenhuma das quais o pipeline de arquivamento deveria buscar em nome do cliente.
Antes que o trabalho de mesclagem entre em produção, vale a pena decidir, tipo de documento por tipo de documento, se alguma exceção é necessária. O cenário de faturamento deste exemplo precisou de exatamente uma: o logotipo da própria empresa, servido a partir de um arquivo já presente em disco em vez de ser buscado da URL remota que o HTML indica. Todo o resto – a folha de estilo de rastreamento, o endereço no estilo de metadados, o arquivo irmão, os caminhos UNC e file:/// – não tinha motivo legítimo para ser buscado, portanto os padrões sozinhos eram a resposta correta.
// Reject a whitelist entry that is not an absolute URI prefix
var loadOptions = new LoadOptions(FileType.HTML)
{
WhitelistedResources = new List<string> { "cdn.example.com" }
};
Passar apenas um nome de host em vez de um prefixo absoluto como https://cdn.example.com/brand/ gera exceção, com a mensagem Whitelisted resource 'cdn.example.com' must be an absolute URI without a query, fragment or encoded '/', '\' or '.'. (Parameter 'WhitelistedResources') – antes mesmo de qualquer upload ser aberto. Detectar uma lista branca mal configurada na inicialização vale mais do que detectá‑la depois que um recurso falha silenciosamente em produção.
O Que Mais Você Pode Fazer com GroupDocs.Merger para .NET?
- Validar entradas da lista branca antecipadamente: uma entrada malformada em
WhitelistedResourcesfalha na construção doMerger, portanto verificações de inicialização de implantação a capturam antes que qualquer documento seja processado. - Fornecer ativos confiáveis a partir do disco:
IExternalResourceHandlerpode responder a uma solicitação com bytes que você já possui, sem nenhum acesso à rede. - Aplicar uma política a todos os documentos unidos:
LoadOptionsé definido uma única vez noMerger, e todo documento unido posteriormente segue as mesmas regras. - Abranger mais que HTML: processadores de texto, HTML/MHTML, apresentações, planilhas, SVG e documentos EPUB respeitam as mesmas opções.
Conclusão
Mesclar HTML que você não escreveu não significa mais confiar em tudo que ele contém. GroupDocs.Merger para .NET nega recursos externos por padrão desde a versão 26.10, e as duas formas de conceder uma exceção – um manipulador de ativos confiáveis e WhitelistedResources – dão exatamente o acesso que um pipeline específico necessita, nada a mais.
Pronto para experimentar por conta própria?
- Experimente a licença temporária gratuita
- Leia como pular o carregamento de recursos externos
- Saiba quando o GroupDocs.Merger acessa a rede
- Explore o guia de caso de uso passo a passo
- Confira o projeto de exemplo no GitHub