CA5389: No agregar la ruta de acceso del elemento de archivo a la ruta de acceso del sistema de archivos de destino
Propiedad | Value |
---|---|
Identificador de la regla | CA5389 |
Título | No agregar la ruta de acceso del elemento de archivo a la ruta de acceso del sistema de archivos de destino |
Categoría | Seguridad |
La corrección interrumpe o no interrumpe | Poco problemático |
Habilitado de forma predeterminada en .NET 9 | No |
Causa
Se utiliza una ruta de acceso del archivo de origen no saneada como ruta de acceso del archivo de destino en uno de estos parámetros:
- parámetro
destinationFileName
del método ZipFileExtensions.ExtractToFile - parámetro
path
del método File.Open - parámetro
path
del método File.OpenWrite - parámetro
path
del método File.Create - parámetro
path
del constructor para FileStream - parámetro
fileName
del constructor para FileInfo
De forma predeterminada, esta regla analiza todo el código base, pero esto es configurable.
Descripción de la regla
La ruta de acceso de archivo puede ser relativa y puede dar lugar a un acceso al sistema de archivos fuera de la ruta de destino del sistema de archivos esperada, con una generación de cambios de configuración malintencionados y la ejecución remota de código mediante la técnica conocida como "lay-and-wait".
Cómo corregir infracciones
No use la ruta de acceso del archivo de origen para construir la ruta de acceso del archivo de destino o asegúrese de que el último carácter de la ruta de extracción sea el carácter separador de directorio.
Cuándo suprimir las advertencias
Puede suprimir esta advertencia si la ruta de acceso de origen siempre proviene de un origen de confianza.
Supresión de una advertencia
Si solo quiere suprimir una única infracción, agregue directivas de preprocesador al archivo de origen para deshabilitar y volver a habilitar la regla.
#pragma warning disable CA5389
// The code that's violating the rule is on this line.
#pragma warning restore CA5389
Para deshabilitar la regla de un archivo, una carpeta o un proyecto, establezca su gravedad en none
del archivo de configuración.
[*.{cs,vb}]
dotnet_diagnostic.CA5389.severity = none
Para obtener más información, consulte Procedimiento para suprimir advertencias de análisis de código.
Configuración del código para analizar
Use las opciones siguientes para configurar en qué partes del código base se va a ejecutar esta regla.
Puede configurar estas opciones solo para esta regla, para todas las reglas a las que se aplica o para todas las reglas de esta categoría (Seguridad) a las que se aplica. Para más información, vea Opciones de configuración de reglas de calidad de código.
Exclusión de símbolos específicos
Puede excluir símbolos específicos, como tipos y métodos, del análisis. Por ejemplo, para especificar que la regla no se debe ejecutar en ningún código dentro de los tipos con el nombre MyType
, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType
Formatos de nombre de símbolo permitidos en el valor de opción (separados por |
):
- Solo nombre de símbolo (incluye todos los símbolos con el nombre, con independencia del tipo contenedor o el espacio de nombres).
- Nombres completos en el formato de id. de documentación del símbolo. Cada nombre de símbolo necesita un prefijo de tipo símbolo, como
M:
para los métodos,T:
para los tipos yN:
para los espacios de nombres. .ctor
para los constructores y.cctor
para los constructores estáticos.
Ejemplos:
Valor de la opción | Resumen |
---|---|
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType |
Coincide con todos los símbolos denominados MyType . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 |
Coincide con todos los símbolos denominados MyType1 o MyType2 . |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) |
Coincide con un método MyMethod concreto con la signatura completa especificada. |
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) |
Coincide con los métodos MyMethod1 y MyMethod2 concretos con las signaturas completas especificadas. |
Exclusión de tipos específicos y sus tipos derivados
Puede excluir tipos específicos y sus tipos derivados del análisis. Por ejemplo, para especificar que la regla no se debe ejecutar en ningún método dentro de los tipos con el nombre MyType
y sus tipos derivados, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType
Formatos de nombre de símbolo permitidos en el valor de opción (separados por |
):
- Solo nombre de tipo (incluye todos los tipos con el nombre, con independencia del tipo contenedor o el espacio de nombres).
- Nombres completos en el formato de identificador de documentación del símbolo, con un prefijo
T:
opcional.
Ejemplos:
Valor de la opción | Resumen |
---|---|
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType |
Coincide con todos los tipos denominados MyType y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 |
Coincide con todos los tipos denominados MyType1 o MyType2 , y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType |
Coincide con un tipo MyType específico con el nombre completo dado y todos sus tipos derivados. |
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 |
Coincide con los tipos MyType1 y MyType2 específicos con los correspondientes nombres completos y todos sus tipos derivados. |
Ejemplo
El fragmento de código siguiente muestra el patrón que detecta esta regla.
Infracción:
using System.IO.Compression;
class TestClass
{
public void TestMethod(ZipArchiveEntry zipArchiveEntry)
{
zipArchiveEntry.ExtractToFile(zipArchiveEntry.FullName);
}
}
Solución:
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);
}
}
}
}
}