diff --git a/.github/workflows/security-assessment.yml b/.github/workflows/security-assessment.yml index 178a5c5..40b8ddd 100644 --- a/.github/workflows/security-assessment.yml +++ b/.github/workflows/security-assessment.yml @@ -37,6 +37,10 @@ jobs: - name: Install dependencies run: npm ci + - name: Audit dependencies + run: npm audit --audit-level=high + continue-on-error: true + - name: Start server in background run: | npm start & diff --git a/Vulnerability_Tool/Identified Vulnerabilities Report.docx b/Vulnerability_Tool/Identified Vulnerabilities Report.docx deleted file mode 100644 index af11626..0000000 Binary files a/Vulnerability_Tool/Identified Vulnerabilities Report.docx and /dev/null differ diff --git a/Vulnerability_Tool/Vulnerability Report.docx b/Vulnerability_Tool/Vulnerability Report.docx deleted file mode 100644 index 4aed10b..0000000 Binary files a/Vulnerability_Tool/Vulnerability Report.docx and /dev/null differ diff --git a/Vulnerability_Tool/Vulnerability_Scanner_V1.1.py b/Vulnerability_Tool/Vulnerability_Scanner_V1.1.py deleted file mode 100644 index cabe7cc..0000000 --- a/Vulnerability_Tool/Vulnerability_Scanner_V1.1.py +++ /dev/null @@ -1,113 +0,0 @@ -# Importing modules to assist with vulnerability scanning and detecting -import os -import re - -# Define text Colour -class Colour: - GREEN = '\033[92m' - RED = '\033[91m' - BLUE = '\033[94m' - YELLOW = '\033[93m' - V_PATTEN_NAME = '\033[38;5;208m' # Orange names - NORMAL = '\033[0m' - -# Define Vulnerability Pattern -V_Patterns = { - "Sql_Injection": re.compile(r'\.query\s*\(.*\+.*\)'), - "XSS": re.compile(r'res\.send\s*\(.*\+.*\)'), - "Command_Injection": re.compile(r'exec\s*\(.*\+.*\)'), - "insecure_file_handling": re.compile(r'fs\.unlink\s*\(.*\)'), - "insecure_file_upload": re.compile(r'multer\s*\(\s*{.*dest.*}\s*\)'), -# New Vulnerability Pattern identifications Added in "V1.1" - "Eval_Function": re.compile(r'eval\s*\(.*\)'), - "Directory_Movement": re.compile(r'fs\.readFile\s*\(.*\.\.\/.*\)'), - "Insecure_Token_Generation": re.compile(r'Math\.random\s*\(\)'), - "Dangerous_Permission_Level": re.compile(r'fs\.chmod\s*\(.*\)'), - "Redirects": re.compile(r'res\.redirect\s*\(.*req\.query\..*\)') - -} -# Opening the files for processing -def AnalyseFile(FileLocation): - vulnerabilities = {key: [] for key in V_Patterns.keys()} - try: - with open(FileLocation, 'r', encoding='utf-8') as file: - Data = file.read() - except Exception as e: - print(f"Error reading file {FileLocation}: {e}") - return None - -# Check for vulnerabilities based on pre set V_Patterns - for key, pattern in V_Patterns.items(): - matches = pattern.findall(Data) - if matches: - vulnerabilities[key].extend(matches) - - return vulnerabilities - -# Formatting files for list -def list_files(): - return [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.js')] - -def OrderedF(Dataset): - print("|--------------------------------|\n| JavaScript files for Analysis: |\n|--------------------------------|") - for i, file in enumerate(Dataset, 1): - print(f"{i} - {file}") - -# Result box for outcome of vulnerability scan -def PrintOutcome(Data): - Outside = max(len(line) for line in Data.splitlines()) + 4 - print('|' + '-' * (Outside - 2) + '|') - for line in Data.splitlines(): - print(f"| {line.ljust(Outside - 4)} |") - print('|' + '-' * (Outside - 2) + '|') - -# Catches not JavaScript files in directory -def main(): - Dataset = list_files() - if not Dataset: - print("No .js files found") - return - -# Terminate program when "end" is entered in - while True: - OrderedF(Dataset) - User_Input = input("\nPlease enter a file number from the listed options\nor\nType 'end' to quit the application \n> ") - if User_Input == 'end': - break - -# Catches an input ouside of the file number range - try: - file_index = int(User_Input) - 1 - if file_index < 0 or file_index >= len(Dataset): - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease enter the file number from the listed options") - continue - - JsFile = Dataset[file_index] - print(f"{Colour.YELLOW}\nAnalysing: {Colour.NORMAL}{JsFile}") - vulnerabilities = AnalyseFile(JsFile) - -# This should not get called. However, is left here to future proof the application - if not vulnerabilities: - Outcome = f"Could not read file: {JsFile}" - -# No vulnerabilities have been located - elif not any(vulnerabilities.values()): - Outcome = f"{Colour.GREEN}No vulnerabilities found.{Colour.NORMAL}" - -# Lists the potentiaal vulnerability found - else: - Outcome = f"{Colour.RED}Potential Vulnerability Found: {Colour.NORMAL}\n" - for key, found in vulnerabilities.items(): - if found: - Outcome += f"{Colour.V_PATTEN_NAME} {key.replace('_', ' ').title()} vulnerabilities:{Colour.NORMAL}\n" - for q in found: - Outcome += f" - {q}\n" - -# Print Result - PrintOutcome(Outcome) -# Triggers invalid input - chance to try again - except ValueError: - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease Input a number.") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Vulnerability_Tool/Vulnerability_Scanner_V1.2.py b/Vulnerability_Tool/Vulnerability_Scanner_V1.2.py deleted file mode 100644 index 1e931ba..0000000 --- a/Vulnerability_Tool/Vulnerability_Scanner_V1.2.py +++ /dev/null @@ -1,119 +0,0 @@ -# Importing modules to assist with vulnerability scanning and detecting -import os -import re - -# Define text Colour -class Colour: - GREEN = '\033[92m' - RED = '\033[91m' - BLUE = '\033[94m' - YELLOW = '\033[93m' - V_PATTEN_NAME = '\033[38;5;208m' # Orange names - NORMAL = '\033[0m' - -# Define Vulnerability Pattern -V_Patterns = { - "Sql_Injection": re.compile(r'\.query\s*\(.*\+.*\)'), - "XSS": re.compile(r'res\.send\s*\(.*\+.*\)'), - "Command_Injection": re.compile(r'exec\s*\(.*\+.*\)'), - "insecure_file_handling": re.compile(r'fs\.unlink\s*\(.*\)'), - "insecure_file_upload": re.compile(r'multer\s*\(\s*{.*dest.*}\s*\)'), -# New Vulnerability Pattern Identifications Added in "V1.1" - "Eval_Function": re.compile(r'eval\s*\(.*\)'), - "Directory_Movement": re.compile(r'fs\.readFile\s*\(.*\.\.\/.*\)'), - "Insecure_Token_Generation": re.compile(r'Math\.random\s*\(\)'), - "Dangerous_Permission_Level": re.compile(r'fs\.chmod\s*\(.*\)'), - "Redirects": re.compile(r'res\.redirect\s*\(.*req\.query\..*\)'), -# New Vulnerability Pattern Identifications Added in "V1.2" - "API_Key_Hardcoded": re.compile(r'api_key\s*=\s*[\'"].*[\'"]'), - "Weak_Hashing_Algorithm": re.compile(r'(md5|sha1|des)\s*\('), - "Plainetext_Credentials": re.compile(r'(username|password)\s*=\s*[\'"].*[\'"]'), - "Insecure_SSL_Configeration": re.compile(r'server\.listen\s*\(.*http.*\)'), - "HTTP_Called": re.compile(r'http\.get\s*\(.*\)') - -} -# Opening the files for processing -def AnalyseFile(FileLocation): - vulnerabilities = {key: [] for key in V_Patterns.keys()} - try: - with open(FileLocation, 'r', encoding='utf-8') as file: - Data = file.read() - except Exception as e: - print(f"Error reading file {FileLocation}: {e}") - return None - -# Check for vulnerabilities based on pre set V_Patterns - for key, pattern in V_Patterns.items(): - matches = pattern.findall(Data) - if matches: - vulnerabilities[key].extend(matches) - - return vulnerabilities - -# Formatting files for list -def list_files(): - return [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.js')] - -def OrderedF(Dataset): - print("|--------------------------------|\n| JavaScript files for Analysis: |\n|--------------------------------|") - for i, file in enumerate(Dataset, 1): - print(f"{i} - {file}") - -# Result box for outcome of vulnerability scan -def PrintOutcome(Data): - Outside = max(len(line) for line in Data.splitlines()) + 4 - print('|' + '-' * (Outside - 2) + '|') - for line in Data.splitlines(): - print(f"| {line.ljust(Outside - 4)} |") - print('|' + '-' * (Outside - 2) + '|') - -# Catches not JavaScript files in directory -def main(): - Dataset = list_files() - if not Dataset: - print("No .js files found") - return - -# Terminate program when "end" is entered in - while True: - OrderedF(Dataset) - User_Input = input("\nPlease enter a file number from the listed options\nor\nType 'end' to quit the application \n> ") - if User_Input == 'end': - break - -# Catches an input ouside of the file number range - try: - file_index = int(User_Input) - 1 - if file_index < 0 or file_index >= len(Dataset): - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease enter the file number from the listed options") - continue - - JsFile = Dataset[file_index] - print(f"{Colour.YELLOW}\nAnalysing: {Colour.NORMAL}{JsFile}") - vulnerabilities = AnalyseFile(JsFile) - -# This should not get called. However, is left here to future proof the application - if not vulnerabilities: - Outcome = f"Could not read file: {JsFile}" - -# No vulnerabilities have been located - elif not any(vulnerabilities.values()): - Outcome = f"{Colour.GREEN}No vulnerabilities found.{Colour.NORMAL}" - -# Lists the potentiaal vulnerability found - else: - Outcome = f"{Colour.RED}Potential Vulnerability Found: {Colour.NORMAL}\n" - for key, found in vulnerabilities.items(): - if found: - Outcome += f"{Colour.V_PATTEN_NAME} {key.replace('_', ' ').title()} vulnerabilities:{Colour.NORMAL}\n" - for q in found: - Outcome += f" - {q}\n" - -# Print Result - PrintOutcome(Outcome) -# Triggers invalid input - chance to try again - except ValueError: - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease Input a number.") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Vulnerability_Tool/Vulnerability_Scanner_V1.3.py b/Vulnerability_Tool/Vulnerability_Scanner_V1.3.py deleted file mode 100644 index b1828c8..0000000 --- a/Vulnerability_Tool/Vulnerability_Scanner_V1.3.py +++ /dev/null @@ -1,125 +0,0 @@ -# Importing modules to assist with vulnerability scanning and detecting -import os -import re - -# Define text Colour -class Colour: - GREEN = '\033[92m' - RED = '\033[91m' - BLUE = '\033[94m' - YELLOW = '\033[93m' - V_PATTEN_NAME = '\033[38;5;208m' # Orange names - NORMAL = '\033[0m' - -# Define Vulnerability Pattern -V_Patterns = { - "Sql_Injection": re.compile(r'\.query\s*\(.*\+.*\)'), - "XSS": re.compile(r'res\.send\s*\(.*\+.*\)'), - "Command_Injection": re.compile(r'exec\s*\(.*\+.*\)'), - "insecure_file_handling": re.compile(r'fs\.unlink\s*\(.*\)'), - "insecure_file_upload": re.compile(r'multer\s*\(\s*{.*dest.*}\s*\)'), -# New Vulnerability Pattern Identifications Added in "V1.1" - "Eval_Function": re.compile(r'eval\s*\(.*\)'), - "Directory_Movement": re.compile(r'fs\.readFile\s*\(.*\.\.\/.*\)'), - "Insecure_Token_Generation": re.compile(r'Math\.random\s*\(\)'), - "Dangerous_Permission_Level": re.compile(r'fs\.chmod\s*\(.*\)'), - "Redirects": re.compile(r'res\.redirect\s*\(.*req\.query\..*\)'), -# New Vulnerability Pattern Identifications Added in "V1.2" - "API_Key_Hardcoded": re.compile(r'api_key\s*=\s*[\'"].*[\'"]'), - "Weak_Hashing_Algorithm": re.compile(r'(md5|sha1|des)\s*\('), - "Planetext_Credentials": re.compile(r'(username|password)\s*=\s*[\'"].*[\'"]'), - "Insecure_SSL_Configeration": re.compile(r'server\.listen\s*\(.*http.*\)'), - "HTTP_Called": re.compile(r'http\.get\s*\(.*\)'), -# New Vulnerability Pattern Identifications Added in "V1.3" - "Sensitive_Data_Logging": re.compile(r'console\.(log|debug|error|warn)\s*\(.*(password|secret|key|token).*\)'), - "JSON_Parsing_No_Validation": re.compile(r'JSON\.parse\s*\(.*req\.(body|query|params).*\)'), - "Environment_Variables_In_Planetext": re.compile(r'process\.env\.[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*[\'"].+[\'"]'), - "Debug_Left_Exposed": re.compile(r'app\.get\s*\([\'"].*debug.*[\'"],.*\)'), - "Insecure_File_Paths": re.compile(r'(fs\.(readFile|writeFile))\s*\(.*req\.(body|query|params)\.path.*\)'), - "Unsecured_Spawn": re.compile(r'spawn\s*\(.*\)') -} -# Opening the files for processing -def AnalyseFile(FileLocation): - vulnerabilities = {key: [] for key in V_Patterns.keys()} - try: - with open(FileLocation, 'r', encoding='utf-8') as file: - Data = file.read() - except Exception as e: - print(f"Error reading file {FileLocation}: {e}") - return None - -# Check for vulnerabilities based on pre set V_Patterns - for key, pattern in V_Patterns.items(): - matches = pattern.findall(Data) - if matches: - vulnerabilities[key].extend(matches) - - return vulnerabilities - -# Formatting files for list -def list_files(): - return [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.js')] - -def OrderedF(Dataset): - print("|--------------------------------|\n| JavaScript files for Analysis: |\n|--------------------------------|") - for i, file in enumerate(Dataset, 1): - print(f"{i} - {file}") - -# Result box for outcome of vulnerability scan -def PrintOutcome(Data): - Outside = max(len(line) for line in Data.splitlines()) + 4 - print('|' + '-' * (Outside - 2) + '|') - for line in Data.splitlines(): - print(f"| {line.ljust(Outside - 4)} |") - print('|' + '-' * (Outside - 2) + '|') - -# Catches not JavaScript files in directory -def main(): - Dataset = list_files() - if not Dataset: - print("No .js files found") - return - -# Terminate program when "end" is entered in - while True: - OrderedF(Dataset) - User_Input = input("\nPlease enter a file number from the listed options\nor\nType 'end' to quit the application \n> ") - if User_Input == 'end': - break - -# Catches an input ouside of the file number range - try: - file_index = int(User_Input) - 1 - if file_index < 0 or file_index >= len(Dataset): - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease enter the file number from the listed options") - continue - - JsFile = Dataset[file_index] - print(f"{Colour.YELLOW}\nAnalysing: {Colour.NORMAL}{JsFile}") - vulnerabilities = AnalyseFile(JsFile) - -# This should not get called. However, is left here to future proof the application - if not vulnerabilities: - Outcome = f"Could not read file: {JsFile}" - -# No vulnerabilities have been located - elif not any(vulnerabilities.values()): - Outcome = f"{Colour.GREEN}No vulnerabilities found.{Colour.NORMAL}" - -# Lists the potentiaal vulnerability found - else: - Outcome = f"{Colour.RED}Potential Vulnerability Found: {Colour.NORMAL}\n" - for key, found in vulnerabilities.items(): - if found: - Outcome += f"{Colour.V_PATTEN_NAME} {key.replace('_', ' ').title()} vulnerabilities:{Colour.NORMAL}\n" - for q in found: - Outcome += f" - {q}\n" - -# Print Result - PrintOutcome(Outcome) -# Triggers invalid input - chance to try again - except ValueError: - print(f"\n{Colour.BLUE}|---------------|\n| Invalid input |\n|---------------|{Colour.NORMAL}\nPlease Input a number.") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Vulnerability_Tool/Vulnerability_Scanner_V1.4.py b/Vulnerability_Tool/Vulnerability_Scanner_V1.4.py deleted file mode 100644 index c50e28c..0000000 --- a/Vulnerability_Tool/Vulnerability_Scanner_V1.4.py +++ /dev/null @@ -1,160 +0,0 @@ -import os -import re -import sys -import docx - -# Define Vulnerability Patterns for JavaScript files -JS_Patterns = { - "Sql_Injection": re.compile(r'\.query\s*\(.*\+.*\)'), - "XSS": re.compile(r'res\.send\s*\(.*\+.*\)'), - "Command_Injection": re.compile(r'exec\s*\(.*\+.*\)'), - "insecure_file_handling": re.compile(r'fs\.unlink\s*\(.*\)'), - "insecure_file_upload": re.compile(r'multer\s*\(\s*{.*dest.*}\s*\)'), - "Eval_Function": re.compile(r'eval\s*\(.*\)'), - "Directory_Movement": re.compile(r'fs\.readFile\s*\(.*\.\./.*\)'), - "Insecure_Token_Generation": re.compile(r'Math\.random\s*\(\)'), - "Dangerous_Permission_Level": re.compile(r'fs\.chmod\s*\(.*\)'), - "Redirects": re.compile(r'res\.redirect\s*\(.*req\.query\..*\)'), - "API_Key_Hardcoded": re.compile(r'api_key\s*=\s*[\'"]\S+[\'"]'), - "Weak_Hashing_Algorithm": re.compile(r'(md5|sha1|des)\s*\('), - "Planetext_Credentials": re.compile(r'(username|password)\s*=\s*[\'"]\S+[\'"]'), - "Insecure_SSL_Config": re.compile(r'server\.listen\s*\(.*http.*\)'), - "HTTP_Called": re.compile(r'http\.get\s*\(.*\)'), - "Sensitive_Data_Logging": re.compile(r'console\.(log|debug|error|warn)\s*\(.*(password|secret|key|token).*\)'), - "JSON_Parsing_No_Validation": re.compile(r'JSON\.parse\s*\(.*req\.(body|query|params).*\)'), - "Environment_Variables_In_Planetext": re.compile(r'process\.env\.[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*[\'"]\S+[\'"]'), - "Debug_Left_Exposed": re.compile(r'app\.get\s*\([\'"]\.\*/debug.*[\'"]'), - "Insecure_File_Paths": re.compile(r'(fs\.(readFile|writeFile))\s*\(.*req\.(body|query|params)\.path.*\)'), - "Unsecured_Spawn": re.compile(r'spawn\s*\(.*\)') -} - -Python_Patterns = { - "Eval_Function": re.compile(r'eval\s*\(.*\)'), - "Exec_Function": re.compile(r'exec\s*\(.*\)'), - "OS_Command_Injection": re.compile(r'os\.(system|popen)\s*\(.*\)'), - "Subprocess_Injection": re.compile(r'subprocess\.(Popen|call|run)\s*\(.*\)'), - "Pickle_Load": re.compile(r'pickle\.load\s*\(.*\)'), - "Hardcoded_Credentials": re.compile(r'(username|password)\s*=\s*[\'"]\S+[\'"]'), - "Weak_Hashing_Algorithm": re.compile(r'(md5|sha1|des)\s*\('), - "Insecure_Random": re.compile(r'random\.randint\s*\(.*\)'), - "Unverified_SSL": re.compile(r'requests\.get\s*\(.*verify\s*=\s*False\)'), - "Dangerous_File_Access": re.compile(r'open\s*\(.*\)'), - "Environment_Variables_Exposure": re.compile(r'os\.environ\[\s*[\'"]\S+[\'"]\s*\]'), - "Debug_Logging": re.compile(r'print\s*\(.*(password|secret|key|token).*\)'), - "Deserialization_Risk": re.compile(r'json\.loads\s*\(.*\)'), - "Unsecured_Spawn": re.compile(r'os\.spawn\s*\(.*\)') -} - -Word_Patterns = { - "Hardcoded_Credentials": re.compile(r'(username|password)\s*=\s*[\'"]\S+[\'"]'), - "Sensitive_Keywords": re.compile(r'(confidential|private|classified|top secret)', re.IGNORECASE), - "Email_Addresses": re.compile(r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'), - "Phone_Numbers": re.compile(r'\b(?:\+\d{1,3})?[-.\s]?(\d{2,4})?[-.\s]?\d{3}[-.\s]?\d{4}\b'), - "URLs": re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+') -} - -TXT_Patterns = { - "Hardcoded_Credentials": re.compile(r'(username|password|token|secret|access[_-]?key)\s*[:=]\s*[\'"]?\S+[\'"]?', re.IGNORECASE), - "Sensitive_Keywords": re.compile(r'\b(confidential|private|classified|secret|token|proprietary)\b', re.IGNORECASE), - "Email_Addresses": re.compile(r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'), - "URLs": re.compile(r'https?://[^\s]+'), - "IP_Addresses": re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b'), - "AWS_Credentials": re.compile(r'AKIA[0-9A-Z]{16}'), - "API_Keys": re.compile(r'(?i)(api[_-]?key|access[_-]?token)\s*[:=]\s*[\'"]?[A-Za-z0-9\-_]{20,}'), - "JWT_Tokens": re.compile(r'eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}\.[A-Za-z0-9._-]{10,}') -} - -YML_Patterns = { - "Hardcoded_Credentials": re.compile(r'(username|password|token|secret|access[_-]?key)\s*:\s*[\'"]?\S+[\'"]?', re.IGNORECASE), - "Sensitive_Keywords": re.compile(r'\b(confidential|private|classified|secret|proprietary)\b', re.IGNORECASE), - "Email_Addresses": re.compile(r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'), - "URLs": re.compile(r'https?://[^\s]+'), - "IP_Addresses": re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b'), - "AWS_Credentials": re.compile(r'AKIA[0-9A-Z]{16}'), - "API_Keys": re.compile(r'(?i)(api[_-]?key|access[_-]?token)\s*:\s*[\'"]?[A-Za-z0-9\-_]{20,}'), - "Unsafe_YAML_Object": re.compile(r'!!python/(object|module|function)') -} - - -def AnalyseFile(FileLocation, patterns): - vulnerabilities = {key: [] for key in patterns.keys()} - try: - with open(FileLocation, 'r', encoding='utf-8') as file: - Data = file.read() - except Exception as e: - print(f"Error reading file {FileLocation}: {e}") - return None - for key, pattern in patterns.items(): - matches = pattern.findall(Data) - if matches: - vulnerabilities[key].extend(matches) - return vulnerabilities - -def AnalyseWordFile(FileLocation): - vulnerabilities = {key: [] for key in Word_Patterns.keys()} - try: - doc = docx.Document(FileLocation) - text_data = "\n".join([para.text for para in doc.paragraphs]) - except Exception as e: - print(f"Error reading file {FileLocation}: {e}") - return None - for key, pattern in Word_Patterns.items(): - matches = pattern.findall(text_data) - if matches: - vulnerabilities[key].extend(matches) - return vulnerabilities - -def get_modified_files(): - return os.getenv("MODIFIED_FILES", "").split() - -def PrintOutcome(Data): - Outside = max(len(line) for line in Data.splitlines()) + 4 - print('|' + '-' * (Outside - 2) + '|') - for line in Data.splitlines(): - print(f"| {line.ljust(Outside - 4)} |") - print('|' + '-' * (Outside - 2) + '|') - -def main(): - modified_files = get_modified_files() - if not modified_files: - print("No modified files detected.") - return - for file in modified_files: - if not os.path.exists(file): - print(f"File not found: {file}") - continue - print(f"Detected new file: {file}") - if file.endswith(".js"): - print(f"Scanning {file} for vulnerabilities...") - patterns = JS_Patterns - vulnerabilities = AnalyseFile(file, patterns) - elif file.endswith(".py"): - print(f"Scanning {file} for vulnerabilities...") - patterns = Python_Patterns - vulnerabilities = AnalyseFile(file, patterns) - elif file.endswith(".docx"): - print(f"Scanning {file} for vulnerabilities...") - vulnerabilities = AnalyseWordFile(file) - elif file.endswith(".txt"): - print(f"Scanning {file} for vulnerabilities...") - vulnerabilities = AnalyseFile(file, TXT_Patterns) - elif file.endswith(".yml") or file.endswith("yaml"): - print(f"Scanning {file} for vulnerabilities...") - vulnerabilities = AnalyseFile(file, YML_Patterns) - else: - print(f"{file} is not a JavaScript, Python or Word file. Skipping...") - continue - - if vulnerabilities and any(vulnerabilities.values()): - Outcome = f"Potential Vulnerability Found in {file}:\n" - for key, found in vulnerabilities.items(): - if found: - Outcome += f" {key.replace('_', ' ').title()} vulnerabilities:\n" - for q in found: - Outcome += f" - {q}\n" - else: - Outcome = f"No vulnerabilities found in {file}." - PrintOutcome(Outcome) - -if __name__ == "__main__": - main() diff --git a/package.json b/package.json index 603bb4c..0c9ca62 100644 --- a/package.json +++ b/package.json @@ -34,24 +34,26 @@ "dotenv": "^16.6.1", "express": "^4.19.1", "express-rate-limit": "^7.5.0", - "express-validator": "^7.2.1", + "express-validator": "7.3.0", "fs-extra": "^11.3.1", "helmet": "^8.1.0", + "hpp": "^0.2.3", "jsonwebtoken": "^9.0.2", - "multer": "^1.4.5-lts.1", + "multer": "^2.0.2", "mysql2": "^3.9.2", "node-fetch": "^3.3.2", - "nutrihelp-api": "file:", "sinon": "^18.0.0", "swagger-ui-express": "^5.0.0", "twilio": "^5.9.0", + "xss-clean": "^0.1.4", "yamljs": "^0.3.0" }, "devDependencies": { "axios": "^1.11.0", - "chai": "^6.0.1", + "chai": "^4.3.10", "chai-http": "^5.1.2", "concurrently": "^8.2.2", + "eslint-plugin-security": "^3.0.0", "form-data": "^4.0.2", "jest": "^30.1.3", "mocha": "^11.7.2", diff --git a/services/authService.js b/services/authService.js index db0f437..1e7d82c 100644 --- a/services/authService.js +++ b/services/authService.js @@ -11,7 +11,7 @@ const supabase = createClient( class AuthService { constructor() { - this.accessTokenExpiry = '15m'; // 15 minutes + this.accessTokenExpiry = '10m'; // 15 minutes this.refreshTokenExpiry = 7 * 24 * 60 * 60 * 1000; // 7 days }