csharp.lang.security.filesystem.unsafe-path-combine.unsafe-path-combine

profile photo of semgrepsemgrep
Author
unknown
Download Count*

String argument $A is used to read or write data from a file via Path.Combine without direct sanitization via Path.GetFileName. If the path is user-supplied data this can lead to path traversal.

Run Locally

Run in CI

Defintion

rules:
  - id: unsafe-path-combine
    mode: taint
    pattern-sources:
      - patterns:
          - pattern: $A
          - pattern-inside: |
              Path.Combine(...,$A,...)
          - pattern-inside: |
              public $TYPE $M(...,$A,...){...}
          - pattern-not-inside: |
              <... Path.GetFileName($A) != $A ...>
    pattern-sinks:
      - patterns:
          - focus-metavariable: $X
          - pattern: |
              File.$METHOD($X,...)
          - metavariable-regex:
              metavariable: $METHOD
              regex: (?i)^(read|write)
    pattern-sanitizers:
      - pattern: |
          Path.GetFileName(...)
      - patterns:
          - pattern-inside: |
              $X = Path.GetFileName(...);
              ...
          - pattern: $X
      - patterns:
          - pattern: $X
          - pattern-inside: |
              if(<... Path.GetFileName($X) != $X ...>){
                ...
                throw new $EXCEPTION(...);
              }
              ...
    message: String argument $A is used to read or write data from a file via
      Path.Combine without direct sanitization via Path.GetFileName. If the path
      is user-supplied data this can lead to path traversal.
    languages:
      - csharp
    severity: WARNING
    metadata:
      category: security
      confidence: MEDIUM
      references:
        - https://www.praetorian.com/blog/pathcombine-security-issues-in-aspnet-applications/
        - https://docs.microsoft.com/en-us/dotnet/api/system.io.path.combine?view=net-6.0#remarks
      technology:
        - .net
      cwe:
        - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
          ('Path Traversal')"
      owasp:
        - A05:2017 - Broken Access Control
        - A01:2021 - Broken Access Control
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Path Traversal

Examples

unsafe-path-combine.cs

public class Foo{

    public static bytes[] GetFileBad(string filename) { 
        // Ensure that all path elements are safe path elements. 
        if (string.IsNullOrEmpty(filename)) 
        {   
            throw new ArgumentNullException("error"); 
        }
        string filepath = Path.Combine("\\FILESHARE\images", filename); 
        // ruleid: unsafe-path-combine
        return File.ReadAllBytes(filepath);
    }

    public static bytes[] GetFileSafe(string filename) { 
        // Ensure that all path elements are safe path elements. 
        if (string.IsNullOrEmpty(filename)) 
        {   
            throw new ArgumentNullException("error"); 
        }
        filename = Path.GetFileName(filename);
        // ok: unsafe-path-combine
        string filepath = Path.Combine("\\FILESHARE\images", filename); 
        return File.ReadAllBytes(filepath);
    }

    public static bytes[] GetFileSafe2(string filename) { 
        // Ensure that all path elements are safe path elements. 
        if (string.IsNullOrEmpty(filename) || Path.GetFileName(filename) != filename) 
        {   
            throw new ArgumentNullException("error"); 
        }
        string filepath = Path.Combine("\\FILESHARE\images", filename); 
        // ok: unsafe-path-combine
        return File.ReadAllBytes(filepath);
    }

    public static bytes[] GetFileSafe3(string filename) { 
        // Ensure that all path elements are safe path elements. 
        if (string.IsNullOrEmpty(filename)) 
        {   
            throw new ArgumentNullException("error"); 
        }
        // ok: unsafe-path-combine
        string filepath = Path.Combine("\\FILESHARE\images", Path.GetFileName(filename)); 
    }

    public static bytes[] GetFileSafe4(string filename) { 
        // Ensure that all path elements are safe path elements. 
        if (string.IsNullOrEmpty(filename)) 
        {   
            throw new ArgumentNullException("error"); 
        }
        string otherPath = Path.GetFileName(filename);
        string safePath = Path.Combine("\\FILESHARE\images",otherPath);
        // ok: unsafe-path-combine
        return File.ReadAllBytes(safePath);
    }    
}