Skip to content

Commit e36f55a

Browse files
Improves season 1 level 3 solution (#113)
* 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>
1 parent 3ad54a4 commit e36f55a

File tree

1 file changed

+57
-30
lines changed

1 file changed

+57
-30
lines changed

Season-1/Level-3/solution.py

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,61 @@
1-
import os
1+
# Model solution follows
22

3-
# Example of a secure function that doesn't suffer from path traversal
4-
def safe_path(path):
5-
base_dir = os.path.dirname(os.path.abspath(__file__))
6-
filepath = os.path.normpath(os.path.join(base_dir, path))
7-
if base_dir != os.path.commonpath([base_dir, filepath]):
8-
return None
9-
return filepath
10-
11-
# Following the above, this is the secure version of the respective function on code.py
12-
def get_prof_picture(self, path=None):
13-
# setting a profile picture is optional
14-
if not path:
15-
pass
16-
17-
# defends against path traversal attacks
18-
if path.startswith('/') or path.startswith('..'):
19-
return None
20-
21-
# builds path
22-
base_dir = os.path.dirname(os.path.abspath(__file__))
23-
prof_picture_path = os.path.normpath(os.path.join(base_dir, path))
24-
if base_dir != os.path.commonpath([base_dir, prof_picture_path]):
25-
return None
26-
27-
with open(prof_picture_path, 'rb') as pic:
28-
picture = bytearray(pic.read())
29-
30-
# assume that image is returned on screen after this
31-
return prof_picture_path
3+
import os
4+
from flask import Flask, request
5+
6+
### Unrelated to the exercise -- Starts here -- Please ignore
7+
app = Flask(__name__)
8+
@app.route("/")
9+
def source():
10+
TaxPayer('foo', 'bar').get_tax_form_attachment(request.args["input"])
11+
TaxPayer('foo', 'bar').get_prof_picture(request.args["input"])
12+
### Unrelated to the exercise -- Ends here -- Please ignore
13+
14+
class TaxPayer:
15+
16+
def __init__(self, username, password):
17+
self.username = username
18+
self.password = password
19+
self.prof_picture = None
20+
self.tax_form_attachment = None
21+
22+
# returns the path of an optional profile picture that users can set
23+
def get_prof_picture(self, path=None):
24+
# setting a profile picture is optional
25+
if not path:
26+
pass
27+
28+
# builds path
29+
base_dir = os.path.dirname(os.path.abspath(__file__))
30+
prof_picture_path = os.path.normpath(os.path.join(base_dir, path))
31+
if not prof_picture_path.startswith(base_dir):
32+
return None
33+
34+
with open(prof_picture_path, 'rb') as pic:
35+
picture = bytearray(pic.read())
36+
37+
# assume that image is returned on screen after this
38+
return prof_picture_path
39+
40+
# returns the path of an attached tax form that every user should submit
41+
def get_tax_form_attachment(self, path=None):
42+
tax_data = None
43+
44+
# A tax form is required
45+
if not path:
46+
raise Exception("Error: Tax form is required for all users")
47+
48+
# Validate the path to prevent path traversal attacks
49+
base_dir = os.path.dirname(os.path.abspath(__file__))
50+
tax_form_path = os.path.normpath(os.path.join(base_dir, path))
51+
if not tax_form_path.startswith(base_dir):
52+
return None
53+
54+
with open(tax_form_path, 'rb') as form:
55+
tax_data = bytearray(form.read())
56+
57+
# assume that tax data is returned on screen after this
58+
return tax_form_path
3259

3360

3461
# Solution explanation

0 commit comments

Comments
 (0)