Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.2 Development Branch #523

Merged
merged 80 commits into from
Dec 29, 2024
Merged

v4.2 Development Branch #523

merged 80 commits into from
Dec 29, 2024

Conversation

donaldzou
Copy link
Owner

No description provided.

src/dashboard.py Fixed Show fixed Hide fixed
@donaldzou donaldzou linked an issue Nov 24, 2024 that may be closed by this pull request
22 tasks
src/DashboardConfig.py Fixed Show fixed Hide fixed
src/DashboardConfig.py Fixed Show fixed Hide fixed
src/Utilities.py Fixed Show resolved Hide resolved
@return: Boolean indicate if the text match the regex pattern
"""
pattern = re.compile(regex)
return pattern.search(text) is not None

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on a
user-provided value
may run slow on strings with many repetitions of '0.'.
This
regular expression
that depends on a
user-provided value
may run slow on strings starting with '_' and with many repetitions of '_a'.
self.__createDatabase()
with open(self.__configPath, "w+") as configFile:
self.createDatabase()
with open(self.configPath, "w+") as configFile:

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate the user-provided ConfigurationName before using it to construct the file path. We can use os.path.normpath to normalize the path and ensure it is within a safe directory. Additionally, we can use werkzeug.utils.secure_filename to sanitize the filename.

  1. Import secure_filename from werkzeug.utils.
  2. Normalize the constructed path using os.path.normpath.
  3. Ensure the normalized path starts with the intended base directory.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -1,2 +1,3 @@
 import itertools, random, shutil, sqlite3, configparser, hashlib, ipaddress, json, traceback, os, secrets, subprocess
+from werkzeug.utils import secure_filename
 import smtplib
@@ -473,3 +474,7 @@
         self.Protocol = "wg" if wg else "awg"
-        self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
+        safe_name = secure_filename(self.Name)
+        base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
+        self.configPath = os.path.normpath(os.path.join(base_path, f'{safe_name}.conf'))
+        if not self.configPath.startswith(base_path):
+            raise ValueError("Invalid configuration name resulting in path traversal")
         
@@ -490,3 +495,7 @@
             self.Name = data["ConfigurationName"]
-            self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
+            safe_name = secure_filename(self.Name)
+            base_path = self.__getProtocolPath()
+            self.configPath = os.path.normpath(os.path.join(base_path, f'{safe_name}.conf'))
+            if not self.configPath.startswith(base_path):
+                raise ValueError("Invalid configuration name resulting in path traversal")
             
EOF
@@ -1,2 +1,3 @@
import itertools, random, shutil, sqlite3, configparser, hashlib, ipaddress, json, traceback, os, secrets, subprocess
from werkzeug.utils import secure_filename
import smtplib
@@ -473,3 +474,7 @@
self.Protocol = "wg" if wg else "awg"
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
safe_name = secure_filename(self.Name)
base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
self.configPath = os.path.normpath(os.path.join(base_path, f'{safe_name}.conf'))
if not self.configPath.startswith(base_path):
raise ValueError("Invalid configuration name resulting in path traversal")

@@ -490,3 +495,7 @@
self.Name = data["ConfigurationName"]
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
safe_name = secure_filename(self.Name)
base_path = self.__getProtocolPath()
self.configPath = os.path.normpath(os.path.join(base_path, f'{safe_name}.conf'))
if not self.configPath.startswith(base_path):
raise ValueError("Invalid configuration name resulting in path traversal")

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if self.PrivateKey:
self.PublicKey = self.__getPublicKey()
self.Status = self.getStatus()
with open(self.configPath, 'r') as f:

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to ensure that the constructed file path is contained within a safe root folder. We can achieve this by normalizing the path using os.path.normpath and then checking that the normalized path starts with the root folder. This will prevent any path traversal attacks.

  1. Normalize the configPath using os.path.normpath.
  2. Check that the normalized path starts with the expected root directory.
  3. Raise an exception if the path is not within the expected directory.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -473,3 +473,6 @@
         self.Protocol = "wg" if wg else "awg"
-        self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
+        base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
+        self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
+        if not self.configPath.startswith(base_path):
+            raise ValueError("Invalid configuration path")
         
@@ -490,3 +493,6 @@
             self.Name = data["ConfigurationName"]
-            self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
+            base_path = self.__getProtocolPath()
+            self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
+            if not self.configPath.startswith(base_path):
+                raise ValueError("Invalid configuration path")
             
EOF
@@ -473,3 +473,6 @@
self.Protocol = "wg" if wg else "awg"
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
if not self.configPath.startswith(base_path):
raise ValueError("Invalid configuration path")

@@ -490,3 +493,6 @@
self.Name = data["ConfigurationName"]
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
base_path = self.__getProtocolPath()
self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
if not self.configPath.startswith(base_path):
raise ValueError("Invalid configuration path")

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
self.RestrictedPeers = []
restricted = sqlSelect("SELECT * FROM '%s_restrict_access'" % self.Name).fetchall()
for i in restricted:
self.RestrictedPeers.append(Peer(i, self))

def configurationFileChanged(self) :
mt = os.path.getmtime(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'))
mt = os.path.getmtime(self.configPath)

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to ensure that the constructed file path is safe and does not allow path traversal attacks. We can achieve this by normalizing the path and ensuring it is contained within a predefined safe directory. We will use os.path.normpath to normalize the path and then check if the resulting path starts with the expected base directory.

  1. Normalize the configPath using os.path.normpath.
  2. Ensure the normalized path starts with the base directory.
  3. Raise an exception if the path is not within the expected directory.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -473,3 +473,6 @@
         self.Protocol = "wg" if wg else "awg"
-        self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
+        base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
+        self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
+        if not self.configPath.startswith(base_path):
+            raise Exception("Invalid configuration path")
         
@@ -490,3 +493,6 @@
             self.Name = data["ConfigurationName"]
-            self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
+            base_path = self.__getProtocolPath()
+            self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
+            if not self.configPath.startswith(base_path):
+                raise Exception("Invalid configuration path")
             
EOF
@@ -473,3 +473,6 @@
self.Protocol = "wg" if wg else "awg"
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf') if wg else os.path.join(DashboardConfig.GetConfig("Server", "awg_conf_path")[1], f'{self.Name}.conf')
base_path = self.__getProtocolPath() if wg else DashboardConfig.GetConfig("Server", "awg_conf_path")[1]
self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
if not self.configPath.startswith(base_path):
raise Exception("Invalid configuration path")

@@ -490,3 +493,6 @@
self.Name = data["ConfigurationName"]
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
base_path = self.__getProtocolPath()
self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
if not self.configPath.startswith(base_path):
raise Exception("Invalid configuration path")

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if self.configurationFileChanged():
self.Peers = []
with open(os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{self.Name}.conf'), 'r') as configFile:
with open(self.configPath, 'r') as configFile:

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate the user-provided file path to ensure it does not lead to path traversal attacks. We can achieve this by normalizing the path and ensuring it is contained within a safe root directory. This involves the following steps:

  1. Normalize the path using os.path.normpath.
  2. Check that the normalized path starts with the expected base directory.
  3. Raise an exception or return an error response if the path is invalid.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -490,3 +490,6 @@
             self.Name = data["ConfigurationName"]
-            self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
+            base_path = self.__getProtocolPath()
+            self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
+            if not self.configPath.startswith(base_path):
+                raise ValueError("Invalid configuration name resulting in path traversal")
             
EOF
@@ -490,3 +490,6 @@
self.Name = data["ConfigurationName"]
self.configPath = os.path.join(self.__getProtocolPath(), f'{self.Name}.conf')
base_path = self.__getProtocolPath()
self.configPath = os.path.normpath(os.path.join(base_path, f'{self.Name}.conf'))
if not self.configPath.startswith(base_path):
raise ValueError("Invalid configuration name resulting in path traversal")

Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
}

if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate and sanitize the user-provided data["Backup"] value before using it to construct file paths. We can use os.path.normpath to normalize the path and ensure it does not contain any path traversal sequences. Additionally, we should check that the resulting path is within the intended backup directory.

  1. Normalize the data["Backup"] value using os.path.normpath.
  2. Ensure the normalized path is within the WGDashboard_Backup directory.
  3. Update the file path construction to use the validated and sanitized path.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2222,8 +2222,14 @@
         }
-     
-        if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
-                os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        
+        backup_file = os.path.normpath(data["Backup"])
+        backup_sql_file = os.path.normpath(data["Backup"].replace('.conf', '.sql'))
+        
+        wg_backup_path = os.path.join(path['wg'], 'WGDashboard_Backup')
+        awg_backup_path = os.path.join(path['awg'], 'WGDashboard_Backup')
+        
+        if (backup_file.startswith(wg_backup_path) and os.path.exists(os.path.join(wg_backup_path, backup_file)) and
+                os.path.exists(os.path.join(wg_backup_path, backup_sql_file))):
             protocol = "wg"
-        elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
-              os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        elif (backup_file.startswith(awg_backup_path) and os.path.exists(os.path.join(awg_backup_path, backup_file)) and
+              os.path.exists(os.path.join(awg_backup_path, backup_sql_file))):
             protocol = "awg"
@@ -2233,3 +2239,3 @@
         shutil.copy(
-            os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
+            os.path.join(path[protocol], 'WGDashboard_Backup', backup_file),
             os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
EOF
@@ -2222,8 +2222,14 @@
}

if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):

backup_file = os.path.normpath(data["Backup"])
backup_sql_file = os.path.normpath(data["Backup"].replace('.conf', '.sql'))

wg_backup_path = os.path.join(path['wg'], 'WGDashboard_Backup')
awg_backup_path = os.path.join(path['awg'], 'WGDashboard_Backup')

if (backup_file.startswith(wg_backup_path) and os.path.exists(os.path.join(wg_backup_path, backup_file)) and
os.path.exists(os.path.join(wg_backup_path, backup_sql_file))):
protocol = "wg"
elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
elif (backup_file.startswith(awg_backup_path) and os.path.exists(os.path.join(awg_backup_path, backup_file)) and
os.path.exists(os.path.join(awg_backup_path, backup_sql_file))):
protocol = "awg"
@@ -2233,3 +2239,3 @@
shutil.copy(
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
os.path.join(path[protocol], 'WGDashboard_Backup', backup_file),
os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
protocol = "wg"
elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate and sanitize the user-provided Backup value before using it in the os.path.join function. We can use the os.path.normpath function to normalize the path and ensure it does not contain any directory traversal sequences. Additionally, we should check that the resulting path is within the intended directory.

  1. Normalize the Backup value using os.path.normpath.
  2. Ensure the normalized path is within the WGDashboard_Backup directory.
  3. Update the code to use the validated and sanitized path.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2223,7 +2223,12 @@
      
-        if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
-                os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        backup_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"]))
+        backup_path_wg_sql = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
+        backup_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"]))
+        backup_path_awg_sql = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
+
+        if (backup_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_wg) and
+                backup_path_wg_sql.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_wg_sql)):
             protocol = "wg"
-        elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
-              os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        elif (backup_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_awg) and
+              backup_path_awg_sql.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_awg_sql)):
             protocol = "awg"
@@ -2233,3 +2238,3 @@
         shutil.copy(
-            os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
+            backup_path_wg if protocol == "wg" else backup_path_awg,
             os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
EOF
@@ -2223,7 +2223,12 @@

if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
backup_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"]))
backup_path_wg_sql = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
backup_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"]))
backup_path_awg_sql = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))

if (backup_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_wg) and
backup_path_wg_sql.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_wg_sql)):
protocol = "wg"
elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
elif (backup_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_awg) and
backup_path_awg_sql.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and os.path.exists(backup_path_awg_sql)):
protocol = "awg"
@@ -2233,3 +2238,3 @@
shutil.copy(
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
backup_path_wg if protocol == "wg" else backup_path_awg,
os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
protocol = "wg"
elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate and sanitize the user-provided data["Backup"] value before using it in file path operations. We can use os.path.normpath to normalize the path and ensure it does not contain any directory traversal sequences. Additionally, we can check that the resulting path is within a predefined safe directory.

  1. Normalize the data["Backup"] value using os.path.normpath.
  2. Ensure the normalized path is within the WGDashboard_Backup directory.
  3. Use the sanitized path for file operations.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2223,7 +2223,14 @@
      
-        if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
-                os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        backup_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"]))
+        backup_sql_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
+        backup_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"]))
+        backup_sql_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
+        
+        if (backup_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and
+                backup_sql_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and
+                os.path.exists(backup_path_wg) and os.path.exists(backup_sql_path_wg)):
             protocol = "wg"
-        elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
-              os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
+        elif (backup_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and
+              backup_sql_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and
+              os.path.exists(backup_path_awg) and os.path.exists(backup_sql_path_awg)):
             protocol = "awg"
EOF
@@ -2223,7 +2223,14 @@

if (os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
backup_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"]))
backup_sql_path_wg = os.path.normpath(os.path.join(path['wg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))
backup_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"]))
backup_sql_path_awg = os.path.normpath(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))

if (backup_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and
backup_sql_path_wg.startswith(os.path.join(path['wg'], 'WGDashboard_Backup')) and
os.path.exists(backup_path_wg) and os.path.exists(backup_sql_path_wg)):
protocol = "wg"
elif (os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"])) and
os.path.exists(os.path.join(path['awg'], 'WGDashboard_Backup', data["Backup"].replace('.conf', '.sql')))):
elif (backup_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and
backup_sql_path_awg.startswith(os.path.join(path['awg'], 'WGDashboard_Backup')) and
os.path.exists(backup_path_awg) and os.path.exists(backup_sql_path_awg)):
protocol = "awg"
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

shutil.copy(
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup', data["Backup"]),
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{data["ConfigurationName"]}.conf')
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to ensure that the user-provided Backup value is validated and sanitized before being used in file path operations. We can achieve this by normalizing the path and ensuring it is contained within a safe root directory. This will prevent directory traversal attacks and ensure that only intended files are accessed.

  1. Normalize the Backup path using os.path.normpath.
  2. Ensure the normalized path starts with the intended root directory.
  3. Raise an exception or return an error response if the validation fails.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2232,4 +2232,7 @@
         
+        backup_path = os.path.normpath(os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]))
+        if not backup_path.startswith(os.path.join(path[protocol], 'WGDashboard_Backup')):
+            return ResponseObject(False, "Invalid backup path")
         shutil.copy(
-            os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
+            backup_path,
             os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
EOF
@@ -2232,4 +2232,7 @@

backup_path = os.path.normpath(os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]))
if not backup_path.startswith(os.path.join(path[protocol], 'WGDashboard_Backup')):
return ResponseObject(False, "Invalid backup path")
shutil.copy(
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
backup_path,
os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], 'WGDashboard_Backup', data["Backup"]),
os.path.join(DashboardConfig.GetConfig("Server", "wg_conf_path")[1], f'{data["ConfigurationName"]}.conf')
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to ensure that the ConfigurationName provided by the user does not contain any malicious input that could lead to path traversal attacks. We can achieve this by normalizing the path and ensuring it stays within a predefined safe directory. Additionally, we can use a library function like werkzeug.utils.secure_filename to sanitize the filename.

  1. Import the secure_filename function from werkzeug.utils.
  2. Use secure_filename to sanitize the ConfigurationName before using it in the file path.
  3. Normalize the path and ensure it stays within the intended directory.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -1,2 +1,3 @@
 import itertools, random, shutil, sqlite3, configparser, hashlib, ipaddress, json, traceback, os, secrets, subprocess
+from werkzeug.utils import secure_filename
 import smtplib
@@ -2232,6 +2233,8 @@
         
-        shutil.copy(
-            os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
-            os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
-        )
+        safe_configuration_name = secure_filename(data["ConfigurationName"])
+        backup_path = os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"])
+        config_path = os.path.join(path[protocol], f'{safe_configuration_name}.conf')
+        if not os.path.commonpath([config_path, path[protocol]]) == path[protocol]:
+            return ResponseObject(False, "Invalid configuration name.")
+        shutil.copy(backup_path, config_path)
         WireguardConfigurations[data['ConfigurationName']] = WireguardConfiguration(data=data, name=data['ConfigurationName']) if protocol == 'wg' else AmneziaWireguardConfiguration(data=data, name=data['ConfigurationName'])
EOF
@@ -1,2 +1,3 @@
import itertools, random, shutil, sqlite3, configparser, hashlib, ipaddress, json, traceback, os, secrets, subprocess
from werkzeug.utils import secure_filename
import smtplib
@@ -2232,6 +2233,8 @@

shutil.copy(
os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"]),
os.path.join(path[protocol], f'{data["ConfigurationName"]}.conf')
)
safe_configuration_name = secure_filename(data["ConfigurationName"])
backup_path = os.path.join(path[protocol], 'WGDashboard_Backup', data["Backup"])
config_path = os.path.join(path[protocol], f'{safe_configuration_name}.conf')
if not os.path.commonpath([config_path, path[protocol]]) == path[protocol]:
return ResponseObject(False, "Invalid configuration name.")
shutil.copy(backup_path, config_path)
WireguardConfigurations[data['ConfigurationName']] = WireguardConfiguration(data=data, name=data['ConfigurationName']) if protocol == 'wg' else AmneziaWireguardConfiguration(data=data, name=data['ConfigurationName'])
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
file = request.args.get('file')
if file is None or len(file) == 0:
return ResponseObject(False, "Please specify a file")
if os.path.exists(os.path.join('download', file)):

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to validate the file parameter to ensure it does not contain any malicious input that could lead to path traversal attacks. The best way to do this is to normalize the path and ensure it is contained within the intended directory. We can use os.path.normpath to remove any .. segments and then check that the resulting path starts with the intended directory.

Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2801,4 +2801,8 @@
         return ResponseObject(False, "Please specify a file")
-    if os.path.exists(os.path.join('download', file)):
-        return send_file(os.path.join('download', file), as_attachment=True)
+    safe_base_path = os.path.abspath('download')
+    full_path = os.path.abspath(os.path.join(safe_base_path, file))
+    if not full_path.startswith(safe_base_path):
+        return ResponseObject(False, "Invalid file path")
+    if os.path.exists(full_path):
+        return send_file(full_path, as_attachment=True)
     else:
EOF
@@ -2801,4 +2801,8 @@
return ResponseObject(False, "Please specify a file")
if os.path.exists(os.path.join('download', file)):
return send_file(os.path.join('download', file), as_attachment=True)
safe_base_path = os.path.abspath('download')
full_path = os.path.abspath(os.path.join(safe_base_path, file))
if not full_path.startswith(safe_base_path):
return ResponseObject(False, "Invalid file path")
if os.path.exists(full_path):
return send_file(full_path, as_attachment=True)
else:
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if file is None or len(file) == 0:
return ResponseObject(False, "Please specify a file")
if os.path.exists(os.path.join('download', file)):
return send_file(os.path.join('download', file), as_attachment=True)

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix AI about 2 months ago

To fix the problem, we need to ensure that the file path constructed from user input is safe and does not allow access to files outside the intended directory. We can achieve this by normalizing the path and ensuring it starts with the intended base directory.

  1. Normalize the path using os.path.normpath to remove any ".." segments.
  2. Check that the normalized path starts with the 'download' directory.
Suggested changeset 1
src/dashboard.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/dashboard.py b/src/dashboard.py
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -2801,4 +2801,8 @@
         return ResponseObject(False, "Please specify a file")
-    if os.path.exists(os.path.join('download', file)):
-        return send_file(os.path.join('download', file), as_attachment=True)
+    base_path = os.path.abspath('download')
+    full_path = os.path.normpath(os.path.join(base_path, file))
+    if not full_path.startswith(base_path):
+        return ResponseObject(False, "Invalid file path")
+    if os.path.exists(full_path):
+        return send_file(full_path, as_attachment=True)
     else:
EOF
@@ -2801,4 +2801,8 @@
return ResponseObject(False, "Please specify a file")
if os.path.exists(os.path.join('download', file)):
return send_file(os.path.join('download', file), as_attachment=True)
base_path = os.path.abspath('download')
full_path = os.path.normpath(os.path.join(base_path, file))
if not full_path.startswith(base_path):
return ResponseObject(False, "Invalid file path")
if os.path.exists(full_path):
return send_file(full_path, as_attachment=True)
else:
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
@donaldzou donaldzou merged commit ef7b5ac into main Dec 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

v4.2.0 Road Map
2 participants