python.django.security.injection.path-traversal.path-traversal-join.path-traversal-join
semgrep
Author
6,591
Download Count*
License
Data from request is passed to os.path.join() and to open(). This is a path traversal vulnerability, which can lead to sensitive data being leaked. To mitigate, consider using os.path.abspath or os.path.realpath or Path library.
Run Locally
Run in CI
Defintion
rules:
- id: path-traversal-join
message: Data from request is passed to os.path.join() and to open(). This is a
path traversal vulnerability, which can lead to sensitive data being
leaked. To mitigate, consider using os.path.abspath or os.path.realpath or
Path library.
metadata:
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
references:
- https://owasp.org/www-community/attacks/Path_Traversal
category: security
technology:
- django
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Path Traversal
patterns:
- pattern-inside: |
def $F(...):
...
- pattern-not-inside: |
def $F(...):
...
os.path.abspath(...)
...
- pattern-not-inside: |
def $F(...):
...
os.path.realpath(...)
...
- pattern-either:
- pattern: open(os.path.join(..., request.$W.get(...), ...), ...)
- pattern: open(os.path.join(..., request.$W(...), ...), ...)
- pattern: open(os.path.join(..., request.$W, ...), ...)
- pattern: open(os.path.join(..., request.$W[...], ...), ...)
- pattern: |
$P = os.path.join(..., request.$W.get(...), ...)
...
open($P, ...)
- pattern: |
$P = os.path.join(..., request.$W(...), ...)
...
open($P, ...)
- pattern: |
$P = os.path.join(..., request.$W, ...)
...
open($P, ...)
- pattern: |
$P = os.path.join(..., request.$W[...], ...)
...
open($P, ...)
- pattern: |
$V = request.$W.get($X)
...
$P = os.path.join(..., $V, ...)
...
open($P, ...)
- pattern: |
$V = request.$W($X)
...
$P = os.path.join(..., $V, ...)
...
open($P, ...)
- pattern: |
$V = request.$W[$X]
...
$P = os.path.join(..., $V, ...)
...
open($P, ...)
- pattern: |
$V = request.$W
...
$P = os.path.join(..., $V, ...)
...
open($P, ...)
- pattern: |
$P = request.$W.get(...)
...
open(os.path.join(..., $P, ...), ...)
- pattern: |
$P = request.$W(...)
...
open(os.path.join(..., $P, ...), ...)
- pattern: |
$P = request.$W
...
open(os.path.join(..., $P, ...), ...)
- pattern: |
$P = request.$W[...]
...
open(os.path.join(..., $P, ...), ...)
languages:
- python
severity: WARNING
Examples
path-traversal-join.py
from django.http import HttpResponse
import os
def foo_1(request):
# ruleid: path-traversal-join
param = request.GET.get('param')
file_path = os.path.join("MY_SECRET", param)
f = open(file_path, 'r')
return HttpResponse(content=f, content_type="text/plain")
def foo_2(request):
# ok due to abspath
param = request.GET.get('param')
file_path = os.path.join("MY_SECRET", param)
file_path = os.path.abspath(file_path)
f = open(file_path, 'r')
return HttpResponse(content=f, content_type="text/plain")
def user_pic(request):
"""A view that is vulnerable to malicious file access."""
base_path = os.path.join(os.path.dirname(__file__), '../../badguys/static/images')
# ruleid: path-traversal-join
filename = request.GET.get('p')
data = open(os.path.join(base_path, filename), 'rb').read()
return HttpResponse(data, content_type=mimetypes.guess_type(filename)[0])
Short Link: https://sg.run/Dovo