Skip to content

Commit

Permalink
Improves season 1 level 3 solution (#113)
Browse files Browse the repository at this point in the history
* Reversing Season 2 level-3 with level-4 due to another initiative we are working on.

* adds mocha

* fixes template reference

* replaces executable

* improves the solution in Season-1/Level-3

* Potential fix for code scanning alert no. 46: Uncontrolled data used in path expression

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
  • Loading branch information
jkcso and github-advanced-security[bot] authored Jan 16, 2025
1 parent 3ad54a4 commit e36f55a
Showing 1 changed file with 57 additions and 30 deletions.
87 changes: 57 additions & 30 deletions Season-1/Level-3/solution.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,61 @@
import os
# Model solution follows

# Example of a secure function that doesn't suffer from path traversal
def safe_path(path):
base_dir = os.path.dirname(os.path.abspath(__file__))
filepath = os.path.normpath(os.path.join(base_dir, path))
if base_dir != os.path.commonpath([base_dir, filepath]):
return None
return filepath

# Following the above, this is the secure version of the respective function on code.py
def get_prof_picture(self, path=None):
# setting a profile picture is optional
if not path:
pass

# defends against path traversal attacks
if path.startswith('/') or path.startswith('..'):
return None

# builds path
base_dir = os.path.dirname(os.path.abspath(__file__))
prof_picture_path = os.path.normpath(os.path.join(base_dir, path))
if base_dir != os.path.commonpath([base_dir, prof_picture_path]):
return None

with open(prof_picture_path, 'rb') as pic:
picture = bytearray(pic.read())

# assume that image is returned on screen after this
return prof_picture_path
import os
from flask import Flask, request

### Unrelated to the exercise -- Starts here -- Please ignore
app = Flask(__name__)
@app.route("/")
def source():
TaxPayer('foo', 'bar').get_tax_form_attachment(request.args["input"])
TaxPayer('foo', 'bar').get_prof_picture(request.args["input"])
### Unrelated to the exercise -- Ends here -- Please ignore

class TaxPayer:

def __init__(self, username, password):
self.username = username
self.password = password
self.prof_picture = None
self.tax_form_attachment = None

# returns the path of an optional profile picture that users can set
def get_prof_picture(self, path=None):
# setting a profile picture is optional
if not path:
pass

# builds path
base_dir = os.path.dirname(os.path.abspath(__file__))
prof_picture_path = os.path.normpath(os.path.join(base_dir, path))
if not prof_picture_path.startswith(base_dir):
return None

with open(prof_picture_path, 'rb') as pic:
picture = bytearray(pic.read())

# assume that image is returned on screen after this
return prof_picture_path

# returns the path of an attached tax form that every user should submit
def get_tax_form_attachment(self, path=None):
tax_data = None

# A tax form is required
if not path:
raise Exception("Error: Tax form is required for all users")

# Validate the path to prevent path traversal attacks
base_dir = os.path.dirname(os.path.abspath(__file__))
tax_form_path = os.path.normpath(os.path.join(base_dir, path))
if not tax_form_path.startswith(base_dir):
return None

with open(tax_form_path, 'rb') as form:
tax_data = bytearray(form.read())

# assume that tax data is returned on screen after this
return tax_form_path


# Solution explanation
Expand Down

0 comments on commit e36f55a

Please sign in to comment.