CA5389: Não adicione o caminho do item de arquivo ao caminho do sistema de arquivos de destino
Property | valor |
---|---|
ID da regra | CA5389 |
Título | Não adicione o caminho do item de arquivo ao caminho do sistema de arquivos de destino |
Categoria | Segurança |
A correção está quebrando ou não quebrando | Sem quebra |
Habilitado por padrão no .NET 9 | Não |
Motivo
Um caminho de arquivo de origem não limpo é usado como o caminho do arquivo de destino em um destes parâmetros:
- parâmetro
destinationFileName
do método ZipFileExtensions.ExtractToFile - parâmetro
path
do método File.Open - parâmetro
path
do método File.OpenWrite - parâmetro
path
do método File.Create - parâmetro
path
do construtor para FileStream - parâmetro
fileName
do construtor para FileInfo
Por padrão, essa regra analisa toda a base de código, mas isso é configurável.
Descrição da regra
O caminho do arquivo pode ser relativo e pode levar ao acesso ao sistema de arquivos fora do caminho de destino esperado do sistema de arquivos, levando a alterações maliciosas de configuração e execução remota de código por meio da técnica lay-and-wait.
Como corrigir violações
Não use o caminho do arquivo de origem para construir o caminho do arquivo de destino ou certifique-se de que o último caractere no caminho de extração seja o caractere separador de diretório.
Quando suprimir avisos
Você pode suprimir esse aviso se o caminho de origem sempre vier de uma fonte confiável.
Suprimir um aviso
Se você quiser apenas suprimir uma única violação, adicione diretivas de pré-processador ao seu arquivo de origem para desativar e, em seguida, reativar a regra.
#pragma warning disable CA5389
// The code that's violating the rule is on this line.
#pragma warning restore CA5389
Para desabilitar a regra de um arquivo, pasta ou projeto, defina sua gravidade como none
no arquivo de configuração.
[*.{cs,vb}]
dotnet_diagnostic.CA5389.severity = none
Para obter mais informações, consulte Como suprimir avisos de análise de código.
Configurar código para análise
Use as opções a seguir para configurar em quais partes da base de código executar essa regra.
Você pode configurar essas opções apenas para esta regra, para todas as regras às quais ela se aplica ou para todas as regras nesta categoria (Segurança) às quais ela se aplica. Para obter mais informações, consulte Opções de configuração da regra de qualidade de código.
Excluir símbolos específicos
Você pode excluir símbolos específicos, como tipos e métodos, da análise. Por exemplo, para especificar que a regra não deve ser executada em nenhum código dentro de tipos nomeados MyType
, adicione o seguinte par chave-valor a um arquivo .editorconfig em seu projeto:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Formatos de nome de símbolo permitidos no valor da opção (separados por |
):
- Somente nome do símbolo (inclui todos os símbolos com o nome, independentemente do tipo ou namespace que o contém).
- Nomes totalmente qualificados no formato de ID de documentação do símbolo. Cada nome de símbolo requer um prefixo de tipo de símbolo, como
M:
para métodos,T:
para tipos eN:
para namespaces. .ctor
para construtores e.cctor
para construtores estáticos.
Exemplos:
Valor da opção | Resumo |
---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
Corresponde a todos os símbolos denominados MyType . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
Corresponde a todos os símbolos denominados ou MyType1 MyType2 . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Corresponde ao método MyMethod específico com a assinatura totalmente qualificada especificada. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Corresponde a métodos MyMethod1 específicos e MyMethod2 com as respetivas assinaturas totalmente qualificadas. |
Excluir tipos específicos e seus tipos derivados
Você pode excluir tipos específicos e seus tipos derivados da análise. Por exemplo, para especificar que a regra não deve ser executada em nenhum método dentro de tipos nomeados MyType
e seus tipos derivados, adicione o seguinte par chave-valor a um arquivo .editorconfig em seu projeto:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Formatos de nome de símbolo permitidos no valor da opção (separados por |
):
- Somente nome do tipo (inclui todos os tipos com o nome, independentemente do tipo ou namespace que o contém).
- Nomes totalmente qualificados no formato de ID de documentação do símbolo, com um prefixo opcional
T:
.
Exemplos:
Valor da opção | Resumo |
---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Corresponde a todos os tipos nomeados MyType e todos os seus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
Corresponde a todos os tipos nomeados ou MyType1 e MyType2 todos os seus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Corresponde a um tipo MyType específico com um determinado nome totalmente qualificado e todos os seus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Corresponde a tipos MyType1 específicos e MyType2 com os respetivos nomes totalmente qualificados, e todos os seus tipos derivados. |
Exemplo
O trecho de código a seguir ilustra o padrão detetado por essa regra.
Violação:
using System.IO.Compression;
class TestClass
{
public void TestMethod(ZipArchiveEntry zipArchiveEntry)
{
zipArchiveEntry.ExtractToFile(zipArchiveEntry.FullName);
}
}
Solução:
using System;
using System.IO;
using System.IO.Compression;
class Program
{
static void Main(string[] args)
{
string zipPath = @".\result.zip";
Console.WriteLine("Provide path where to extract the zip file:");
string extractPath = Console.ReadLine();
// Normalizes the path.
extractPath = Path.GetFullPath(extractPath);
// Ensures that the last character on the extraction path
// is the directory separator char.
// Without this, a malicious zip file could try to traverse outside of the expected
// extraction path.
if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
extractPath += Path.DirectorySeparatorChar;
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
// Gets the full path to ensure that relative segments are removed.
string destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName));
// Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
// are case-insensitive.
if (destinationPath.StartsWith(extractPath, StringComparison.Ordinal))
entry.ExtractToFile(destinationPath);
}
}
}
}
}