CA5389: Nie dodawaj ścieżki elementu archiwum do docelowej ścieżki systemu plików

Właściwości Wartość
Identyfikator reguły CA5389
Tytuł Nie dodawaj ścieżki elementu archiwum do docelowej ścieżki systemu plików
Kategoria Bezpieczeństwo
Poprawka powodująca niezgodność lub niezgodność Niezgodność
Domyślnie włączone na platformie .NET 8 Nie.

Przyczyna

Ścieżka pliku źródłowego, która nie jest oczyszczona, jest używana jako ścieżka pliku docelowego w jednym z następujących parametrów:

Domyślnie ta reguła analizuje całą bazę kodu, ale można to skonfigurować.

Opis reguły

Ścieżka pliku może być względna i może prowadzić do dostępu do systemu plików poza oczekiwaną ścieżką docelową systemu plików, co prowadzi do złośliwych zmian konfiguracji i zdalnego wykonywania kodu za pomocą techniki lay-and-wait.

Jak naprawić naruszenia

Nie używaj ścieżki pliku źródłowego do konstruowania docelowej ścieżki pliku lub upewnij się, że ostatnim znakiem ścieżki wyodrębniania jest znak separatora katalogu.

Kiedy pomijać ostrzeżenia

To ostrzeżenie można pominąć, jeśli ścieżka źródłowa zawsze pochodzi z zaufanego źródła.

Pomijanie ostrzeżenia

Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.

#pragma warning disable CA5389
// The code that's violating the rule is on this line.
#pragma warning restore CA5389

Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none w pliku konfiguracji.

[*.{cs,vb}]
dotnet_diagnostic.CA5389.severity = none

Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.

Konfigurowanie kodu do analizowania

Użyj poniższych opcji, aby skonfigurować, które części bazy kodu mają być uruchamiane w tej regule.

Możesz skonfigurować te opcje tylko dla tej reguły, dla wszystkich reguł, do których ma ona zastosowanie, lub dla wszystkich reguł w tej kategorii (Zabezpieczenia), których dotyczy. Aby uzyskać więcej informacji, zobacz Opcje konfiguracji reguły jakości kodu.

Wykluczanie określonych symboli

Z analizy można wykluczyć określone symbole, takie jak typy i metody. Aby na przykład określić, że reguła nie powinna być uruchamiana w żadnym kodzie w typach o nazwie MyType, dodaj następującą parę klucz-wartość do pliku editorconfig w projekcie:

dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType

Dozwolone formaty nazw symboli w wartości opcji (oddzielone przez |):

  • Tylko nazwa symbolu (zawiera wszystkie symbole o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
  • W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu. Każda nazwa symboli wymaga prefiksu typu symboli, takiego jak M: metody, T: dla typów i N: przestrzeni nazw.
  • .ctor dla konstruktorów i .cctor konstruktorów statycznych.

Przykłady:

Wartość opcji Podsumowanie
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType Pasuje do wszystkich symboli o nazwie MyType.
dotnet_code_quality.CAXXXX.excluded_symbol_names = MyType1|MyType2 Pasuje do wszystkich symboli o nazwie MyType1 lub MyType2.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS.MyType.MyMethod(ParamType) Pasuje do określonej metody MyMethod z określonym w pełni kwalifikowanym podpisem.
dotnet_code_quality.CAXXXX.excluded_symbol_names = M:NS1.MyType1.MyMethod1(ParamType)|M:NS2.MyType2.MyMethod2(ParamType) Pasuje do określonych metod MyMethod1 i MyMethod2 z odpowiednimi w pełni kwalifikowanymi podpisami.

Wykluczanie określonych typów i ich typów pochodnych

Z analizy można wykluczyć określone typy i ich typy pochodne. Aby na przykład określić, że reguła nie powinna być uruchamiana na żadnych metodach w typach nazwanych MyType i ich typach pochodnych, dodaj następującą parę klucz-wartość do pliku .editorconfig w projekcie:

dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType

Dozwolone formaty nazw symboli w wartości opcji (oddzielone przez |):

  • Nazwa typu (zawiera tylko wszystkie typy o nazwie, niezależnie od typu zawierającego lub przestrzeni nazw).
  • W pełni kwalifikowane nazwy w formacie identyfikatora dokumentacji symbolu z opcjonalnym T: prefiksem.

Przykłady:

Wartość opcji Podsumowanie
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType Pasuje do wszystkich typów nazwanych MyType i wszystkich ich typów pochodnych.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = MyType1|MyType2 Dopasuje wszystkie typy o nazwie MyType1 lub MyType2 i wszystkie ich typy pochodne.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS.MyType Pasuje do określonego typu MyType z daną w pełni kwalifikowaną nazwą i wszystkimi jego typami pochodnymi.
dotnet_code_quality.CAXXXX.excluded_type_names_with_derived_types = M:NS1.MyType1|M:NS2.MyType2 Pasuje do określonych typów MyType1 i MyType2 z odpowiednimi w pełni kwalifikowanymi nazwami i wszystkimi ich typami pochodnymi.

Przykład

Poniższy fragment kodu ilustruje wzorzec wykryty przez tę regułę.

Naruszenie:

using System.IO.Compression;

class TestClass
{
    public void TestMethod(ZipArchiveEntry zipArchiveEntry)
    {
        zipArchiveEntry.ExtractToFile(zipArchiveEntry.FullName);
    }
}

Rozwiązanie:

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);
                }
            }
        }
    }
}