-
-
Notifications
You must be signed in to change notification settings - Fork 3
Bug fixes and v3.3.0 #176
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
Bug fixes and v3.3.0 #176
Conversation
Now you can log emojis due to use of UTF-8 instead of the default UniCode! Signed-off-by: Shahm Najeeb <[email protected]>
Added better docstrings, and added new plans while removing old ones, fixed minor bugs as well, and added todo work Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Removed some plans that wouldn't work out, Updated Flag.py to show better help options. Also fixed a huge bug with flags, where abreviation was allowed, thus leading to wonky flags combos like --web or --def, Signed-off-by: Shahm Najeeb <[email protected]>
Updated PLANS.md to reflect the changes, Fixing minor bugs Signed-off-by: Shahm Najeeb <[email protected]>
Added a smart flag companion, it gives flag suggestions based on your flag, thus helping fix spelling mistakes, etc and predicts flags for you, just like git, if it can't find a flag that works with you - Part 1 (difflib) Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Signed-off-by: Shahm Najeeb <[email protected]>
Adding new beta feature: Generate Summary Added proper history saving, loading, and updating as well as minor bug fixes to match_flag() function Signed-off-by: Shahm Najeeb <[email protected]>
Finally implemented the history feature properly, as a last resort, if the model is not sure of a good flag, it resorts to the history file for more info Signed-off-by: Shahm Najeeb <[email protected]>
Fully implemented the script and its code properly, also ran --dev to submit changes, as well as added new feature to Get to allow you to exclude files from the search for list_files() Updated .gitignore for the History created Removed old tests Signed-off-by: Shahm Najeeb <[email protected]>
Updated CREDITS.md to include contrib.rocks Updated SECURITY.md to add the missing versions Signed-off-by: Shahm Najeeb <[email protected]>
Re-hauled dump_memory.py, now made it better and more useful, as well as fixed issues with dependencies Signed-off-by: Shahm Najeeb <[email protected]>
Re-hauled dump_memory.py, now made it better and more useful, as well as fixed issues with dependencies Signed-off-by: Shahm Najeeb <[email protected]>
…ixes-and-v3.3.0 Signed-off-by: Shahm Najeeb <[email protected]> # Conflicts: # CODE/dump_memory.py
Re-hauled event_log.py, now made it better and more useful, as well as fixed issues with dependencies Also updated Logicytics.py to remove deprecated code Updated exception logging to discourage it, making only one script now using it Signed-off-by: Shahm Najeeb <[email protected]>
WalkthroughThe pull request introduces a comprehensive set of updates across multiple files in the Logicytics project. These changes span various aspects of the codebase, including configuration updates, error handling improvements, logging enhancements, and new functionalities in different modules. The modifications touch on areas like file management, system logging, Bluetooth device tracking, flag handling, and overall script execution strategies. Changes
Suggested Labels
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 10
🔭 Outside diff range comments (5)
CODE/sensitive_data_miner.py (2)
Line range hint
75-99: Hold up! This code needs some serious security checks! 🛡️The
__search_and_copy_filesmethod is doing some heavy lifting without any safety rails:
- It's starting from C:\ (root drive) - that's like giving someone keys to your whole house!
- It's using multiple threads to copy files - cool for speed, but risky for system resources
- No limits on total file size or count
Here's what we should add:
- A configurable root directory (not just C:)
- File size limits
- Total copied files limit
- Skip system directories
Want me to show you how to make this safer?
🧰 Tools
🪛 Ruff (0.8.2)
91-91: Loop control variable
filesnot used within loop bodyRename unused
filesto_files(B007)
Line range hint
101-119: The password search could use some upgrades! 🔍The keywords list is pretty basic. We might miss important stuff like:
- "credentials"
- "auth"
- "token"
- "private"
Also, we're deleting and recreating the destination folder without checking if files are in use:
destination = Path("Password_Files") if destination.exists(): + # Check if any files are in use before deletion + try: + for file in destination.iterdir(): + if file.is_file(): + with open(file, 'r'): pass shutil.rmtree(destination) + except PermissionError: + log.error("Cannot clean destination - files are in use") + return🧰 Tools
🪛 Ruff (0.8.2)
91-91: Loop control variable
filesnot used within loop bodyRename unused
filesto_files(B007)
CODE/vulnscan.py (2)
Line range hint
46-71: Yo! Watch out for those global variables! 🚨Hey there! The use of global variables (
model_to_useandvectorizer_to_use) could be super risky in a multi-threaded setup, even with locks. It's like having multiple people trying to use the same pencil at once - kinda messy!Also, that generic
Exceptioncatch is pretty broad - it's like using a giant net to catch a specific fish.Here's a better way to handle this:
- global model_to_use, vectorizer_to_use + model = None + vectorizer = None try: with model_lock: - if model_to_use is None: + if model is None: log.info(f"Loading model from {model_path}") - model_to_use = load_model(model_path) + model = load_model(model_path) with vectorizer_lock: - if vectorizer_to_use is None: + if vectorizer is None: log.info(f"Loading vectorizer from {vectorizer_path}") - vectorizer_to_use = joblib.load(vectorizer_path) + vectorizer = joblib.load(vectorizer_path) - vulnscan(model_to_use, scan_paths, vectorizer_to_use) - except Exception as e: + vulnscan(model, scan_paths, vectorizer) + except FileNotFoundError as e: log.error(f"Error scanning path {scan_paths}: {e}") + except ValueError as e: + log.error(f"Invalid model or vectorizer format for {scan_paths}: {e}") + except torch.cuda.CudaError as e: + log.error(f"CUDA error while scanning {scan_paths}: {e}")
Line range hint
130-150: Let's make those file operations safer! 💪The way you're handling that "Sensitive_File_Paths.txt" file is kinda like leaving your diary unlocked - not super safe! Also, what if the file can't be opened?
Here's a safer way to do it:
+from pathlib import Path + +SENSITIVE_FILES_PATH = Path("Sensitive_File_Paths.txt") @log.function def vulnscan(model, SCAN_PATH, vectorizer): log.info(f"Scanning {SCAN_PATH}") result, probability, reason = scan_file(model, vectorizer, SCAN_PATH) if result: log.info(f"File {SCAN_PATH} is sensitive with probability {probability:.2f}. Reason: {reason}") - if not os.path.exists("Sensitive_File_Paths.txt"): - with open("Sensitive_File_Paths.txt", "w") as sensitive_file: - sensitive_file.write(f"{SCAN_PATH}\n\n") - with open("Sensitive_File_Paths.txt", "a") as sensitive_file: - sensitive_file.write(f"{SCAN_PATH}\n") + try: + with SENSITIVE_FILES_PATH.open("a+") as sensitive_file: + if SENSITIVE_FILES_PATH.stat().st_size == 0: + sensitive_file.write(f"{SCAN_PATH}\n\n") + else: + sensitive_file.write(f"{SCAN_PATH}\n") + except IOError as e: + log.error(f"Failed to write sensitive file path: {e}")CODE/logicytics/Flag.py (1)
Line range hint
263-432: Better unknown flag handling
Cool approach using difflib to guess intended flags. Maybe keep a minimum threshold (like 0.8) for the guess. If the user typed something totally different, better to say “no clue” than suggest something random. Also, forcing an exit with code1might break some automated scripts. Consider returning an error code only if truly necessary.
🧹 Nitpick comments (18)
CODE/sensitive_data_miner.py (3)
37-44: Nice error handling upgrade! 👍The new try-catch block for Windows permission errors is solid. It's like having a safety net when you're parkour running through directories!
But hey, one small thing - instead of just logging the error, maybe we should:
try: path_list = os.listdir(root) except WindowsError as e: if DEBUG: - # Log the error if in debug mode, as it is a common occurrence. - log.warning(f"Permission Denied: {e}") + # Track skipped directories for reporting + log.warning(f"Access Denied to directory {root}: {e}") + return []
124-127: Cool warning message! But let's make it more informative! 🎯- log.warning( - "Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)") + log.warning( + "🔍 Starting to search for sensitive files...\n" + "⚠️ This might take a while and use lots of system resources\n" + "💡 Pro tip: Now's a good time for a coffee break!")
Line range hint
1-127: Yo! We need to talk about the bigger picture here! 🌍This script is like a double-edged sword - super powerful but potentially dangerous. Here are some major concerns:
Security:
- It's copying sensitive files to one place - that's risky!
- No encryption for the copied files
- No access controls
System Impact:
- Could eat up disk space
- Might slow down the system
- No resource limits
Here's what we should add:
- File encryption
- Resource monitoring
- Access logging
- Clean-up functionality
Want me to help design a safer architecture?
CODE/logicytics/Logger.py (2)
Line range hint
142-161: Sweet error handling upgrade! 🛡️You've leveled up the error handling game here! The try-except blocks now catch those annoying Unicode errors that pop up when dealing with weird text characters. Plus, that warning about not using this method outside the class is super helpful.
Just one tiny thing to make it even better:
- except Exception as E: + except Exception as E: + self.__internal(f"Error writing to log file: {E} - Message: {str(message)}")The error message could be a bit more specific about what failed.
🧰 Tools
🪛 Ruff (0.8.2)
150-150: f-string without any placeholders
Remove extraneous
fprefix(F541)
251-266: Cool new feature for handling multiple log messages! 📝The
parse_executionmethod is a neat way to handle multiple messages at once. But heads up, there's a small thing we could make better:- if message_log: + if not message_log: + return + for message_list in message_log: - for message_list in message_log:This would make the code a bit cleaner by handling empty lists right away!
CODE/event_log.py (2)
Line range hint
1-14: Make the admin requirement more noticeable! 🔑Hey! That admin requirement comment is super important but it's kinda hiding in there. Let's make it pop by adding a more visible warning at the start of the file.
import os import shutil import threading import wmi # Import the wmi library from logicytics import Log, DEBUG +""" +⚠️ IMPORTANT: This script requires administrator privileges to run! +If you run this without admin rights, it's gonna fail faster than a phone without TikTok. +""" + - # Note: This script CANNOT be run without admin privileges if __name__ == "__main__": log = Log({"log_level": DEBUG})
16-26: Level up that docstring! 📝The docstring could use some extra details to make it super clear what's going on:
- What admin privileges are needed
- What happens if WMI isn't available
- What the function returns (or doesn't return)
def parse_event_logs(log_type: str, output_file: str): """ Parses Windows event logs of a specified type and writes them to an output file using WMI. Args: log_type (str): The type of event log to parse (e.g., 'Security', 'Application'). output_file (str): The file path where the parsed event logs will be written. + Returns: + None + Raises: Exception: If there is an error opening or reading the event log, or writing to the output file. + wmi.x_wmi: If there are WMI-specific issues or insufficient permissions. + + Note: + - Requires administrator privileges + - Windows Management Instrumentation (WMI) must be running + - Supported log_types: 'Security', 'Application', 'System' """CODE/dump_memory.py (3)
12-14: Cool TODO for the next version! 📝These TODOs look important for v3.3.1! Want me to help implement these memory stats improvements? They'd make the RAM snapshot way more detailed!
16-18: The file size limit needs more info! 📏The comment about the file size limit is a bit unclear. Let's add more details about:
- Why we chose 20 MiB as the limit
- What happens to the truncated data
- How to handle important data if it gets cut off
-# If the file size exceeds this limit, the file will be truncated with a message -# Put 0 to disable the limit +# Maximum file size for memory dumps (in MiB) +# - Set to 0 to disable the limit +# - Files exceeding this limit will be truncated +# - Important: Check logs for truncated data warnings +# - Default: 20 MiB (suitable for most debugging needs)
22-39: The RAM snapshot function looks solid, but could be even better! 💪The function works great, but here's a pro tip - let's make it more reusable and add some unit tests!
-def capture_ram_snapshot(): +def capture_ram_snapshot(output_file="Ram_Snapshot.txt"): """Capture system RAM and swap memory statistics. Args: output_file (str): Path to save the snapshot Returns: dict: Memory statistics for testing """ log.info("Capturing RAM Snapshot...") memory = psutil.virtual_memory() swap = psutil.swap_memory() + stats = { + "ram_total": memory.total, + "ram_used": memory.used, + "ram_available": memory.available, + "swap_total": swap.total, + "swap_used": swap.used, + "swap_free": swap.free, + "ram_percent": memory.percent + } - with open("Ram_Snapshot.txt", "w") as file: + with open(output_file, "w") as file: try: file.write(f"Total RAM: {memory.total / (1024 ** 3):.2f} GB\n") # ... rest of the writes ... - log.info("RAM Snapshot saved to Ram_Snapshot.txt") + log.info(f"RAM Snapshot saved to {output_file}") + return statsCODE/vulnscan.py (1)
157-158: Let's keep an eye on that memory usage! 🧠Your code's memory management is like downloading the same game multiple times - it's just wasting space! We should make sure we're being smart about memory usage.
Here's what we should add:
+import psutil +import gc + +def check_memory_usage(): + memory = psutil.Process().memory_info() + memory_gb = memory.rss / (1024 * 1024 * 1024) # Convert to GB + if memory_gb > 8: # Adjust threshold as needed + log.warning(f"High memory usage detected: {memory_gb:.2f} GB") + gc.collect() + torch.cuda.empty_cache() # If using CUDA + if __name__ == "__main__": # Locks for model and vectorizer log.info("Locking threads - Model and Vectorizer") model_lock = threading.Lock() vectorizer_lock = threading.Lock() model_to_use = None vectorizer_to_use = None + + # Schedule periodic memory checks + import schedule + schedule.every(5).minutes.do(check_memory_usage)Also, don't forget to add these to your requirements:
psutil>=5.9.0 schedule>=1.1.0CODE/packet_sniffer.py (4)
3-28: Nice job with the error handling! But let's make it even cooler 😎The config reading setup and error handling is solid! But having those global variables (
packet_dataandG) floating around is kinda like leaving your stuff all over the floor - it works, but it's messy.Consider wrapping these in a class to keep things organized:
class PacketSniffer: def __init__(self): self.packet_data = [] # List to store packet information self.G = nx.Graph() # Initialize a graph self.config = self._load_config() def _load_config(self): try: config = ConfigParser() config.read('config.ini') return config['PacketSniffer Settings'] except Exception as e: log.error(f"Error reading configuration: {e}") exit(1)
Line range hint
138-182: The sniffing setup is solid, but let's make it bulletproof! 🛡️The callback function and packet counting is well done, but we could add some extra error handling for network issues.
Here's how to make it even better:
def start_sniffing(self, interface, packet_count=10, timeout=10): try: # Check if interface exists if interface not in conf.ifaces: raise ValueError(f"Interface {interface} not found") # Your existing code here except OSError as e: log.error(f"Network error: {e}") raise except KeyboardInterrupt: log.info("Packet capture stopped by user") # Save any captured packets before exiting self.save_packet_data_to_csv('captured_packets.csv')
Line range hint
235-270: Love the emoji error messages! 🎯 But let's level up the error handlingThe auto-correction for WiFi interfaces is super smart! But those nested try-except blocks are getting a bit maze-like.
Here's a cleaner way to structure it:
def _correct_interface_name(interface): corrections = { "WiFi": "Wi-Fi", "Wi-Fi": "WiFi" } return corrections.get(interface, interface) def packet_sniffer(): interface = config['interface'] packet_count = int(config['packet_count']) timeout = int(config['timeout']) if not self._validate_settings(packet_count, timeout): return for attempt in range(2): # Try original and corrected name try: start_sniffing(interface, packet_count, timeout) break except Exception as err: if attempt == 0 and interface in ("WiFi", "Wi-Fi"): log.warning(f"Retrying with corrected interface name...") interface = self._correct_interface_name(interface) else: log.error(f"Failed to sniff packets: {err}") raise
273-279: The main block is simple and sweet! 🍬 But let's add some cleanupIt's good that you're catching errors, but we should clean up any resources before exiting.
Here's how to make it even better:
if __name__ == "__main__": sniffer = None try: sniffer = PacketSniffer() sniffer.packet_sniffer() except Exception as e: log.error(e) exit(1) finally: if sniffer: # Clean up resources plt.close('all') # Close any open plots # Could add more cleanup hereCODE/logicytics/Flag.py (3)
4-36: Neat config approach, watch for missing config
Yo, it's dope how you load config fromconfig.inior a parent folder. But if both fail, you just exit. Maybe add a backup default config or a more guided error? That’ll help users who forget the config file.
40-68: SentenceTransformer usage
Your__get_simfunction is sweet, but you might want to catch ifsentence_transformersisn’t installed. Right now, if it's missing, you'll crash. Maybe handle that more gracefully with a friendly error. Also, watch out that you only set the logging level once. Double sets can be confusing.
538-580: Multiple flags usage
The logic for restricting users to a single or double flag is good. If they break the rules, you bail out. Just be sure the users know how to combine flags. A doc comment or examples in your README would totally help.
🛑 Comments failed to post (10)
CODE/sensitive_data_miner.py (1)
15-21:
⚠️ Potential issueYo! 🚨 We need to think twice about these file extensions!
Adding support for database files (.mdb, .accdb, .sql) and email files (.pst, .msg) is pretty risky. These could contain super sensitive stuff like:
- User credentials
- Personal info
- Company secrets
Consider:
- Adding a warning when copying these high-risk files
- Implementing file size limits
- Adding checksums to track file integrity
Want me to help create a safer implementation?
CODE/logicytics/Logger.py (1)
269-295: 🛠️ Refactor suggestion
⚠️ Potential issueAwesome performance tracking decorator! ⏱️
Love how you're tracking function execution times! But there's a small catch we should fix:
def wrapper(*args, **kwargs): if not callable(func): - self.exception(f"Function {func.__name__} is not callable.", TypeError) + raise TypeError(f"Function {func.__name__} is not callable.") start_time = time.perf_counter() - self.debug(f"Running the function {func.__name__}().") + func_args = ", ".join([str(arg) for arg in args] + + [f"{k}={v}" for k, v in kwargs.items()]) + self.debug(f"Running {func.__name__}({func_args})") result = func(*args, **kwargs) end_time = time.perf_counter() elapsed_time = end_time - start_time - self.debug(f"Function {func.__name__}() executed in {elapsed_time:.6f} seconds.") + self.debug(f"{func.__name__}() completed in {elapsed_time:.6f}s -> returned {type(result).__name__}") return resultThese changes will:
- Check for callable before wrapping (no need to use exception logging here)
- Log the actual arguments being passed
- Include the return type in the completion log
Also, the callable check should be moved to decorator level:
def function(self, func: callable): + if not callable(func): + raise TypeError(f"{func} is not callable") def wrapper(*args, **kwargs): - if not callable(func): - self.exception(f"Function {func.__name__} is not callable.", TypeError) start_time = time.perf_counter()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.""" A decorator that logs the execution of a function, including its start time, end time, and elapsed time. :param func: The function to be decorated. :return: The wrapper function. """ def wrapper(*args, **kwargs): """ Wrapper function that logs the execution of the decorated function. :param args: Positional arguments for the decorated function. :param kwargs: Keyword arguments for the decorated function. :raises TypeError: If the provided function is not callable. :return: The result of the decorated function. """ if not callable(func): raise TypeError(f"Function {func.__name__} is not callable.") start_time = time.perf_counter() func_args = ", ".join([str(arg) for arg in args] + [f"{k}={v}" for k, v in kwargs.items()]) self.debug(f"Running {func.__name__}({func_args})") result = func(*args, **kwargs) end_time = time.perf_counter() elapsed_time = end_time - start_time self.debug(f"{func.__name__}() completed in {elapsed_time:.6f}s -> returned {type(result).__name__}") return resultCODE/event_log.py (3)
32-34:
⚠️ Potential issueWhoa there! Let's secure that query! 🛡️
The WMI query is using an f-string with direct user input - that's like leaving your front door wide open! We should sanitize that
log_typeto prevent any sneaky business.- query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'" + valid_log_types = {'Security', 'Application', 'System'} + if log_type not in valid_log_types: + raise ValueError(f"Invalid log_type. Must be one of: {valid_log_types}") + query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Query based on log_type ('Security', 'Application', or 'System') valid_log_types = {'Security', 'Application', 'System'} if log_type not in valid_log_types: raise ValueError(f"Invalid log_type. Must be one of: {valid_log_types}") query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'" log.debug(f"Executing WMI query: {query}")
38-50: 🛠️ Refactor suggestion
Watch out for the memory monster! 🧟♂️
Loading all events at once could eat up your RAM faster than you eat pizza! Let's process these in chunks to keep things smooth.
- events = c.query(query) - f.write(f"Total records: {len(events)}\n\n") - log.debug(f"Number of events retrieved: {len(events)}") - for event in events: + BATCH_SIZE = 1000 + total_events = 0 + for event in c.query(query): + if total_events == 0: + f.write("Processing events...\n\n") event_data = { 'Event Category': event.Category, 'Time Generated': event.TimeGenerated, 'Source Name': event.SourceName, 'Event ID': event.EventCode, 'Event Type': event.Type, 'Event Data': event.InsertionStrings } f.write(str(event_data) + '\n\n') + total_events += 1 + if total_events % BATCH_SIZE == 0: + log.debug(f"Processed {total_events} events...") + f.write(f"\nTotal records processed: {total_events}\n")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.BATCH_SIZE = 1000 total_events = 0 for event in c.query(query): if total_events == 0: f.write("Processing events...\n\n") event_data = { 'Event Category': event.Category, 'Time Generated': event.TimeGenerated, 'Source Name': event.SourceName, 'Event ID': event.EventCode, 'Event Type': event.Type, 'Event Data': event.InsertionStrings } f.write(str(event_data) + '\n\n') total_events += 1 if total_events % BATCH_SIZE == 0: log.debug(f"Processed {total_events} events...") f.write(f"\nTotal records processed: {total_events}\n")
68-78: 🛠️ Refactor suggestion
Let's make those threads bulletproof! 🚀
The threading setup is cool, but it needs some safety nets! What if a thread crashes or gets stuck? Let's add some error handling and timeouts.
threads = [] + results = [] threads_items = [('Security', 'event_logs/Security_events.txt'), ('Application', 'event_logs/App_events.txt'), ('System', 'event_logs/System_events.txt')] + def thread_wrapper(log_type_main, output_file_main, results): + try: + parse_event_logs(log_type_main, output_file_main) + results.append((log_type_main, True, None)) + except Exception as e: + log.error(f"Thread failed for {log_type_main}: {e}") + results.append((log_type_main, False, str(e))) for log_type_main, output_file_main in threads_items: - thread = threading.Thread(target=parse_event_logs, args=(log_type_main, output_file_main)) + thread = threading.Thread(target=thread_wrapper, + args=(log_type_main, output_file_main, results)) threads.append(thread) thread.start() for thread in threads: - thread.join() + thread.join(timeout=300) # 5 minute timeout + if thread.is_alive(): + log.error("Thread timeout! Some logs might be incomplete.") + + # Check results + failed = [r[0] for r in results if not r[1]] + if failed: + log.error(f"Failed to process logs: {', '.join(failed)}")Committable suggestion skipped: line range outside the PR's diff.
SECURITY.md (1)
9-25:
⚠️ Potential issueHey! The release dates need a quick update! 🗓️
Since we're now in 2025, some of these dates look a bit off. Most of these versions were released in 2024, but they're showing up as future releases in the current year. Let's fix that to avoid confusion!
Here's what needs updating:
- 3.3.x and 3.2.x can stay in 2025 (they're recent)
- Everything from 2.5.x down to 1.0.x should be in 2024
Want me to help update these dates? Just say the word! 👍
🧰 Tools
🪛 LanguageTool
[inconsistency] ~13-~13: A new year has begun. Did you mean “Nov 25, 2025”?
Context: ...c 6, 2024 | | 2.5.x | ✖️ | Nov 25, 2024 | | 2.4.x | ✖️ | Nov 12, 20...(DATE_NEW_YEAR)
[inconsistency] ~14-~14: A new year has begun. Did you mean “Nov 12, 2025”?
Context: ...v 25, 2024 | | 2.4.x | ✖️ | Nov 12, 2024 | | 2.3.x | ✖️ | Sep 21, 20...(DATE_NEW_YEAR)
[inconsistency] ~15-~15: A new year has begun. Did you mean “Sep 21, 2025”?
Context: ...v 12, 2024 | | 2.3.x | ✖️ | Sep 21, 2024 | | 2.2.x | ✖️ | Sep 9, 202...(DATE_NEW_YEAR)
[inconsistency] ~16-~16: A new year has begun. Did you mean “Sep 9, 2025”?
Context: ...p 21, 2024 | | 2.2.x | ✖️ | Sep 9, 2024 | | 2.1.x | ✖️ | Aug 29, 2...(DATE_NEW_YEAR)
[inconsistency] ~17-~17: A new year has begun. Did you mean “Aug 29, 2025”?
Context: ...p 9, 2024 | | 2.1.x | ✖️ | Aug 29, 2024 | | 2.0.x | ✖️ | Aug 25, 20...(DATE_NEW_YEAR)
[inconsistency] ~18-~18: A new year has begun. Did you mean “Aug 25, 2025”?
Context: ...g 29, 2024 | | 2.0.x | ✖️ | Aug 25, 2024 | | 1.6.x | ❌ | Jun 18, 20...(DATE_NEW_YEAR)
[inconsistency] ~19-~19: A new year has begun. Did you mean “Jun 18, 2025”?
Context: ...g 25, 2024 | | 1.6.x | ❌ | Jun 18, 2024 | | 1.5.x | ❌ | Jun 10, 20...(DATE_NEW_YEAR)
[inconsistency] ~20-~20: A new year has begun. Did you mean “Jun 10, 2025”?
Context: ...n 18, 2024 | | 1.5.x | ❌ | Jun 10, 2024 | | 1.4.x | ❌ | May 30, 20...(DATE_NEW_YEAR)
[inconsistency] ~21-~21: A new year has begun. Did you mean “May 30, 2025”?
Context: ...n 10, 2024 | | 1.4.x | ❌ | May 30, 2024 | | 1.3.x | ❌ | May 21, 20...(DATE_NEW_YEAR)
[inconsistency] ~22-~22: A new year has begun. Did you mean “May 21, 2025”?
Context: ...y 30, 2024 | | 1.3.x | ❌ | May 21, 2024 | | 1.2.x | ❌ | May 16, 20...(DATE_NEW_YEAR)
[inconsistency] ~23-~23: A new year has begun. Did you mean “May 16, 2025”?
Context: ...y 21, 2024 | | 1.2.x | ❌ | May 16, 2024 | | 1.1.x | ❌ | May 10, 20...(DATE_NEW_YEAR)
[inconsistency] ~24-~24: A new year has begun. Did you mean “May 10, 2025”?
Context: ...y 16, 2024 | | 1.1.x | ❌ | May 10, 2024 | | 1.0.x | ❌ | May 4, 202...(DATE_NEW_YEAR)
[inconsistency] ~25-~25: A new year has begun. Did you mean “May 4, 2025”?
Context: ...y 10, 2024 | | 1.0.x | ❌ | May 4, 2024 | ### Key: | Key | Desc ...(DATE_NEW_YEAR)
CODE/dump_memory.py (1)
61-118:
⚠️ Potential issueWatch out! The memory dump function needs some safety checks!
⚠️ The memory dump function is doing some cool stuff, but we should add some safety features:
- Check available disk space before dumping
- Add a timeout for large dumps
- Handle permissions better on Windows
def memory_dump(): log.info("Creating basic memory dump scan...") pid = os.getpid() + # Check available disk space + if os.path.exists("Ram_Dump.txt"): + required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 2 # 2x safety margin + free_space = psutil.disk_usage(".").free + if free_space < required_space: + log.error(f"Not enough disk space. Need {required_space/1024/1024:.2f}MB") + returnCommittable suggestion skipped: line range outside the PR's diff.
CODE/vulnscan.py (2)
182-183: 🛠️ Refactor suggestion
Time to level up your config game! ⚙️
Having those model and vectorizer paths hardcoded in the code is like writing your password on a sticky note - not the best idea! Plus, those version numbers in the filenames are gonna be a pain to update.
Let's make it configurable:
+import configparser +import json + +def load_config(): + config = configparser.ConfigParser() + config.read('config.ini') + return { + 'model_path': config.get('Models', 'vulnscan_model_path'), + 'vectorizer_path': config.get('Models', 'vulnscan_vectorizer_path') + } if __name__ == "__main__": + try: + config = load_config() + except Exception as e: + log.error(f"Failed to load config: {e}") + sys.exit(1) + # ... rest of the code ... with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = [ executor.submit( scan_path, - "VulnScan/Model SenseMini .3n3.pth", + config['model_path'], path, - "VulnScan/Vectorizer .3n3.pkl" + config['vectorizer_path'] )And create a
config.inifile:[Models] vulnscan_model_path = VulnScan/models/sensemini.pth vulnscan_vectorizer_path = VulnScan/models/vectorizer.pkl
151-188:
⚠️ Potential issueWhoa there! Let's not crash the system! 🔥
Creating a new thread for EVERY file is like opening a new tab for every website you visit - your computer's gonna have a bad time! Also, those Windows-only paths aren't gonna work for your Mac and Linux friends.
Here's how to make it better:
+from concurrent.futures import ThreadPoolExecutor +import platform +from typing import List + +def get_system_paths() -> List[str]: + if platform.system() == "Windows": + return [ + "C:\\Users\\", + "C:\\Windows\\Logs", + "C:\\Program Files", + "C:\\Program Files (x86)" + ] + elif platform.system() == "Linux": + return ["/home", "/var/log", "/usr"] + elif platform.system() == "Darwin": # macOS + return ["/Users", "/var/log", "/Applications"] + return [] if __name__ == "__main__": # Locks for model and vectorizer log.info("Locking threads - Model and Vectorizer") model_lock = threading.Lock() vectorizer_lock = threading.Lock() model_to_use = None vectorizer_to_use = None # Start scanning log.info("Getting paths to scan - This may take some time!!") - threads = [] paths = [] - base_paths = [ - "C:\\Users\\", - "C:\\Windows\\Logs", - "C:\\Program Files", - "C:\\Program Files (x86)" - ] + base_paths = get_system_paths() for base_path in base_paths: for root, _, files_main in os.walk(base_path): for file_main in files_main: paths.append(os.path.join(root, file_main)) # Start scanning log.warning("Starting scan - This may take hours and consume memory!!") - for path in paths: - thread = threading.Thread(target=scan_path, - args=("VulnScan/Model SenseMini .3n3.pth", - path, "VulnScan/Vectorizer .3n3.pkl")) - threads.append(thread) - thread.start() - - for thread in threads: - thread.join() + # Use max_workers based on CPU count but cap it at a reasonable number + max_workers = min(32, os.cpu_count() * 2) + with ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = [ + executor.submit( + scan_path, + "VulnScan/Model SenseMini .3n3.pth", + path, + "VulnScan/Vectorizer .3n3.pkl" + ) + for path in paths + ] + for future in futures: + try: + future.result() + except Exception as e: + log.error(f"Scan failed: {e}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": # Locks for model and vectorizer log.info("Locking threads - Model and Vectorizer") model_lock = threading.Lock() vectorizer_lock = threading.Lock() model_to_use = None vectorizer_to_use = None # Start scanning log.info("Getting paths to scan - This may take some time!!") paths = [] base_paths = get_system_paths() for base_path in base_paths: for root, _, files_main in os.walk(base_path): for file_main in files_main: paths.append(os.path.join(root, file_main)) # Start scanning log.warning("Starting scan - This may take hours and consume memory!!") # Use max_workers based on CPU count but cap it at a reasonable number max_workers = min(32, os.cpu_count() * 2) with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = [ executor.submit( scan_path, "VulnScan/Model SenseMini .3n3.pth", path, "VulnScan/Vectorizer .3n3.pkl" ) for path in paths ] for future in futures: try: future.result() except Exception as e: log.error(f"Scan failed: {e}")CODE/packet_sniffer.py (1)
106-135: 🛠️ Refactor suggestion
Another global variable alert! 🚨
The functions are neat, but
add_to_graphis using that globalGvariable. Just like before, this could cause problems if multiple things try to update the graph at once.Let's fix this by moving it into our
PacketSnifferclass:class PacketSniffer: def __init__(self): self.G = nx.Graph() self.graph_lock = Lock() def add_to_graph(self, packet_info): with self.graph_lock: src_ip = packet_info['src_ip'] dst_ip = packet_info['dst_ip'] protocol = packet_info['protocol'] self.G.add_edge(src_ip, dst_ip, protocol=protocol)
Docstrings generation was requested by @DefinetlyNotAI. * #176 (comment) The following files were modified: * `CODE/Logicytics.py` * `CODE/_debug.py` * `CODE/_dev.py` * `CODE/bluetooth_details.py` * `CODE/bluetooth_logger.py` * `CODE/dir_list.py` * `CODE/dump_memory.py` * `CODE/event_log.py` * `CODE/log_miner.py` * `CODE/logicytics/Execute.py` * `CODE/logicytics/FileManagement.py` * `CODE/logicytics/Flag.py` * `CODE/logicytics/Get.py` * `CODE/logicytics/Logger.py` * `CODE/logicytics/__init__.py` * `CODE/media_backup.py` * `CODE/packet_sniffer.py` * `CODE/sensitive_data_miner.py` * `CODE/vulnscan.py` * `CODE/wifi_stealer.py`
|
Note We have generated docstrings for this pull request, at #178 |
Signed-off-by: Shahm Najeeb <[email protected]>
dump_memory.py: Added failsafe check for disk space Logger.py: Made the @function decorator better, by having more precision in its output vulnscan.py: Added a threadlock as a failsafe to not overload the system Signed-off-by: Shahm Najeeb <[email protected]>
> [!WARNING] > The [docstrings feature](https://docs.coderabbit.ai/finishing-touches/docstrings) is in [beta](https://docs.coderabbit.ai/early-access/#beta). Docstrings generation was requested by @DefinetlyNotAI. * #176 (comment) The following files were modified: * `CODE/Logicytics.py` * `CODE/_debug.py` * `CODE/_dev.py` * `CODE/bluetooth_details.py` * `CODE/bluetooth_logger.py` * `CODE/dir_list.py` * `CODE/dump_memory.py` * `CODE/event_log.py` * `CODE/log_miner.py` * `CODE/logicytics/Execute.py` * `CODE/logicytics/FileManagement.py` * `CODE/logicytics/Flag.py` * `CODE/logicytics/Get.py` * `CODE/logicytics/Logger.py` * `CODE/logicytics/__init__.py` * `CODE/media_backup.py` * `CODE/packet_sniffer.py` * `CODE/sensitive_data_miner.py` * `CODE/vulnscan.py` * `CODE/wifi_stealer.py` <details> <summary>These files were kept as they were</summary> * `CODE/sys_internal.py` </details> <details> <summary>These file types are not supported</summary> * `.github/ISSUE_TEMPLATE/bug_report.yml` * `.gitignore` * `CODE/config.ini` * `CREDITS.md` * `PLANS.md` * `README.md` * `SECURITY.md` * `requirements.txt` </details> <details> <summary>ℹ️ Note</summary><blockquote> CodeRabbit cannot perform edits on its own pull requests yet. </blockquote></details>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 8
🔭 Outside diff range comments (4)
CODE/packet_sniffer.py (1)
Line range hint
3-20: Yo! Let's make this code more robust! 🛠️The config reading part is kinda risky - if the config file is missing or messed up, the code will crash without telling us what went wrong. Also, those global variables (
packet_dataandG) could cause some headaches later.Here's how we can make it better:
# Read configuration from config.ini config = ConfigParser() -config.read('config.ini') -config = config['PacketSniffer Settings'] +try: + if not config.read('config.ini'): + raise FileNotFoundError("config.ini not found!") + config = config['PacketSniffer Settings'] +except Exception as e: + log.error(f"Failed to read config: {e}") + exit(1)Also, consider wrapping those global variables in a class to keep things organized! 🎯
CODE/sensitive_data_miner.py (1)
Line range hint
110-120: Storing sensitive files without protection? That's a big yikes! 😱The copied files are just chilling in a regular folder without any protection. That's like keeping your passwords on a sticky note on your monitor!
We should:
- Encrypt the copied files
- Add access controls to the destination folder
- Add an option to securely delete files after analysis
Also, consider adding these keywords: "cert", "ssh", "pgp", "wallet" to catch more sensitive files.
CODE/vulnscan.py (2)
Line range hint
47-72: Hey, let's make this code even better! 🔧Using global variables (
model_to_useandvectorizer_to_use) isn't the coolest way to do this. It's like sharing your pencil with the whole class - someone might change it when you're not looking! Here's a better way:-def scan_path(model_path: str, scan_paths: str, vectorizer_path: str): +def scan_path(model_path: str, scan_paths: str, vectorizer_path: str, *, model_lock: threading.Lock, vectorizer_lock: threading.Lock): """ Load the model and vectorizer if not already loaded, and scan the specified path for sensitive content. """ - global model_to_use, vectorizer_to_use + model_to_use = None + vectorizer_to_use = None try: with model_lock: if model_to_use is None:
Line range hint
131-150: Watch out! Your file saving might crash! 💥When you're trying to save the "Sensitive_File_Paths.txt" file, you're not checking if the folder exists first. This could totally fail if the folder isn't there!
Here's how to fix it:
if result: log.info(f"File {SCAN_PATH} is sensitive with probability {probability:.2f}. Reason: {reason}") + output_dir = os.path.dirname("Sensitive_File_Paths.txt") + if output_dir and not os.path.exists(output_dir): + os.makedirs(output_dir) if not os.path.exists("Sensitive_File_Paths.txt"):
🧹 Nitpick comments (11)
CODE/packet_sniffer.py (3)
Line range hint
29-53: Hey! Let's add some type hints to make this code even cooler! 🚀The function looks solid with that error handling, but adding type hints would make it easier for other devs to understand what's going on.
+from typing import TypedDict + +class PacketInfo(TypedDict): + src_ip: str + dst_ip: str + protocol: str + src_port: int | None + dst_port: int | None - packet_info = { + packet_info: PacketInfo = {
Line range hint
135-198: The sniffing logic is pretty sweet, but let's make it even better! 🎮The packet callback's return value could use a bit more explanation in the docstring. When it returns
True, it stops the sniffing - that's pretty important info!Update the callback's docstring like this:
Returns: - bool: True if the packet count is reached, otherwise False. + bool: True to stop packet sniffing (when packet count is reached), + False to continue sniffing.
231-272: The main function is looking good, but watch out for these things! 👀
- That f-string on line 269 doesn't need to be an f-string since it's just a regular string.
- We should probably limit the number of retries when correcting interface names.
Here are the fixes:
- log.warning(f"Retrying with corrected interface name...") + log.warning("Retrying with corrected interface name...")[security]
Also, since we're dealing with network interfaces, we should validate the interface name to prevent any injection attacks:+ def validate_interface_name(name: str) -> bool: + return bool(re.match(r'^[a-zA-Z0-9-_]+$', name)) + interface = config['interface'] + if not validate_interface_name(interface): + log.error(f"Invalid interface name: {interface}") + exit(1)🧰 Tools
🪛 Ruff (0.8.2)
269-269: f-string without any placeholders
Remove extraneous
fprefix(F541)
CODE/sensitive_data_miner.py (1)
Line range hint
1-128: Let's talk about the elephant in the room 🐘This tool is super powerful but could be dangerous in the wrong hands. Here's what we should think about:
- Add user authentication and authorization
- Log all operations for audit trails
- Add rate limiting and resource controls
- Implement secure storage with encryption
- Add file integrity checks
Consider breaking this into a client-server architecture where:
- Server handles permissions and resource controls
- Client only runs with proper authentication
- All operations are logged and monitored
- Copied files are automatically encrypted
CODE/dump_memory.py (4)
16-18: Make the file size limit super clear! 📏The comment could be clearer about the units. Let's spell it out!
-# If the file size exceeds this limit, the file will be truncated with a message -# Put 0 to disable the limit +# If the file size exceeds this limit (in MiB), the file will be truncated with a message +# Set to 0 to disable the size limit completely
22-39: Let's make this code even more awesome! 🚀The function works great, but we could make it even better:
- The file path is hardcoded - maybe we should make it configurable?
- Those GB calculations are repeated a lot - we could make a helper function!
Here's how we could clean it up:
+def bytes_to_gb(bytes_value): + return bytes_value / (1024 ** 3) + +RAM_SNAPSHOT_PATH = "Ram_Snapshot.txt" + def capture_ram_snapshot(): log.info("Capturing RAM Snapshot...") memory = psutil.virtual_memory() swap = psutil.swap_memory() - with open("Ram_Snapshot.txt", "w") as file: + with open(RAM_SNAPSHOT_PATH, "w") as file: try: - file.write(f"Total RAM: {memory.total / (1024 ** 3):.2f} GB\n") + file.write(f"Total RAM: {bytes_to_gb(memory.total):.2f} GB\n") # Apply similar changes to other lines...
41-58: Let's add some type hints to make this even cooler! 🎯The function works great, but adding type hints would make it easier for others to understand and for IDEs to help catch bugs!
Here's how we could improve it:
+from typing import Dict, Any, Union + +SYSTEM_INFO_PATH = "SystemRam_Info.txt" + -def gather_system_info(): +def gather_system_info() -> Dict[str, Any]: log.info("Gathering system information...") try: sys_info: Dict[str, Union[tuple, str, int]] = { 'Architecture': platform.architecture(), 'System': platform.system(), 'Machine': platform.machine(), 'Processor': platform.processor(), 'Page Size (bytes)': struct.calcsize("P"), } except Exception as e: log.error(f"Error gathering system information: {e}") sys_info = {'Error': 'Failed to gather system information'} - with open("SystemRam_Info.txt", "w") as file: + with open(SYSTEM_INFO_PATH, "w") as file: for key, value in sys_info.items(): file.write(f"{key}: {value}\n") return sys_info # Return the info for potential reuse
104-106: Clean up time! Let's remove those commented-out lines! 🧹These commented lines about Windows API should probably be removed if they're not needed anymore.
- # file_device = win32api.GetFileAttributes(file_path) if os.path.exists(file_path) else 'N/A' region_metadata[' File Path'] = file_path - # region_metadata['File Device'] = file_deviceCODE/vulnscan.py (1)
181-197: Add a progress bar to see how it's going! 📊The scanning could take hours, and right now you can't tell how much is left. Let's add a cool progress bar!
with ThreadPoolExecutor(max_workers=max_workers) as executor: + total_paths = len(paths) + completed = 0 futures = [ executor.submit( scan_path, "VulnScan/Model SenseMini .3n3.pth", path, "VulnScan/Vectorizer .3n3.pkl" ) for path in paths ] for future in futures: try: future.result() + completed += 1 + if completed % 100 == 0: + progress = (completed / total_paths) * 100 + log.info(f"Scan progress: {progress:.1f}% ({completed}/{total_paths})") except Exception as e: log.error(f"Scan failed: {e}")CODE/logicytics/Logger.py (2)
Line range hint
142-161: Make the warning super clear!⚠️ The warning about not using
raw()could be clearer about why it's dangerous. Also, let's catch specific exceptions!""" Logs a raw message directly to the log file. - This should only be called from within the Log class. - So do not use this method in your code. + WARNING: This method is for internal use only! Using it directly can mess up + your log file format and make it hard to read. Use info(), debug(), or + other public methods instead.🧰 Tools
🪛 Ruff (0.8.2)
150-150: f-string without any placeholders
Remove extraneous
fprefix(F541)
288-295: Make the timing info easier to read! ⏱️The elapsed time is shown in raw seconds, which isn't super readable. Let's format it nicely!
- elapsed_time = end_time - start_time + elapsed_time = end_time - start_time + if elapsed_time < 0.001: + formatted_time = f"{elapsed_time*1000000:.2f}μs" + elif elapsed_time < 1: + formatted_time = f"{elapsed_time*1000:.2f}ms" + else: + formatted_time = f"{elapsed_time:.2f}s" - self.debug(f"{func.__name__}({func_args}) executed in {elapsed_time} -> returned {type(result).__name__}") + self.debug(f"{func.__name__}({func_args}) finished in {formatted_time} -> returned {type(result).__name__}")
🛑 Comments failed to post (8)
CODE/sensitive_data_miner.py (4)
15-21:
⚠️ Potential issueWhoa! 🚨 Hold up - We're dealing with some super sensitive file types here!
Hey, adding all these file extensions like
.pst(Outlook emails),.mdf(SQL Server databases), and.accdb(Access databases) is pretty risky! These files often contain private stuff like:
- Email archives with personal info
- Database backups with user data
- Configuration files with passwords
Consider:
- Adding a warning message before copying these sensitive files
- Implementing file size limits to prevent copying large database files
- Adding an option to exclude certain file types based on user role or permissions
125-128: 🛠️ Refactor suggestion
Let's add a safety check before we start digging! ✋
Starting this sensitive operation without asking the user first is like borrowing someone's phone without asking - not cool!
Add a confirmation prompt:
if __name__ == "__main__": log.warning( "Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)") + confirm = input("This tool will search for and copy sensitive files. Are you sure you want to continue? (yes/no): ") + if confirm.lower() != "yes": + log.info("Operation cancelled by user") + exit(0) Mine.passwords()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": log.warning( "Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)") confirm = input("This tool will search for and copy sensitive files. Are you sure you want to continue? (yes/no): ") if confirm.lower() != "yes": log.info("Operation cancelled by user") exit(0) Mine.passwords()
37-54: 🛠️ Refactor suggestion
Watch out for those logs! 👀
The debug logging here might accidentally spill the beans about where sensitive files are located on the system. That's like posting your house key's location on social media - not cool!
Here's how to make it safer:
- log.debug(f"Skipped {file_path}, Unsupported due to {file_path.suffix} extension") + log.debug(f"Skipped file with extension: {file_path.suffix}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.path_list = [] try: path_list = os.listdir(root) except WindowsError as e: if DEBUG: # Log the error if in debug mode, as it is a common occurrence. log.warning(f"Permission Denied: {e}") for filename in path_list: file_path = root / filename if ( keyword.lower() in filename.lower() and file_path.is_file() and file_path.suffix in allowed_extensions ): matching_files.append(file_path) else: log.debug(f"Skipped file with extension: {file_path.suffix}")
91-99: 🛠️ Refactor suggestion
This code could accidentally turn your PC into a 🐌
Running unlimited parallel searches across your entire C: drive? That's like trying to eat an entire pizza in one bite!
Let's make it safer:
- Add a max worker limit to ThreadPoolExecutor
- Add a progress bar
- Allow users to specify search paths
Here's how:
- with ThreadPoolExecutor() as executor: + with ThreadPoolExecutor(max_workers=4) as executor: + total_dirs = sum(1 for _ in os.walk(drives_root)) + processed = 0 for root, dirs, _ in os.walk(drives_root): + processed += 1 + if processed % 100 == 0: + log.info(f"Processed {processed}/{total_dirs} directories")Committable suggestion skipped: line range outside the PR's diff.
CODE/dump_memory.py (2)
72-78:
⚠️ Potential issueOops! Found a sneaky bug in the disk space check! 🐛
The
returnstatement is inside theifblock but outside the error logging. This could cause silent failures!if os.path.exists("Ram_Dump.txt"): required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 1.5 # 2x safety margin free_space = psutil.disk_usage(".").free if free_space < required_space: log.error(f"Not enough disk space. Need {required_space / 1024 / 1024:.2f}MB") - return + return📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if os.path.exists("Ram_Dump.txt"): required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 1.5 # 2x safety margin free_space = psutil.disk_usage(".").free if free_space < required_space: log.error(f"Not enough disk space. Need {required_space / 1024 / 1024:.2f}MB") return
133-140: 🛠️ Refactor suggestion
Let's make the main function more robust! 💪
The main function could use some error handling to make sure one failing task doesn't stop the others.
Here's how we could make it better:
@log.function def main(): log.info("Starting system memory collection tasks...") + success = True + + try: capture_ram_snapshot() + except Exception as e: + log.error(f"Failed to capture RAM snapshot: {e}") + success = False + + try: gather_system_info() + except Exception as e: + log.error(f"Failed to gather system info: {e}") + success = False + + try: memory_dump() - log.info("All tasks completed [dump_memory.py].") + except Exception as e: + log.error(f"Failed to create memory dump: {e}") + success = False + + status = "completed" if success else "completed with errors" + log.info(f"All tasks {status} [dump_memory.py].") + return success📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Main function to run all tasks @log.function def main(): log.info("Starting system memory collection tasks...") success = True try: capture_ram_snapshot() except Exception as e: log.error(f"Failed to capture RAM snapshot: {e}") success = False try: gather_system_info() except Exception as e: log.error(f"Failed to gather system info: {e}") success = False try: memory_dump() except Exception as e: log.error(f"Failed to create memory dump: {e}") success = False status = "completed" if success else "completed with errors" log.info(f"All tasks {status} [dump_memory.py].") return successCODE/vulnscan.py (1)
166-171:
⚠️ Potential issueThose hard-coded paths won't work everywhere! 🌍
Not everyone's computer has the same folders, and some might be using Mac or Linux! Let's make this work everywhere.
Consider moving these paths to a config file or getting them from environment variables:
- base_paths = [ - "C:\\Users\\", - "C:\\Windows\\Logs", - "C:\\Program Files", - "C:\\Program Files (x86)" - ] + # Load paths from config file + config_file = "config.ini" + base_paths = load_scan_paths_from_config(config_file)Committable suggestion skipped: line range outside the PR's diff.
CODE/logicytics/Logger.py (1)
251-266: 🛠️ Refactor suggestion
Add better checks for the message format! 🔍
The code doesn't check if the message types are valid before trying to use them. This could lead to confusing errors!
def parse_execution(self, message_log: list[list[str, str]]): + valid_types = {'debug', 'info', 'warning', 'error', 'critical', 'err', 'warn', 'crit', 'except'} if message_log: for message_list in message_log: if len(message_list) == 2: + msg_type = message_list[1].lower() + if msg_type not in valid_types: + self.__internal(f"Invalid log type '{msg_type}'. Using 'debug' instead.") + msg_type = 'debug' - self.string(message_list[0], message_list[1]) + self.string(message_list[0], msg_type)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.def parse_execution(self, message_log: list[list[str, str]]): """ Parses and logs a list of messages with their corresponding log types. Only use this method if you have a list of lists where each inner list contains a message and its log type. Use case include "Execute.script()" function. :param message_log: A list of lists, where each inner list contains a message and its log type. """ valid_types = {'debug', 'info', 'warning', 'error', 'critical', 'err', 'warn', 'crit', 'except'} if message_log: for message_list in message_log: if len(message_list) == 2: msg_type = message_list[1].lower() if msg_type not in valid_types: self.__internal(f"Invalid log type '{msg_type}'. Using 'debug' instead.") msg_type = 'debug' self.string(message_list[0], msg_type) else: self.__internal( f"Message List is not in the correct format: {message_list}" )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 13
🔭 Outside diff range comments (8)
CODE/vulnscan.py (1)
Line range hint
24-52: Heads up! There's a security risk in loading PyTorch models 🚨Using
torch.load()without safety checks is risky - it can execute malicious code hidden in the model file. This is super important since you're scanning potentially untrusted files!Here's how to make it safer:
- return torch.load(model_path_to_load, weights_only=False) + # Use pickle_module=None to prevent arbitrary code execution + return torch.load(model_path_to_load, weights_only=True, pickle_module=None)CODE/sensitive_data_miner.py (3)
Line range hint
71-94: 🛡️ Secure that file copying process!The copy function is working, but it's like leaving your front door wide open! Here are some security tips:
- The logs are showing full file paths - that's risky!
- We're not checking file permissions
- No encryption for sensitive files
Here's a safer version:
@staticmethod def __copy_file(src_file_path: Path, dst_file_path: Path): try: + # Check file size and permissions + if src_file_path.stat().st_size > 10_000_000: # 10MB limit + log.warning("File exceeds size limit") + return shutil.copy(src_file_path, dst_file_path) - log.debug(f"Copied {src_file_path} to {dst_file_path}") + log.debug("Copied file successfully") except FileExistsError as e: - log.warning(f"Failed to copy file due to it already existing: {e}") + log.warning("File already exists in destination") except Exception as e: - log.error(f"Failed to copy file: {e}") + log.error("File copy failed")
Line range hint
96-131: ⚡ Your search is too powerful - let's add some guardrails!This function is like a race car without brakes! 🏎️ It's scanning the entire C: drive without any limits.
Here's what we should add:
- Let users specify which drives/folders to scan
- Add a progress bar (using
tqdm)- Add rate limiting to avoid system overload
Here's how:
@classmethod def __search_and_copy_files(cls, keyword: str): + # Allow configurable root directory + drives_root = Path(os.getenv('SEARCH_ROOT', 'C:\\')) destination = Path("Password_Files") if not destination.exists(): destination.mkdir() + # Add progress tracking + from tqdm import tqdm with ThreadPoolExecutor() as executor: - for root, dirs, _ in os.walk(drives_root): + for root, dirs, _ in tqdm(os.walk(drives_root), desc=f"Searching for {keyword}"):
Line range hint
133-173: 🎯 Make the password search smarter and safer!The keywords list is like a treasure map to sensitive data! Let's make it more secure and flexible:
- Move keywords to a config file
- Add regex pattern support
- Add an audit log for compliance
Here's how:
@classmethod @log.function def passwords(cls): - keywords = ["password", "secret", "code", "login", "api", "key", - "token", "auth", "credentials", "private", ] + # Load keywords from config + from configparser import ConfigParser + config = ConfigParser() + config.read('config.ini') + keywords = config.get('sensitive_data', 'keywords').split(',') + + # Start audit log + log.audit(f"Starting sensitive data scan with {len(keywords)} keywords") destination = Path("Password_Files") if destination.exists(): shutil.rmtree(destination) destination.mkdir() + destination.chmod(0o700) # Restrict permissionsCODE/dir_list.py (1)
Line range hint
31-33: PowerShell command needs some security love! 🔒The PowerShell command is using raw directory input which could be dangerous if someone passes in malicious input. Let's make it safer!
- command = f"powershell -Command Get-ChildItem {directory} -Recurse" + safe_directory = directory.replace('"', '`"') # Escape quotes + command = f'powershell -NoProfile -Command "Get-ChildItem \\""{safe_directory}\\"" -Recurse"'CODE/Logicytics.py (2)
Line range hint
291-350: Let's make the threading super efficient! 🏃♂️The threading code works, but we can make it way better using a thread pool:
+from concurrent.futures import ThreadPoolExecutor, as_completed + def execute_scripts(): """Executes the scripts in the execution list based on the action.""" if ACTION == "threaded" or ACTION == "depth": - def threaded_execution(execution_list_thread, index_thread): - log.debug(f"Thread {index_thread} started") + def execute_single_script(script): + log.debug(f"Executing {script}") try: - log.parse_execution(Execute.script(execution_list_thread[index_thread])) - log.info(f"{execution_list_thread[index_thread]} executed") + log.parse_execution(Execute.script(script)) + log.info(f"{script} executed") + return script, None except Exception as err: - log.error(f"Error in thread: {err}") - log.debug(f"Thread {index_thread} finished") + log.error(f"Error executing {script}: {err}") + return script, err - threads = [] execution_list = generate_execution_list() - for index, _ in enumerate(execution_list): - thread = threading.Thread( - target=threaded_execution, - args=(execution_list, index)) - threads.append(thread) - thread.start() - - for thread in threads: - thread.join() + with ThreadPoolExecutor() as executor: + futures = {executor.submit(execute_single_script, script): script + for script in execution_list} + + for future in as_completed(futures): + script = futures[future] + result, error = future.result() + if error: + log.error(f"Failed to execute {script}") + else: + log.debug(f"Completed {script}")This is way cooler because:
- It uses Python's built-in thread pool 🎯
- It handles errors better 🛠️
- It shows progress as scripts complete ✨
- It's faster because it reuses threads 🚀
Line range hint
401-431: Let's make the main function super reliable! 💪The main function looks good, but we should add some error handling to make it bulletproof:
@log.function def Logicytics(): """Main entry point for Logicytics.""" + try: + # Track success of each step + steps_completed = [] + # Get flags_list and configs get_flags() + steps_completed.append("flags") + # Check for special actions handle_special_actions() + steps_completed.append("special_actions") + # Check for privileges and errors check_privileges() + steps_completed.append("privileges") + # Execute scripts execute_scripts() + steps_completed.append("scripts") + # Zip generated files zip_generated_files() + steps_completed.append("zip") + # Finish with sub actions handle_sub_action() + steps_completed.append("sub_actions") + + log.info("✨ All steps completed successfully!") + + except Exception as e: + log.error(f"Failed during step: {steps_completed[-1] if steps_completed else 'initialization'}") + log.error(f"Error: {e}") + log.info("🔄 Cleaning up...") + # Add cleanup code here if needed + + finally: # Finish input("Press Enter to exit...")This makes the function:
- Track which steps completed successfully 📝
- Tell you exactly where it failed if something goes wrong 🎯
- Clean up properly even if there's an error 🧹
CODE/logicytics/Flag.py (1)
Line range hint
378-385: Hey! There's a syntax error in the__colorifymethod! 🚨The docstring is broken! It's causing Python to get super confused. Let's fix it:
@classmethod def __colorify(cls, text: str, color: str) -> str: - The existing docstring is comprehensive and follows good documentation practices. It clearly explains the function's purpose, parameters, return value, and provides context about the color codes. Therefore: - - KEEP_EXISTING + """ + Colorize text with ANSI color codes. + + Args: + text (str): The text to colorize + color (str): The color code ('y' for yellow, 'r' for red, 'b' for blue) + + Returns: + str: The colorized text with ANSI escape codes + """ colors = { "y": "\033[93m", "r": "\033[91m", "b": "\033[94m" }🧰 Tools
🪛 Ruff (0.8.2)
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: Simple statements must be separated by newlines or semicolons
379-379: SyntaxError: missing closing quote in string literal
379-380: SyntaxError: Expected a statement
🧹 Nitpick comments (28)
CODE/vulnscan.py (2)
Line range hint
54-87: The error handling could be more specific! 🎯Instead of catching all exceptions with a generic
Exception, it would be better to catch specific ones. This helps you handle different problems in different ways.Here's a better way to handle errors:
- try: + try: with model_lock: if model_to_use is None: log.info(f"Loading model from {model_path}") model_to_use = load_model(model_path) with vectorizer_lock: if vectorizer_to_use is None: log.info(f"Loading vectorizer from {vectorizer_path}") vectorizer_to_use = joblib.load(vectorizer_path) vulnscan(model_to_use, scan_paths, vectorizer_to_use) - except Exception as err: - log.error(f"Error scanning path {scan_paths}: {err}") + except FileNotFoundError as err: + log.error(f"File not found while scanning {scan_paths}: {err}") + except PermissionError as err: + log.error(f"Permission denied while scanning {scan_paths}: {err}") + except (torch.serialization.pickle.UnpicklingError, RuntimeError) as err: + log.error(f"Model loading failed for {scan_paths}: {err}") + except Exception as err: + log.error(f"Unexpected error scanning {scan_paths}: {err}")
199-202: Add some path validation before scanning! 🔍You should check if paths exist and are accessible before trying to scan them.
Here's how to validate paths:
def validate_path(path): if not os.path.exists(path): log.warning(f"Path does not exist: {path}") return False try: # Test if we can actually read from this path if os.path.isfile(path): with open(path, 'r', errors='ignore'): pass return True except (PermissionError, OSError) as e: log.warning(f"Cannot access path {path}: {e}") return False # Then in your main loop: valid_paths = [ os.path.join(root, file_main) for base_path in base_paths if validate_path(base_path) for root, _, files_main in os.walk(base_path) for file_main in files_main if validate_path(os.path.join(root, file_main)) ]CODE/dump_memory.py (4)
16-18: Let's make that file size limit super clear! 🎯The
LIMIT_FILE_SIZEconstant could use a more descriptive name and comment. It's not immediately obvious that this is in MiB (Mebibytes).Here's a clearer way to write it:
-# If the file size exceeds this limit, the file will be truncated with a message -# Put 0 to disable the limit -LIMIT_FILE_SIZE = 20 # Always in MiB +# Maximum size limit for memory dump files in MiB (Mebibytes) +# Set to 0 to disable the size limit +MAX_DUMP_FILE_SIZE_MIB = 20
21-58: Nice memory snapshot function! 🚀The function looks solid! Just a small suggestion to make it even better - we could add some units to the log messages and maybe round those GB values to make them easier to read.
Here's how we could make it more user-friendly:
- file.write(f"Total RAM: {memory.total / (1024 ** 3):.2f} GB\n") - file.write(f"Used RAM: {memory.used / (1024 ** 3):.2f} GB\n") + # Convert to GB and round to 2 decimal places for readability + total_gb = round(memory.total / (1024 ** 3), 2) + used_gb = round(memory.used / (1024 ** 3), 2) + file.write(f"Total RAM: {total_gb:,} GB\n") # Add thousand separators + file.write(f"Used RAM: {used_gb:,} GB\n")
60-95: Let's get even more system info! 💪The function's doing a great job, but we could make it even cooler by adding more useful system details that might help with debugging!
Here's what we could add:
sys_info = { 'Architecture': platform.architecture(), 'System': platform.system(), 'Machine': platform.machine(), 'Processor': platform.processor(), 'Page Size (bytes)': struct.calcsize("P"), + 'Python Version': platform.python_version(), + 'CPU Count': psutil.cpu_count(), + 'CPU Frequency': psutil.cpu_freq().current if psutil.cpu_freq() else 'N/A', + 'Boot Time': datetime.fromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S'), }Don't forget to add
from datetime import datetimeat the top!
164-166: Time to clean up those commented lines! 🧹These commented-out lines about Windows API should probably be removed since we're not using them anymore. If we need them later, we can always get them back from git history!
- # file_device = win32api.GetFileAttributes(file_path) if os.path.exists(file_path) else 'N/A' region_metadata[' File Path'] = file_path - # region_metadata['File Device'] = file_deviceCODE/sensitive_data_miner.py (1)
177-180: 🎮 Give users more control!The entry point is super basic - let's make it more user-friendly and safe!
Here's a cooler version:
if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser(description="Safely search for sensitive files") + parser.add_argument("--root", default="C:\\", help="Root directory to search") + parser.add_argument("--max-size", type=int, default=10, help="Max file size in MB") + args = parser.parse_args() + + # Ask for confirmation + response = input("⚠️ This tool will search for sensitive files. Are you sure? (yes/no): ") + if response.lower() != "yes": + log.info("Operation cancelled by user") + exit(0) + log.warning("Sensitive Data Miner Initialized. Processing may take a while...") - Mine.passwords() + Mine.passwords(root=args.root, max_size=args.max_size)CODE/logicytics/__init__.py (1)
49-50: Nice job with the deprecation warning! 👏The colored warning message is super helpful for other devs to spot deprecated stuff. Just one suggestion - maybe we could make it even better by adding a stack trace to show exactly where the deprecated function is being called?
- print( - f"\033[91mDeprecationWarning: A call to the deprecated function {func.__name__}() has been called, {reason}. Function will be removed at version {removal_version}\033[0m") + import traceback + stack = ''.join(traceback.format_stack()[:-1]) + print( + f"\033[91mDeprecationWarning: A call to the deprecated function {func.__name__}() has been called, {reason}. Function will be removed at version {removal_version}\n" + f"Called from:\n{stack}\033[0m")CODE/event_log.py (1)
49-57: Memory-friendly event processing! 🧠Writing all events at once could use a lot of memory. Let's process them in chunks!
- events = c.query(query) - f.write(f"Total records: {len(events)}\n\n") - log.debug(f"Number of events retrieved: {len(events)}") - for event in events: + CHUNK_SIZE = 1000 + total_events = 0 + for i, event in enumerate(c.query(query)): + if i == 0: + f.write("Processing events...\n\n") event_data = { 'Event Category': event.Category, 'Time Generated': event.TimeGenerated, 'Source Name': event.SourceName, 'Event ID': event.EventCode, 'Event Type': event.Type, 'Event Data': event.InsertionStrings } f.write(str(event_data) + '\n\n') + total_events += 1 + if total_events % CHUNK_SIZE == 0: + log.debug(f"Processed {total_events} events...") + f.write(f"\nTotal records processed: {total_events}\n")CODE/logicytics/Get.py (1)
10-11: Hey, nice update to the function! 🎯The new
exclude_filesparameter is super helpful for filtering out unwanted files. Just one tiny thing - adding a type hint forexclude_fileswould make it even better!-def list_of_files(directory: str, extensions: tuple | bool = True, append_file_list: list = None, - exclude_files: list = None) -> list: +def list_of_files(directory: str, extensions: tuple | bool = True, append_file_list: list[str] | None = None, + exclude_files: list[str] | None = None) -> list[str]:CODE/media_backup.py (1)
111-136: Cool update to make this a class method! 🚀The change from instance method to class method makes total sense since we're not using any instance variables. Just one thing though - having a hardcoded backup directory name isn't very flexible.
Consider making the backup directory configurable:
- backup_directory = "MediaBackup" + backup_directory = os.getenv("MEDIA_BACKUP_DIR", "MediaBackup")CODE/bluetooth_details.py (2)
60-68: Nice error handling! 🛡️The way you're handling errors is great - catching specific exceptions and logging them clearly. Just one suggestion to make it even better:
Consider adding the command that failed to the error log:
- log.error(f"Failed to query Bluetooth devices: {e}") + log.error(f"Failed to query Bluetooth devices with command '{command}': {e}")
76-81: Good thinking with the fallback messages! 🤔Having fallback messages is super helpful, but we can make the code cleaner by not repeating the same message.
Here's how to make it more DRY (Don't Repeat Yourself):
+ FALLBACK_MSG = 'Unknown (Fallback due to failed Get request)' device_info = { - 'Name': device.get('FriendlyName', 'Unknown (Fallback due to failed Get request)'), - 'Device ID': device.get('DeviceID', 'Unknown (Fallback due to failed Get request)'), - 'Description': device.get('Description', 'Unknown (Fallback due to failed Get request)'), - 'Manufacturer': device.get('Manufacturer', 'Unknown (Fallback due to failed Get request)'), - 'Status': device.get('Status', 'Unknown (Fallback due to failed Get request)'), - 'PNP Device ID': device.get('PnpDeviceID', 'Unknown (Fallback due to failed Get request)') + 'Name': device.get('FriendlyName', FALLBACK_MSG), + 'Device ID': device.get('DeviceID', FALLBACK_MSG), + 'Description': device.get('Description', FALLBACK_MSG), + 'Manufacturer': device.get('Manufacturer', FALLBACK_MSG), + 'Status': device.get('Status', FALLBACK_MSG), + 'PNP Device ID': device.get('PnpDeviceID', FALLBACK_MSG) }CODE/logicytics/FileManagement.py (1)
Line range hint
75-91: Hey, let's make this safer! 🛡️The code looks clean, but we might want to be extra careful about what files we're zipping. Instead of just blocking certain file types, maybe we should only allow specific safe file types. It's like having a whitelist instead of a blacklist - much safer!
Here's how we could make it safer:
- excluded_extensions = (".py", ".exe", ".bat", ".ps1", ".pkl", ".pth") - excluded_prefixes = ("config.ini", "SysInternal_Suite", - "__pycache__", "logicytics", "VulnScan", - "Vectorizer features") - return [ - f for f in os.listdir(path) - if not f.endswith(excluded_extensions) and not f.startswith(excluded_prefixes) - ] + allowed_extensions = (".txt", ".csv", ".json", ".xml", ".log") + allowed_prefixes = ("data_", "report_", "backup_") + return [ + f for f in os.listdir(path) + if f.endswith(allowed_extensions) and any(f.startswith(prefix) for prefix in allowed_prefixes) + ]CODE/bluetooth_logger.py (2)
147-166: Let's add some error handling to make this bulletproof! 💪The function looks great with the new decorator and awesome documentation! But what if something goes wrong while collecting the data? Let's add some try-except blocks to handle any potential issues.
Here's a suggestion:
@log.function def log_bluetooth(): + try: log.info("Starting Bluetooth data logging...") filename = "bluetooth_data.txt" timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") save_to_file(filename, "Bluetooth Data Collection - Timestamp", timestamp) # Rest of the function... log.info("Finished Bluetooth data logging.") + except Exception as e: + log.error(f"Failed to log Bluetooth data: {e}") + raise # Re-raise the exception after logging
181-197: Add some type hints to make it even better! ✨The function looks great, but adding type hints would make it even more awesome! It's like adding labels to everything - makes it super clear what goes in and what comes out.
Here's how we could add them:
- def collect_logs(title, command): + def collect_logs(title: str, command: str) -> None:CODE/_debug.py (2)
181-204: Move those version numbers where everyone can see them! 🔍The function is working great, but those version numbers are like hidden treasure! Let's move them to the top of the file or into a class where they're easier to find and update.
Here's what we could do:
+ class PythonVersionConfig: + MIN_VERSION = (3, 11) + MAX_VERSION = (3, 13) def python_version(): version = sys.version.split()[0] - MIN_VERSION = (3, 11) - MAX_VERSION = (3, 13) + min_version = PythonVersionConfig.MIN_VERSION + max_version = PythonVersionConfig.MAX_VERSION try: major, minor = map(int, version.split(".")[:2]) - if MIN_VERSION <= (major, minor) < MAX_VERSION: + if min_version <= (major, minor) < max_version:
238-259: Add progress tracking to see how far we've come! 📊The debug function is doing a lot of cool stuff, but it would be even better if we could see how far along we are in the process. Like a progress bar in a game!
Here's a suggestion:
@log_debug.function def debug(): + total_steps = 7 # Total number of main checks + current_step = 0 + # Clear Debug Log + current_step += 1 + log_debug.info(f"Progress: {current_step}/{total_steps} - Clearing debug log") log_path = "../ACCESS/LOGS/DEBUG/DEBUG.log" if os.path.exists(log_path): os.remove(log_path) # Online Configuration Check + current_step += 1 + log_debug.info(f"Progress: {current_step}/{total_steps} - Checking online configuration") config = get_online_config() # ... rest of the functionCODE/logicytics/Logger.py (3)
123-133: Hey! Your docstrings are looking good but could be even better! 🎯The docstrings are super detailed (which is awesome!), but they're a bit wordy. Try making them shorter and snappier while keeping the important stuff. Like, instead of:
""" Parameters: message (str): The raw message to be written to the log file. """You could write:
""" Args: message (str): Message to write to log file. """Also applies to: 149-164, 300-323, 334-375
172-180: Nice error handling! But let's make it even better! 💪You've got great error handling for Unicode stuff, but that catch-all
Exceptionat the end is pretty broad. Maybe we should catch more specific exceptions that could happen when writing to files, like:try: with open(self.filename, "a", encoding="utf-8") as f: f.write(f"{str(message)}\n") except (UnicodeDecodeError, UnicodeEncodeError) as UDE: self.__internal( f"UnicodeDecodeError: {UDE} - Message: {str(message)}" ) - except Exception as E: + except (IOError, PermissionError) as E: self.__internal(f"Error: {E} - Message: {str(message)}") + except Exception as E: + self.__internal(f"Unexpected error: {E} - Message: {str(message)}")
376-384: Cool timing feature! Let's make it even cooler! 🚀The timing code works great, but we could make it cleaner using a context manager. Here's a suggestion:
+ @contextmanager + def timer(self, func_name: str, func_args: str): + start = time.perf_counter() + yield + elapsed = time.perf_counter() - start + self.debug(f"{func_name}({func_args}) executed in {elapsed} seconds") def wrapper(*args, **kwargs): - start_time = time.perf_counter() func_args = ", ".join([str(arg) for arg in args] + [f"{k}={v}" for k, v in kwargs.items()]) self.debug(f"Running the function {func.__name__}({func_args}).") - result = func(*args, **kwargs) - end_time = time.perf_counter() - elapsed_time = end_time - start_time - self.debug(f"{func.__name__}({func_args}) executed in {elapsed_time} -> returned {type(result).__name__}") - return result + with self.timer(func.__name__, func_args): + result = func(*args, **kwargs) + self.debug(f"{func.__name__}({func_args}) -> returned {type(result).__name__}") + return resultCODE/packet_sniffer.py (3)
345-351: Let's make the interface handling smarter! 🧠The interface correction is cool, but we could make it even better! Here's how:
- Move the corrections to a config file so it's easier to update
- Add more common variations
- Make the retry logic more flexible
Here's what I mean:
- def correct_interface_name(interface_name: str) -> str: - corrections = { - "WiFi": "Wi-Fi", - "Wi-Fi": "WiFi" - } - return corrections.get(interface_name, interface_name) + def correct_interface_name(interface_name: str) -> list[str]: + """Get possible interface name variations.""" + variations = { + "WiFi": ["Wi-Fi", "Wireless", "WLAN"], + "Wi-Fi": ["WiFi", "Wireless", "WLAN"], + "Ethernet": ["Eth0", "Local Area Connection"] + } + return variations.get(interface_name, [interface_name]) for attempt in range(2): # Try original and corrected name try: start_sniffing(interface, packet_count, timeout) break except Exception as err: - if attempt == 0 and interface in ("WiFi", "Wi-Fi"): + if attempt == 0: log.warning(f"Retrying with corrected interface name...") - interface = correct_interface_name(interface) + variations = correct_interface_name(interface) + for var in variations: + try: + start_sniffing(var, packet_count, timeout) + interface = var # Remember working interface name + break + except Exception: + continue else: log.error(f"Failed to sniff packets: {err}")Also applies to: 367-376
204-224: Let's make the packet callback faster! ⚡The callback is working great, but we can make it even better by:
- Moving the debug log outside the callback
- Using a closure instead of nonlocal
- Adding early return for efficiency
Check this out:
+ # Initialize debug logging outside callback + log.debug(f"Starting packet capture with limit: {packet_count}") + + def make_callback(counter=[0]): # Use list for mutable counter def packet_callback(packet: IP) -> bool: - log.debug(f"Received packet: {packet.summary()}") - nonlocal packet_counter - if packet_counter >= packet_count: + if counter[0] >= packet_count: log.info(f"Captured {packet_count} packets, stopping sniffing.") return True log_packet(packet) - packet_counter += 1 + counter[0] += 1 return False + return packet_callback - sniff(iface=interface, prn=packet_callback, count=packet_count, timeout=timeout) + sniff(iface=interface, prn=make_callback(), count=packet_count, timeout=timeout)Also applies to: 225-235
Line range hint
273-323: Let's make those graphs look awesome! 🎨The graph visualization is cool, but we could make it even more customizable! Here's how:
def visualize_graph( - node_colors: str = None, - node_sizes: str = None + node_colors: dict[str, str] | None = None, + node_sizes: dict[str, int] | None = None, + *, # Force keyword arguments for the following parameters + figsize: tuple[int, int] = (12, 8), + font_size: int = 10, + font_weight: str = "bold", + title: str = "Network Connections Graph", + output_file: str = "network_connections_graph.png", + layout_func: callable = nx.spring_layout ): """Visualizes the graph with customizable styling.""" - pos = nx.spring_layout(G) - plt.figure(figsize=(12, 8)) + pos = layout_func(G) + plt.figure(figsize=figsize)This makes it super easy to customize how your graph looks! You can now do cool stuff like:
visualize_graph( figsize=(15, 10), font_size=12, title="My Awesome Network Graph", layout_func=nx.circular_layout )CODE/logicytics/Flag.py (4)
159-159: Yo! Found a TODO comment! 👀The
_generate_summary_and_graphmethod is marked as "Yet in beta". Want me to help implement the missing features or create a GitHub issue to track this?
201-218: Let's make the graph plotting code more robust! 💪The matplotlib code could use some improvements to handle errors better and clean up resources.
Here's a better way to handle the plotting:
-plt.figure(figsize=(10, 6)) -plt.barh(flags, counts, color='skyblue') -plt.xlabel('Usage Count') -plt.title('Flag Usage Frequency') -plt.gca().invert_yaxis() # Invert y-axis for better readability -plt.subplots_adjust(left=0.2, right=0.8, top=0.9, bottom=0.1) # Adjust layout +try: + fig, ax = plt.subplots(figsize=(10, 6)) + ax.barh(flags, counts, color='skyblue') + ax.set_xlabel('Usage Count') + ax.set_title('Flag Usage Frequency') + ax.invert_yaxis() # Invert y-axis for better readability + fig.subplots_adjust(left=0.2, right=0.8, top=0.9, bottom=0.1) # Adjust layout + + # Save the graph with error handling + for path in ['../ACCESS/DATA/Flag_usage_summary.png', + '../../ACCESS/DATA/Flag_usage_summary.png', + 'Flag_usage_summary.png']: + try: + fig.savefig(path) + print(f"\nFlag Usage Summary Graph saved to '{path}'") + break + except FileNotFoundError: + continue +finally: + plt.close() # Always clean up the figure
525-526: Found some unimplemented features! 🚧The
--webhookand--restoreflags are marked as "Not yet Implemented". Want me to help implement these features or create GitHub issues to track them?Also applies to: 532-534
722-736: Let's make the flag validation simpler! 🎯The flag validation logic could be simplified using sets for better readability.
-used_flags = [flag for flag in vars(args) if getattr(args, flag)] - -if not special_flag_used and len(used_flags) > 1: - print("Invalid combination of flags: Maximum 1 action flag allowed.") - exit(1) +# Convert args to a set of active flags +active_flags = {flag for flag, value in vars(args).items() if value} + +# Early exit if no flags +if not active_flags: + cls.show_help_menu() + exit(0) + +# Check flag count based on special flag usage +max_flags = 2 if special_flag_used else 1 +if len(active_flags) > max_flags: + print(f"Invalid combination of flags: Maximum {max_flags} {'flags' if max_flags > 1 else 'flag'} allowed.") + exit(1)
🛑 Comments failed to post (13)
CODE/vulnscan.py (2)
192-197: 🛠️ Refactor suggestion
These hard-coded paths should be configurable! ⚙️
Having fixed paths in the code makes it less flexible. What if someone wants to scan different locations?
Consider moving these paths to a config file or accepting them as command-line arguments:
# config.py DEFAULT_SCAN_PATHS = [ "C:\\Users\\", "C:\\Windows\\Logs", "C:\\Program Files", "C:\\Program Files (x86)" ] # In main script import argparse parser = argparse.ArgumentParser() parser.add_argument('--paths', nargs='+', default=DEFAULT_SCAN_PATHS, help='Paths to scan for vulnerabilities') args = parser.parse_args() base_paths = args.paths
213-215: 🛠️ Refactor suggestion
Don't hard-code your model paths! 🎯
Just like the scan paths, your model and vectorizer paths should be configurable.
Move these to command-line arguments or environment variables:
parser.add_argument('--model-path', default="VulnScan/Model SenseMini .3n3.pth", help='Path to the model file') parser.add_argument('--vectorizer-path', default="VulnScan/Vectorizer .3n3.pkl", help='Path to the vectorizer file')CODE/dump_memory.py (1)
132-137:
⚠️ Potential issueOops! Found a bug in the disk space check! 🐛
There's a sneaky bug here - the
returnstatement is inside theifblock that checks disk space, which means it'll returnNonewhen there's not enough space but continue processing if the file doesn't exist yet!Let's fix that:
# Check available disk space if os.path.exists("Ram_Dump.txt"): required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 1.5 # 2x safety margin free_space = psutil.disk_usage(".").free if free_space < required_space: log.error(f"Not enough disk space. Need {required_space / 1024 / 1024:.2f}MB") - return + return📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if os.path.exists("Ram_Dump.txt"): required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 1.5 # 2x safety margin free_space = psutil.disk_usage(".").free if free_space < required_space: log.error(f"Not enough disk space. Need {required_space / 1024 / 1024:.2f}MB") returnCODE/sensitive_data_miner.py (2)
28-67: 🛠️ Refactor suggestion
🔒 Be careful with logging file paths!
Your error handling is on point with that try-except block! But here's the thing - logging file paths might accidentally reveal sensitive info in the logs.
Let's make it safer:
- log.debug(f"Skipped {file_path}, Unsupported due to {file_path.suffix} extension") + log.debug(f"Skipped file with extension: {file_path.suffix}")Also, you might want to add:
- A file size limit to avoid huge files
- A depth limit for directory searching
- A way to exclude certain directories (like System32)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.""" Searches for files containing a specified keyword in their names within a given directory. Parameters: root (Path): The root directory to search in for files. keyword (str): The keyword to search for in file names (case-insensitive). Returns: list: A list of file paths matching the search criteria, which: - Contain the keyword in their filename (case-insensitive) - Are files (not directories) - Have file extensions in the allowed_extensions list Raises: WindowsError: If permission is denied when accessing the directory (logged as a warning in debug mode) Notes: - Skips files with unsupported extensions, logging debug information - Uses case-insensitive keyword matching """ matching_files = [] path_list = [] try: path_list = os.listdir(root) except WindowsError as e: if DEBUG: # Log the error if in debug mode, as it is a common occurrence. log.warning(f"Permission Denied: {e}") for filename in path_list: file_path = root / filename if ( keyword.lower() in filename.lower() and file_path.is_file() and file_path.suffix in allowed_extensions ): matching_files.append(file_path) else: log.debug(f"Skipped file with extension: {file_path.suffix}") return matching_files
15-21: 💡 Codebase verification
⚠️ Potential issue🚨 Bruh, this code needs some serious safety warnings!
So I just dug deeper into the code, and here's the tea: While it does have some basic error handling for permissions, it's missing the most important thing - a big fat warning message to users about the serious consequences of using this! 💀
The code's even looking for stuff with keywords like "token", "auth", and "credentials" - that's like next-level private info! But get this - there's no upfront warning or permission check before it starts snooping around. Not cool!
You should:
- Add a huge warning message at the start that makes users confirm they have permission
- Make them type "YES I HAVE PERMISSION" or something before it runs
- Add comments about legal requirements and responsible usage
- Document what kinds of files it might find (so people know how serious this is)
Like, imagine if someone used this without knowing what it does - that's a big yikes! 😬
🔗 Analysis chain
🚨 Heads up! This tool might expose super sensitive stuff!
Hey there! Just noticed you're searching through some pretty serious file types like databases (.sql, .mdb), email files (.pst, .msg), and archives (.zip, .tar). That's like having a master key to everyone's digital lockers! 😱
Make sure you:
- Have proper authorization to scan these files
- Handle the found data with extreme care
- Consider adding a warning message about responsible usage
Let me help you check if there are any company policies or guidelines about handling sensitive data:
🚫 Yo, this tool is straight-up dangerous without proper permission!
OMG, I just checked the README and this is part of a bigger tool called Logicytics that's designed to grab ALL kinds of sensitive stuff from Windows systems! 😱 The tool literally says it's for "gathering as much sensitive data as possible" - that's wild!
The README has some super important warnings we gotta pay attention to:
- "Please remember that extracting data from a system without proper authorization is illegal and unethical"
- "Always obtain proper authorization before extracting any data from a system"
Plus, this
sensitive_data_miner.pyis described as copying "all files that can be considered sensitive in a neat folder" - that's like going through someone's digital diary without asking! 🚫🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Look for security policies or guidelines rg -i "security|policy|guideline|sensitive|data" README.md docs/Length of output: 3910
Script:
#!/bin/bash # Let's check if there are any security measures or warnings in the code itself rg -i "warning|auth|permission|consent" CODE/sensitive_data_miner.pyLength of output: 532
CODE/logicytics/__init__.py (1)
12-14:
⚠️ Potential issueYo, there's a syntax error in your docstring! 🚫
The text "KEEP_EXISTING" shouldn't be there - it's breaking your code! Let's fix that by removing those lines.
- The existing docstrings for the `deprecated` function and its nested functions are already well-structured and comprehensive. They follow Python docstring conventions, provide clear descriptions, specify parameter types, and explain return values. Therefore, the recommendation is: - - KEEP_EXISTING🧰 Tools
🪛 Ruff (0.8.2)
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Compound statements are not allowed on the same line as simple statements
12-12: SyntaxError: Got unexpected token `
12-12: SyntaxError: Got unexpected token `
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Expected ',', found name
12-12: SyntaxError: Expected ',', found name
12-12: SyntaxError: Expected ',', found name
12-12: SyntaxError: Expected ',', found name
12-12: SyntaxError: Expected ',', found 'and'
12-12: SyntaxError: Simple statements must be separated by newlines or semicolons
12-12: SyntaxError: Expected ',', found name
12-12: SyntaxError: Expected an expression
12-13: SyntaxError: Expected a statement
CODE/dir_list.py (1)
59-63:
⚠️ Potential issueWatch out for thread overload! 🚨
You're creating threads without any limits - that could crash your computer if there are too many directories! Let's add a max_workers parameter to keep things under control.
- with ThreadPoolExecutor() as executor: + with ThreadPoolExecutor(max_workers=min(32, os.cpu_count() * 4)) as executor:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.with ThreadPoolExecutor(max_workers=min(32, os.cpu_count() * 4)) as executor: subdirectories = [os.path.join(base_directory, d) for d in os.listdir(base_directory) if os.path.isdir(os.path.join(base_directory, d))] futures = [executor.submit(run_command_threaded, subdir, file, message, encoding) for subdir in subdirectories]CODE/event_log.py (2)
36-37: 🛠️ Refactor suggestion
Don't forget to clean up! 🧹
The WMI connection needs to be closed properly to avoid memory leaks. Let's wrap it in a context manager!
- # Initialize WMI connection - c = wmi.WMI() + # Use context manager for WMI connection + with wmi.WMI() as c: + # Rest of the code...Committable suggestion skipped: line range outside the PR's diff.
80-85: 🛠️ Refactor suggestion
Make your threads more robust! 💪
If one thread crashes, your program might hang forever waiting for it. Let's add some timeout and error handling!
for log_type_main, output_file_main in threads_items: thread = threading.Thread(target=parse_event_logs, args=(log_type_main, output_file_main)) + thread.daemon = True # Don't hang if main thread exits threads.append(thread) thread.start() for thread in threads: - thread.join() + thread.join(timeout=300) # Wait max 5 minutes per thread + if thread.is_alive(): + log.error(f"Thread for {thread.name} timed out!")Committable suggestion skipped: line range outside the PR's diff.
CODE/logicytics/Get.py (1)
47-47:
⚠️ Potential issueWatch out! There's a potential bug here! 🐛
If
exclude_filesis None (which is its default value), trying to check if a filename isin exclude_fileswill crash with an error. Let's fix that:- and filename not in exclude_files + and (exclude_files is None or filename not in exclude_files)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.and (exclude_files is None or filename not in exclude_files)CODE/logicytics/Logger.py (1)
300-331: 🛠️ Refactor suggestion
Let's make those type hints more precise! 📝
The type hint
list[list[str, str]]isn't quite right in Python. For a list of exactly two strings, you should usetuple[str, str]. Here's how to fix it:-def parse_execution(self, message_log: list[list[str, str]]): +def parse_execution(self, message_log: list[tuple[str, str]]):This tells Python that each item in the list must be a tuple of exactly two strings, which is what your code expects!
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.def parse_execution(self, message_log: list[tuple[str, str]]): """ Parse and log multiple messages with their corresponding log types. This method processes a list of messages, where each message is associated with a specific log type. It is designed for scenarios where multiple log entries need to be processed simultaneously, such as logging script execution results. Parameters: message_log (list[tuple[str, str]]): A list of message entries. Each entry is a tuple containing two elements: - First element: The log message (str) - Second element: The log type (str) Behavior: - Iterates through the provided message log - Logs each message using the specified log type via `self.string()` - Logs an internal warning if a message list does not contain exactly two elements Example: log = Log() log.parse_execution([ ['Operation started', 'info'], ['Processing data', 'debug'], ['Completed successfully', 'info'] ]) """ if message_log: for message_list in message_log: if len(message_list) == 2: self.string(message_list[0], message_list[1]) else: self.__internal( f"Message List is not in the correct format: {message_list}" )CODE/Logicytics.py (1)
78-93: 🛠️ Refactor suggestion
Let's make the flag handling bulletproof! 🛡️
The flag handling is simple (which is good!), but we should add some error checking:
def get_flags(): """Retrieves action and sub-action flags.""" global ACTION, SUB_ACTION - ACTION, SUB_ACTION = Flag.data() - log.debug(f"Action: {ACTION}") - log.debug(f"Sub-Action: {SUB_ACTION}") + try: + ACTION, SUB_ACTION = Flag.data() + if ACTION is None: + log.warning("No action flag specified, using default") + ACTION = "minimal" # Set a default action + log.debug(f"Action: {ACTION}") + log.debug(f"Sub-Action: {SUB_ACTION}") + except Exception as e: + log.error(f"Failed to get flags: {e}") + log.info("Using default flags") + ACTION, SUB_ACTION = "minimal", None📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.Retrieves action and sub-action flags from the Flag module and sets global variables. This function extracts the current action and sub-action from the Flag module, setting global ACTION and SUB_ACTION variables. It logs the retrieved values for debugging and tracing purposes. No parameters. Side effects: - Sets global variables ACTION and SUB_ACTION - Logs debug information about current action and sub-action """ global ACTION, SUB_ACTION # Get flags_list try: ACTION, SUB_ACTION = Flag.data() if ACTION is None: log.warning("No action flag specified, using default") ACTION = "minimal" # Set a default action log.debug(f"Action: {ACTION}") log.debug(f"Sub-Action: {SUB_ACTION}") except Exception as e: log.error(f"Failed to get flags: {e}") log.info("Using default flags") ACTION, SUB_ACTION = "minimal", NoneCODE/logicytics/Flag.py (1)
30-30: 🛠️ Refactor suggestion
Watch out! Hardcoded file path alert! 🚫
The history file path is hardcoded to 'logicytics/User_History.json.gz'. This could break if someone installs the package in a different location.
Consider using a configuration setting or a path relative to the package's installation directory:
-HISTORY_FILE = 'logicytics/User_History.json.gz' # User history file +HISTORY_FILE = os.path.join(os.path.dirname(__file__), 'User_History.json.gz')Committable suggestion skipped: line range outside the PR's diff.
Also improved some things, Improved Logicytics.py threading Upgraded Deprecation warning with stack tracing, and added the option to remove it. Signed-off-by: Shahm Najeeb <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 13
🔭 Outside diff range comments (2)
CODE/sensitive_data_miner.py (2)
Line range hint
121-135: Hold up! We're making some risky moves here! 🛑
- Hard-coding "C:" is not cool - what if someone's sensitive stuff is on another drive?
- Putting all sensitive files in one folder called "Password_Files" is like painting a target on it
- We're not cleaning up after ourselves - these copied files just stay there!
Here's what we should do:
- Make the search path configurable
- Use a less obvious directory name
- Add an option to securely delete files after analysis
- Consider encrypting the copied files
Want me to help implement any of these security improvements?
Line range hint
163-173: These keywords are like a hacker's shopping list! 🎯Adding more keywords like "token", "auth", "credentials" makes this tool super powerful - maybe too powerful! We should add some safety features:
- Add rate limiting to avoid system overload
- Keep track of which files we've copied (maybe in a secure log)
- Add a way to exclude certain directories (like Program Files)
- Consider adding a "dry run" mode that just lists files without copying
Here's a starter for the exclusion list:
EXCLUDED_DIRS = { "Program Files", "Program Files (x86)", "Windows", "System32" }
🧹 Nitpick comments (29)
CODE/bluetooth_details.py (3)
27-28: Hey! Let's add some error handling here! 🛡️Right now, if
_write_device_info_to_filefails, we won't know about it in the main function. We should probably handle that and let users know if something went wrong.Here's a cooler way to write it:
devices = _query_bluetooth_devices() if devices: - _write_device_info_to_file(devices, "Bluetooth Info.txt") + try: + _write_device_info_to_file(devices, "Bluetooth Info.txt") + log.info("Successfully wrote Bluetooth device info to file") + except Exception as e: + log.error(f"Failed to write Bluetooth device info: {e}")
Line range hint
56-59: Let's make this PowerShell command easier to read! 📝The command is pretty long and might be hard to update later. We could make it cleaner by moving it to a constant at the top of the file.
Here's how:
+BLUETOOTH_QUERY_CMD = ( + "Get-PnpDevice | " + "Where-Object { $_.FriendlyName -like '*Bluetooth*' } | " + "Select-Object FriendlyName, DeviceID, Description, " + "Manufacturer, Status, PnpDeviceID | " + "ConvertTo-Json -Depth 3" +) def _query_bluetooth_devices() -> bool | list[dict[str, str]]: try: - command = ( - "Get-PnpDevice | Where-Object { $_.FriendlyName -like '*Bluetooth*' } | " - "Select-Object FriendlyName, DeviceID, Description, Manufacturer, Status, PnpDeviceID | " - "ConvertTo-Json -Depth 3" - ) + command = BLUETOOTH_QUERY_CMD
75-82: Quick optimization: Let's move this message outside the loop! 🚀The
FALLBACK_MSGis being defined inside the loop, which means it's created again for each device. Not a huge deal, but we can make it slightly more efficient!Try this:
+ FALLBACK_MSG = 'Unknown (Fallback due to failed Get request)' device_info_list = [] for device in devices: - FALLBACK_MSG = 'Unknown (Fallback due to failed Get request)' device_info = { 'Name': device.get('FriendlyName', FALLBACK_MSG),CODE/dump_memory.py (4)
62-100: Nice system info gathering! Just a couple of tweaks to make it even better! 🚀
- The boot time might show up wrong in different timezones. Let's add UTC:
- 'Boot Time': datetime.fromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S'), + 'Boot Time (UTC)': datetime.utcfromtimestamp(psutil.boot_time()).strftime('%Y-%m-%d %H:%M:%S UTC'),
- Let's make those file paths reusable constants at the top of the file:
SYSTEM_INFO_FILE = "SystemRam_Info.txt" RAM_SNAPSHOT_FILE = "Ram_Snapshot.txt" RAM_DUMP_FILE = "Ram_Dump.txt"
137-142: Let's make that disk space check clearer! 💾The 1.5 safety margin is a bit mysterious. Let's make it a constant:
+# Safety margin multiplier for disk space check +DISK_SPACE_SAFETY_MARGIN = 1.5 - required_space = LIMIT_FILE_SIZE * 1024 * 1024 * 1.5 # 2x safety margin + required_space = LIMIT_FILE_SIZE * 1024 * 1024 * DISK_SPACE_SAFETY_MARGIN
103-193: This function's getting a bit chunky! Let's break it down! 🔨The memory_dump function is doing a lot! We could split it into smaller functions like:
- check_disk_space()
- process_memory_region()
- write_region_metadata()
This would make it easier to read and maintain!
Want me to show you how to break this down into smaller functions?
1-220: Let's add some type hints to make the code even more awesome! 🎯Python type hints would make this code super clear! Here's an example:
def capture_ram_snapshot() -> None: """Captures and logs the current system memory statistics.""" def gather_system_info() -> None: """Gather and log detailed system information.""" def memory_dump() -> None: """Perform a memory dump of the current process."""Want me to show you how to add type hints to the rest of the code?
CODE/event_log.py (3)
60-63: Make your error messages more helpful! 🎯The error messages could be more specific about what went wrong and how to fix it. Like, what kind of WMI errors might happen? What should the user do?
Try something like this:
- log.error(f"Error opening or reading the event log: {err}") + log.error(f"Failed to access Windows event logs ({log_type}). Make sure you have admin rights and WMI service is running. Error: {err}") - log.error(f"Fatal issue: {err}") + log.error(f"Unexpected error while processing {log_type} events: {err}. Please check file permissions and disk space.")
75-88: Let's make this threading stuff better! 🚀A few things could make this code even cooler:
- The 10-minute timeout is hardcoded
- Thread names would help with debugging
- Use
os.path.join()for file paths to avoid problems on different systemsHere's how to level up your code:
+ THREAD_TIMEOUT = 600 # 10 minutes in seconds threads = [] threads_items = [('Security', 'event_logs/Security_events.txt'), ('Application', 'event_logs/App_events.txt'), ('System', 'event_logs/System_events.txt')] for log_type_main, output_file_main in threads_items: + output_file_main = os.path.join('event_logs', f"{log_type_main}_events.txt") thread = threading.Thread(target=parse_event_logs, args=(log_type_main, output_file_main)) + thread.name = f"EventLog_{log_type_main}" thread.daemon = True threads.append(thread) thread.start() for thread in threads: - thread.join(timeout=600) + thread.join(timeout=THREAD_TIMEOUT) if thread.is_alive(): - log.error(f"Thread for {thread.name} timed out (10 minutes)!") + log.error(f"Thread {thread.name} timed out after {THREAD_TIMEOUT/60:.1f} minutes!")
68-70: Quick tip about directory stuff! 💡Instead of removing and recreating the directory, you could just empty it. Also,
os.makedirs()is safer thanos.mkdir()because it creates parent directories if needed!Here's a smoother way:
- if os.path.exists('event_logs'): - shutil.rmtree('event_logs') - os.mkdir('event_logs') + os.makedirs('event_logs', exist_ok=True) + for file in os.listdir('event_logs'): + os.remove(os.path.join('event_logs', file))CODE/log_miner.py (1)
12-28: Awesome docstring update! 👍 But let's make it shorterHey! The new docstring is super detailed, which is great, but we can make it more straight-to-the-point. Like, do we really need to mention the specific PowerShell commands in the docstring? That's kinda in the code already!
Here's a shorter version that still gets the point across:
- Backs up Windows system logs to a CSV file using PowerShell. - - This function retrieves system logs and exports them to a CSV file named 'Logs_backup.csv'. - It uses PowerShell's Get-EventLog cmdlet to collect system logs and Export-Csv to save them. - - The function handles potential errors during log backup and logs the operation's outcome. - If the backup fails, an error message is logged without raising an exception. + Backs up Windows system logs to 'Logs_backup.csv'. + + Exports system event logs to a CSV file using PowerShell commands. + Handles errors by logging them without stopping execution.CODE/dir_list.py (2)
30-31: Good thinking on escaping those quotes! 🔒You're handling those pesky quotes in directory names, which is super important! But maybe we could make this even better by moving it to a helper function?
Here's how we could do it:
- safe_directory = directory.replace('"', '`"') # Escape quotes - command = f'powershell -NoProfile -Command "Get-ChildItem \\""{safe_directory}\\"" -Recurse"' + def escape_powershell_path(path: str) -> str: + """Makes a path safe for PowerShell commands.""" + return path.replace('"', '`"') + + command = f'powershell -NoProfile -Command "Get-ChildItem \\""{escape_powershell_path(directory)}\\"" -Recurse"'
59-68: Nice job with thread handling! 🧵 But let's make it even betterThe thread pool setup is good, but that max workers calculation could be tweaked a bit. Right now you're using
min(32, os.cpu_count() * 4), but we might want to make those numbers configurable.Here's a suggestion:
+ # Constants for thread pool configuration + MAX_WORKERS_LIMIT = 32 + CPU_MULTIPLIER = 4 + with ThreadPoolExecutor( - max_workers=min(32, os.cpu_count() * 4) + max_workers=min(MAX_WORKERS_LIMIT, (os.cpu_count() or 1) * CPU_MULTIPLIER) ) as executor:Also, great job catching those thread pool errors! That'll save someone a headache later! 🎯
CODE/logicytics/__init__.py (2)
20-20: Let's simplify this boolean expression! 🔄The
True if DEBUG == "DEBUG" else Falseis doing the long way around! We can make this way simpler.-def deprecated(removal_version: str, reason: str, show_trace: bool = True if DEBUG == "DEBUG" else False) -> callable: +def deprecated(removal_version: str, reason: str, show_trace: bool = DEBUG == "DEBUG") -> callable:🧰 Tools
🪛 Ruff (0.8.2)
20-20: Remove unnecessary
True if ... else FalseRemove unnecessary
True if ... else False(SIM210)
72-78: Cool color coding in the warning message! 🎨The colored warning message is a nice touch! But we might want to make those color codes constants at the top of the file to make them easier to change later.
+# ANSI color codes +RED = "\033[91m" +RESET = "\033[0m" + - message = f"\033[91mDeprecationWarning: A call to the deprecated function {func.__name__}() has been called, {reason}. Function will be removed at version {removal_version}\n" + message = f"{RED}DeprecationWarning: A call to the deprecated function {func.__name__}() has been called, {reason}. Function will be removed at version {removal_version}\n" if show_trace: stack = ''.join(traceback.format_stack()[:-1]) - message += f"Called from:\n{stack}\033[0m" + message += f"Called from:\n{stack}{RESET}" else: - message += "\033[0m" + message += RESETCODE/vulnscan.py (1)
Line range hint
52-91: Good error handling, but let's make it faster! 🚀The code's looking solid with all that error handling and thread safety! But here's a pro tip: we could make it even better by caching the model and vectorizer in memory instead of loading them for each scan.
Here's how we could do it:
+from functools import lru_cache +@lru_cache(maxsize=1) +def get_model(model_path: str): + with model_lock: + return load_model(model_path) +@lru_cache(maxsize=1) +def get_vectorizer(vectorizer_path: str): + with vectorizer_lock: + return joblib.load(vectorizer_path) @log.function def scan_path(model_path: str, scan_paths: str, vectorizer_path: str): global model_to_use, vectorizer_to_use try: - with model_lock: - if model_to_use is None: - log.info(f"Loading model from {model_path}") - model_to_use = load_model(model_path) - with vectorizer_lock: - if vectorizer_to_use is None: - log.info(f"Loading vectorizer from {vectorizer_path}") - vectorizer_to_use = joblib.load(vectorizer_path) + model_to_use = get_model(model_path) + vectorizer_to_use = get_vectorizer(vectorizer_path) vulnscan(model_to_use, scan_paths, vectorizer_to_use)CODE/_debug.py (3)
181-201: Great version checking! Let's make it even better! 🔄The version checking is super clear, but having those version numbers hard-coded might be tricky to update later.
Let's move them to the config file:
- MIN_VERSION = (3, 11) - MAX_VERSION = (3, 13) + config = configparser.ConfigParser() + config.read("config.ini") + MIN_VERSION = tuple(map(int, config.get("Python", "min_version").split("."))) + MAX_VERSION = tuple(map(int, config.get("Python", "max_version").split(".")))Then in config.ini:
[Python] min_version = 3.11 max_version = 3.13
235-256: Let's make the config download more reliable! 🌐The function handles errors well, but sometimes the internet can be flaky. Adding retry logic would make it more reliable!
Here's how we could do it:
+from tenacity import retry, stop_after_attempt, wait_exponential +@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) def get_online_config() -> dict | None: try: url = "https://raw.githubusercontent.com/DefinetlyNotAI/Logicytics/main/CODE/config.ini" config = configparser.ConfigParser() config.read_string(requests.get(url, timeout=15).text) return config except requests.exceptions.RequestException as e: log_debug.error(f"Connection error: {e}") return None
235-256: Make those system checks zoom! 🏃♂️The debug function is super organized, but running all those checks one after another can be slow. Let's speed it up!
Here's how we could run some checks in parallel:
+from concurrent.futures import ThreadPoolExecutor + @log_debug.function def debug(): """ ... """ + def run_system_checks(): + return { + "admin": Check.admin(), + "uac": Check.uac(), + "execution_policy": Check.execution_policy() + } + + def run_path_checks(): + return { + "psutil_path": psutil.__file__, + "sys_executable": sys.executable, + "sys_prefix": sys.prefix + } + # Clear Debug Log log_path = "../ACCESS/LOGS/DEBUG/DEBUG.log" if os.path.exists(log_path): os.remove(log_path) + # Run checks in parallel + with ThreadPoolExecutor(max_workers=2) as executor: + system_future = executor.submit(run_system_checks) + path_future = executor.submit(run_path_checks) + + system_results = system_future.result() + path_results = path_future.result() + + # Log results + log_debug.info(f"Admin privileges {'found' if system_results['admin'] else 'not found'}") + log_debug.info(f"UAC {'enabled' if system_results['uac'] else 'disabled'}") + log_debug.info(f"Execution path: {path_results['psutil_path']}")CODE/logicytics/Logger.py (2)
304-335: Hey, let's make this even safer! 🔒The new
parse_executionmethod is cool, but we should probably add some checks to make sure the input is valid before trying to use it.Here's how we could make it better:
def parse_execution(self, message_log: list[list[str, str]]): + if not message_log: + self.__internal("Empty message log received") + return + + if not all(isinstance(msg, list) and len(msg) == 2 for msg in message_log): + self.__internal("Invalid message format in log") + return + if message_log: for message_list in message_log:
338-389: Watch out for function inception! 🌀The function decorator is awesome for tracking how long things take, but it might get weird with recursive functions (functions that call themselves). We should probably add a way to handle that!
Here's a way to make it better:
def function(self, func: callable): + # Track recursive calls + func._recursion_depth = 0 def wrapper(*args, **kwargs): + func._recursion_depth += 1 + is_outer_call = func._recursion_depth == 1 start_time = time.perf_counter() func_args = ", ".join([str(arg) for arg in args] + [f"{k}={v}" for k, v in kwargs.items()]) - self.debug(f"Running the function {func.__name__}({func_args}).") + if is_outer_call: + self.debug(f"Running the function {func.__name__}({func_args}).") result = func(*args, **kwargs) end_time = time.perf_counter() elapsed_time = end_time - start_time - self.debug(f"{func.__name__}({func_args}) executed in {elapsed_time} -> returned {type(result).__name__}") + if is_outer_call: + self.debug(f"{func.__name__}({func_args}) executed in {elapsed_time} -> returned {type(result).__name__}") + func._recursion_depth -= 1 return resultCODE/Logicytics.py (1)
317-327: Don't let your computer break a sweat! 💪The new threading code is cool, but we should probably limit how many things it tries to do at once. Too many threads can make your computer struggle!
Here's how to add a limit:
- with ThreadPoolExecutor() as executor: + # Use max_workers to limit concurrent tasks + max_workers = min(4, len(execution_list)) # Don't use more than 4 threads + with ThreadPoolExecutor(max_workers=max_workers) as executor:CODE/packet_sniffer.py (4)
205-224: Add a "how-to" example! 📚The documentation is great, but it would be even better with a real example of how the callback works!
Add this to your docstring:
Raises: No explicit exceptions raised, but may propagate exceptions from log_packet function. + + Example: + def packet_callback(packet): + # Process a TCP packet + if packet.haslayer(TCP): + log_packet(packet) + return packet_counter >= 10 # Stop after 10 packets
356-361: Let's catch more spelling whoopsies! 🔍The interface name correction is helpful, but there are more ways people might type WiFi/Wi-Fi wrong.
Here's how to catch more variations:
corrections = { "WiFi": "Wi-Fi", - "Wi-Fi": "WiFi" + "Wi-Fi": "WiFi", + "wifi": "Wi-Fi", + "WIFI": "Wi-Fi", + "Wifi": "Wi-Fi", + "wi-fi": "Wi-Fi" }
369-373: Make those error messages even friendlier! 😊Love the emojis in the error messages! Let's add some more helpful info for other common problems.
Here's how to make it even better:
log.error( "Oops! Can't work with these values:\n" f"- Packet count: {packet_count} {'❌ (must be > 0)' if packet_count <= 0 else '✅'}\n" - f"- Timeout: {timeout} {'❌ (must be > 0)' if timeout <= 0 else '✅'}" + f"- Timeout: {timeout} {'❌ (must be > 0)' if timeout <= 0 else '✅'}\n" + f"- Interface: {interface} {'❌ (not found)' if not interface else '✅'}\n" + "\nTip: Try running as administrator if you're having permission issues! 🔑" )
396-398: Don't forget to clean up everything! 🧹Good job adding cleanup code, but let's make sure we clean up all our toys when we're done playing!
Here's how to clean up everything:
finally: if G: plt.close() + # Clean up any temporary files + if os.path.exists('captured_packets.csv'): + try: + os.remove('captured_packets.csv') + log.debug("Cleaned up temporary CSV file") + except Exception as e: + log.debug(f"Failed to clean up CSV: {e}")CODE/logicytics/Flag.py (3)
16-35: Hey! Let's make this config setup more organized! 🔧Instead of using global variables, we could wrap this configuration in a class. This would make it way easier to test and manage the settings. Here's a cool way to do it:
-# Set up constants and configurations -config = configparser.ConfigParser() -try: - config.read('config.ini') -except FileNotFoundError: - try: - config.read('../config.ini') - except FileNotFoundError: - exit("No configuration file found.") -# Save user preferences? -SAVE_PREFERENCES = config.getboolean("Settings", "save_preferences") -# Debug mode for Sentence Transformer -DEBUG_MODE = config.getboolean("Flag Settings", "model_debug") -# File for storing user history data -HISTORY_FILE = 'logicytics/User_History.json.gz' -# Minimum accuracy threshold for flag suggestions -MIN_ACCURACY_THRESHOLD = float( - config.get("Flag Settings", "accuracy_min")) -if not 0 <= MIN_ACCURACY_THRESHOLD <= 100: - raise ValueError("accuracy_min must be between 0 and 100") +class LogicyticsConfig: + def __init__(self): + self.config = configparser.ConfigParser() + self._load_config() + self.save_preferences = self.config.getboolean("Settings", "save_preferences") + self.debug_mode = self.config.getboolean("Flag Settings", "model_debug") + self.history_file = 'logicytics/User_History.json.gz' + self.min_accuracy_threshold = self._validate_accuracy( + float(self.config.get("Flag Settings", "accuracy_min"))) + + def _load_config(self): + if not self._try_read_config('config.ini'): + if not self._try_read_config('../config.ini'): + raise FileNotFoundError("No configuration file found.") + + def _try_read_config(self, path: str) -> bool: + try: + return bool(self.config.read(path)) + except FileNotFoundError: + return False + + @staticmethod + def _validate_accuracy(threshold: float) -> float: + if not 0 <= threshold <= 100: + raise ValueError("accuracy_min must be between 0 and 100") + return threshold
30-30: Don't hardcode file paths! 🎯The history file path should be configurable, not hardcoded. Move it to the config file!
-HISTORY_FILE = 'logicytics/User_History.json.gz' # User history fileAdd this to your config.ini:
[Settings] history_file = logicytics/User_History.json.gz
159-159: That TODO needs some love! ❤️I see a TODO comment saying this feature is in beta. Want me to help make it production-ready?
I can help:
- Add error handling for matplotlib
- Add progress indicators for long operations
- Add unit tests for the graph generation
Let me know if you want me to create a GitHub issue to track these improvements!
🛑 Comments failed to post (13)
CODE/dump_memory.py (1)
17-20: 🛠️ Refactor suggestion
Yo! Let's move that LIMIT_FILE_SIZE to config.ini! 🔧
The TODO is right - this should totally be in the config file. It'll make it way easier for users to change it without diving into the code.
Want me to show you how to move this to the config file? Just let me know!
CODE/sensitive_data_miner.py (4)
15-21:
⚠️ Potential issueWhoa! 🚨 We need to be super careful with these file types!
Hey there! Adding all these file extensions (.sql, .mdb, .pst, etc.) is like giving someone the keys to everyone's private stuff! These files often contain super sensitive data like:
- Database files with user info
- Email archives that might have private convos
- Backup files that could have passwords
We should:
- Add a big warning in the docs about the responsibility of using this tool
- Consider adding file size limits for these types
- Maybe make some extensions optional or require extra permissions
Want me to help create a configuration system that lets users pick which extensions they want to search?
178-181:
⚠️ Potential issueWe need a safety check before starting!
⚠️ Just throwing a warning about getting coffee isn't enough for a tool this powerful!
Let's add a confirmation prompt:
if __name__ == "__main__": log.warning( "Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)") + confirm = input("This tool will search for and copy sensitive files. Are you sure you want to continue? (yes/no): ") + if confirm.lower() != "yes": + log.info("Operation cancelled by user") + exit(0) Mine.passwords()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if __name__ == "__main__": log.warning( "Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)") confirm = input("This tool will search for and copy sensitive files. Are you sure you want to continue? (yes/no): ") if confirm.lower() != "yes": log.info("Operation cancelled by user") exit(0) Mine.passwords()
49-66:
⚠️ Potential issueWatch out for those debug logs! 🕵️
The debug logging at line 66 is printing out full file paths - that's like posting your home address online! If these logs end up in the wrong place, they could give away where all the sensitive stuff is stored.
Let's make this safer:
- log.debug(f"Skipped {file_path}, Unsupported due to {file_path.suffix} extension") + log.debug(f"Skipped file with extension: {file_path.suffix}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.path_list = [] try: path_list = os.listdir(root) except WindowsError as e: if DEBUG: # Log the error if in debug mode, as it is a common occurrence. log.warning(f"Permission Denied: {e}") for filename in path_list: file_path = root / filename if ( keyword.lower() in filename.lower() and file_path.is_file() and file_path.suffix in allowed_extensions ): matching_files.append(file_path) else: log.debug(f"Skipped file with extension: {file_path.suffix}")
89-98: 🛠️ Refactor suggestion
Good catch on the file size limit! 👍
The 10MB limit is smart - keeps things from getting out of hand. But heads up:
- The success log at line 94 is showing the full file path again
- The error messages might leak sensitive info too
Try this safer version:
- log.debug(f"Copied {src_file_path} to {dst_file_path}") + log.debug(f"Copied file: {src_file_path.name}") - log.warning(f"File already exists in destination: {e}") + log.warning(f"File already exists: {src_file_path.name}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Check file size and permissions if src_file_path.stat().st_size > 10_000_000: # 10MB limit log.warning("File exceeds size limit") return shutil.copy(src_file_path, dst_file_path) log.debug(f"Copied file: {src_file_path.name}") except FileExistsError as e: log.warning(f"File already exists: {src_file_path.name}") except Exception as e: log.error(f"Failed to copy file: {e}")CODE/event_log.py (1)
39-41:
⚠️ Potential issueWatch out! This could be dangerous! 🚨
The WMI query is built using string formatting with user input (
log_type). If someone gets sneaky with the input, they could inject malicious stuff!Here's a safer way to do it:
- query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'" + valid_log_types = {'Security', 'Application', 'System'} + if log_type not in valid_log_types: + raise ValueError(f"Invalid log type. Must be one of: {valid_log_types}") + query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Query based on log_type ('Security', 'Application', or 'System') valid_log_types = {'Security', 'Application', 'System'} if log_type not in valid_log_types: raise ValueError(f"Invalid log type. Must be one of: {valid_log_types}") query = f"SELECT * FROM Win32_NTLogEvent WHERE Logfile = '{log_type}'" log.debug(f"Executing WMI query: {query}")CODE/logicytics/__init__.py (1)
9-9:
⚠️ Potential issueHeads up! You've got an unused import hanging around 🎯
The static analysis tool caught that we're importing
Logbut never using it. Let's clean that up!-from logicytics.Logger import Log🧰 Tools
🪛 Ruff (0.8.2)
9-9:
logicytics.Logger.Logimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
CODE/vulnscan.py (2)
203-234: 🛠️ Refactor suggestion
Smart threading setup, but watch out for memory! 💾
Love how you:
- Cap the max workers at 32 (super smart!)
- Track progress (nice touch with the percentage!)
- Handle errors in each thread
But heads up! Processing all paths at once could eat up a ton of memory. Maybe we should process them in chunks?
Here's a way to do it:
- with ThreadPoolExecutor(max_workers=max_workers) as executor: - futures = [ - executor.submit( - scan_path, - "VulnScan/Model SenseMini .3n3.pth", - path, - "VulnScan/Vectorizer .3n3.pkl" - ) - for path in paths - ] + chunk_size = 1000 # Process 1000 paths at a time + for i in range(0, len(paths), chunk_size): + chunk = paths[i:i + chunk_size] + with ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = [ + executor.submit( + scan_path, + "VulnScan/Model SenseMini .3n3.pth", + path, + "VulnScan/Vectorizer .3n3.pkl" + ) + for path in chunk + ]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.# Use max_workers based on CPU count but cap it at a reasonable number max_workers = min(32, os.cpu_count() * 2) with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = [executor.submit(os.path.join, root, file_main) for base_path in base_paths for root, _, files_main in os.walk(base_path) for file_main in files_main] for future in futures: paths.append(future.result()) # Start scanning log.warning("Starting scan - This may take hours and consume memory!!") chunk_size = 1000 # Process 1000 paths at a time for i in range(0, len(paths), chunk_size): chunk = paths[i:i + chunk_size] with ThreadPoolExecutor(max_workers=max_workers) as executor: futures = [ executor.submit( scan_path, "VulnScan/Model SenseMini .3n3.pth", path, "VulnScan/Vectorizer .3n3.pkl" ) for path in chunk ] for future in futures: try: future.result() completed += 1 if completed % 100 == 0: progress = (completed / total_paths) * 100 log.info(f"Scan progress: {progress:.1f}% ({completed}/{total_paths})") except Exception as e:
21-22: 💡 Codebase verification
Hey, I found something interesting about those warnings! 🔍
Looking at the code, I can see there are actually two different ways warnings are handled:
- There's a blanket
warnings.filterwarnings("ignore")that blocks ALL warnings- But then there's also a specific warning filter for FutureWarning when loading the torch model:
warnings.filterwarnings("ignore", category=FutureWarning)The second approach (filtering specific warnings) is way better! The code uses warnings in a bunch of important places to tell us about stuff like:
- Permission issues
- File size limits
- Missing files
- Version mismatches
- And other important heads-ups!
By blocking ALL warnings, we might miss these important messages. Let's be more specific about which warnings we want to ignore - just like how the code does it for the FutureWarning!
Here's what you should change:
- Remove the blanket
warnings.filterwarnings("ignore")- If there are specific annoying warnings you want to ignore, filter them by category like:
warnings.filterwarnings("ignore", category=SpecificWarningType)🔗 Analysis chain
Heads up about ignoring all warnings!
⚠️ Using
warnings.filterwarnings("ignore")is like putting on a blindfold - you might miss some important stuff! Maybe we should only ignore specific warnings we know are safe to skip?🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check what warnings might be getting suppressed rg -A 2 "Warning|warning" --type pyLength of output: 13260
CODE/Logicytics.py (1)
78-93: 🛠️ Refactor suggestion
Let's add a safety net! 🎯
The flag retrieval is simpler now (which is great!), but what if something goes wrong when getting the flags? We should probably catch any errors that might happen.
Here's how we can make it safer:
def get_flags(): global ACTION, SUB_ACTION - # Get flags_list - ACTION, SUB_ACTION = Flag.data() - log.debug(f"Action: {ACTION}") - log.debug(f"Sub-Action: {SUB_ACTION}") + try: + # Get flags_list + ACTION, SUB_ACTION = Flag.data() + log.debug(f"Action: {ACTION}") + log.debug(f"Sub-Action: {SUB_ACTION}") + except Exception as e: + log.error(f"Failed to get flags: {e}") + ACTION, SUB_ACTION = None, None📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.Retrieves action and sub-action flags from the Flag module and sets global variables. This function extracts the current action and sub-action from the Flag module, setting global ACTION and SUB_ACTION variables. It logs the retrieved values for debugging and tracing purposes. No parameters. Side effects: - Sets global variables ACTION and SUB_ACTION - Logs debug information about current action and sub-action """ global ACTION, SUB_ACTION try: # Get flags_list ACTION, SUB_ACTION = Flag.data() log.debug(f"Action: {ACTION}") log.debug(f"Sub-Action: {SUB_ACTION}") except Exception as e: log.error(f"Failed to get flags: {e}") ACTION, SUB_ACTION = None, NoneCODE/logicytics/Flag.py (3)
658-658:
⚠️ Potential issueWhat if the user just hits Enter? 🤔
The input prompt doesn't handle empty input. Let's make it more user-friendly!
- user_input_desc = input("We can't find a match, Please provide a description: ").lower() + user_input_desc = input("We can't find a match, Please provide a description: ").strip().lower() + if not user_input_desc: + print("No description provided. Please try again with --help to see available flags.") + exit(1)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.user_input_desc = input("We can't find a match, Please provide a description: ").strip().lower() if not user_input_desc: print("No description provided. Please try again with --help to see available flags.") exit(1)
739-742:
⚠️ Potential issueOops! This return statement is in the wrong place! 🙈
The early return when
SAVE_PREFERENCESis False will prevent the function from returning the used flags.- # Update history with the matched flag(s) - if not SAVE_PREFERENCES: - return - def update_data_history(matched_flag: str): """ Update the usage count for a specific flag in the user's interaction history. """ + if not SAVE_PREFERENCES: + returnCommittable suggestion skipped: line range outside the PR's diff.
71-77: 🛠️ Refactor suggestion
Let's not load the model every time! 🚀
Loading the model in
__get_simfor each call is super slow! We should load it once when the class is initialized.+ _model = None + + @classmethod + def _load_model(cls): + if cls._model is None: + try: + cls._model = SentenceTransformer(config.get("Flag Settings", "model_to_use")) + except Exception as e: + print(f"Error: {e}") + print("Please check the model name in the config file.") + print(f"Model name {config.get('Flag Settings', 'model_to_use')} may not be valid.") + exit(1) + return cls._model @staticmethod def __get_sim(user_input: str, all_descriptions: list[str]) -> list[float]: - try: - MODEL = SentenceTransformer(config.get("Flag Settings", "model_to_use")) - except Exception as e: - print(f"Error: {e}") - print("Please check the model name in the config file.") - print(f"Model name {config.get('Flag Settings', 'model_to_use')} may not be valid.") - exit(1) + MODEL = Match._load_model()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements._model = None @classmethod def _load_model(cls): if cls._model is None: try: cls._model = SentenceTransformer(config.get("Flag Settings", "model_to_use")) except Exception as e: print(f"Error: {e}") print("Please check the model name in the config file.") print(f"Model name {config.get('Flag Settings', 'model_to_use')} may not be valid.") exit(1) return cls._model @staticmethod def __get_sim(user_input: str, all_descriptions: list[str]) -> list[float]: MODEL = Match._load_model()
Also improved some things, Improved Logicytics.py threading Upgraded Deprecation warning with stack tracing, and added the option to remove it. Signed-off-by: Shahm Najeeb <[email protected]>
…ixes-and-v3.3.0 # Conflicts: # CODE/vulnscan.py
|
Code Climate has analyzed commit 77d7519 and detected 4 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
|
@CodeRabbit Provide a very thorough and in detail release note for version 3.3.0 |
|
Tip For best results, initiate chat on the files or code changes. @DefinetlyNotAI Here's a comprehensive release note for Logicytics v3.3.0, covering everything from refactor work to newly introduced functionalities: 1. Major Refactor & Cleanup
2. Logging Enhancements
3. Better Device & Event Coverage
4. Configuration & User Interface
5. Streamlined Execution
6. Deprecated Feature Removal
7. Upgrade Path
8. Known Limitations & Considerations
That’s the gist of everything new and improved in Logicytics v3.3.0. This version aims to boost stability, clarity, and user-friendliness, while also removing legacy clutter. If you have any questions or notice weird behavior, let the team know so we can keep refining the coolest features in future updates. Enjoy exploring v3.3.0! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
CODE/vulnscan.py (1)
Line range hint
27-52: Watch out! 🚨 Loading models without checking them first is dangerous!Loading models without validating them first is like downloading and running random apps from the internet - super risky! Someone could sneak malicious code into a model file.
Here's how to make it safer:
def load_model(model_path_to_load: str) -> safe_open | torch.nn.Module: + # Validate file size and permissions + if os.path.getsize(model_path_to_load) > 1024 * 1024 * 100: # 100MB limit + raise ValueError("Model file too large") + + # Check if file is in a safe directory + safe_dirs = ['models/', 'VulnScan/'] + if not any(model_path_to_load.startswith(d) for d in safe_dirs): + raise ValueError("Model must be in an approved directory") + if model_path_to_load.endswith('.pkl'): + # Pickle files can execute code - use safe_load + return joblib.load(model_path_to_load, mmap_mode='r') - return joblib.load(model_path_to_load)
🛑 Comments failed to post (5)
CODE/vulnscan.py (5)
86-93:
⚠️ Potential issueHey! 🤔 Be careful with what you're logging - it might contain secrets!
When you're logging errors, you gotta be super careful not to accidentally expose sensitive info. Right now, the error messages might include parts of sensitive files!
Let's make the error logging safer:
- log.error(f"File not found while scanning {scan_paths}: {err}") + log.error(f"File not found while scanning [PATH REDACTED]: {err.__class__.__name__}") - log.error(f"Permission denied while scanning {scan_paths}: {err}") + log.error(f"Permission denied while scanning [PATH REDACTED]: {err.__class__.__name__}") - log.error(f"Model loading failed for {scan_paths}: {err}") + log.error(f"Model loading failed: {err.__class__.__name__}") - log.error(f"Unexpected error scanning {scan_paths}: {err}") + log.error(f"Unexpected error: {err.__class__.__name__}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.except FileNotFoundError as err: log.error(f"File not found while scanning [PATH REDACTED]: {err.__class__.__name__}") except PermissionError as err: log.error(f"Permission denied while scanning [PATH REDACTED]: {err.__class__.__name__}") except (torch.serialization.pickle.UnpicklingError, RuntimeError) as err: log.error(f"Model loading failed: {err.__class__.__name__}") except Exception as err: log.error(f"Unexpected error: {err.__class__.__name__}")
223-225:
⚠️ Potential issueYo! 🎯 These model paths could be dangerous!
Using hardcoded relative paths for the model and vectorizer is risky - someone could swap them out with malicious files!
Let's make it safer:
- "VulnScan/Model SenseMini .3n3.pth", + os.path.join(os.path.dirname(__file__), "models", "SenseMini_3n3.pth"), path, - "VulnScan/Vectorizer .3n3.pkl" + os.path.join(os.path.dirname(__file__), "models", "Vectorizer_3n3.pkl")Also, you should validate the model checksums before loading them to make sure they haven't been tampered with!
Committable suggestion skipped: line range outside the PR's diff.
198-203: 🛠️ Refactor suggestion
Bruh! 🤦♂️ These paths only work on Windows!
The hardcoded Windows paths mean this won't work on Mac or Linux. Also, scanning system directories like
C:\Windowsmight not be the best idea!Let's make it work everywhere:
- base_paths = [ - "C:\\Users\\", - "C:\\Windows\\Logs", - "C:\\Program Files", - "C:\\Program Files (x86)" - ] + # Get system-specific paths + base_paths = [] + if os.name == 'nt': # Windows + base_paths = [os.path.expanduser('~')] # Just scan user's home directory + else: # Linux/Mac + base_paths = [os.path.expanduser('~')]Committable suggestion skipped: line range outside the PR's diff.
23-24: 🛠️ Refactor suggestion
⚠️ Potential issueYo! 🚫 Don't ignore ALL warnings - that's super risky!
Hey there! Ignoring all warnings with
warnings.filterwarnings("ignore")is like turning off your phone's notifications completely - you might miss something important! Some warnings could be telling you about security problems or deprecated features that might break in the future.Let's fix this by only ignoring specific warnings we know are safe to ignore:
-# Ignore all warnings -warnings.filterwarnings("ignore") +# Ignore specific known warnings +warnings.filterwarnings("ignore", category=FutureWarning) +warnings.filterwarnings("ignore", category=DeprecationWarning)Also, it'd be super helpful to add version requirements for your imports in
requirements.txtto avoid any surprise breaks!Committable suggestion skipped: line range outside the PR's diff.
205-236:
⚠️ Potential issueHold up! 🛑 This could crash someone's computer!
The scan is using a lot of threads and memory without any limits. It's like opening 100 Chrome tabs at once - your computer's gonna have a bad time!
Let's add some safety limits:
+ # Add resource limits + MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB + MAX_FILES = 10000 + # Use max_workers based on CPU count but cap it at a reasonable number - max_workers = min(32, os.cpu_count() * 2) + max_workers = min(8, os.cpu_count()) # Lower thread count for safety with ThreadPoolExecutor(max_workers=max_workers) as executor: + # Count and filter files before scanning + file_count = 0 futures = [executor.submit(os.path.join, root, file_main) for base_path in base_paths for root, _, files_main in - os.walk(base_path) for file_main in files_main] + os.walk(base_path) for file_main in files_main + if os.path.getsize(os.path.join(root, file_main)) < MAX_FILE_SIZE + and file_count < MAX_FILES]Committable suggestion skipped: line range outside the PR's diff.
Docstrings generation was requested by @DefinetlyNotAI. * #176 (comment) The following files were modified: * `CODE/Logicytics.py` * `CODE/_debug.py` * `CODE/_dev.py` * `CODE/bluetooth_details.py` * `CODE/bluetooth_logger.py` * `CODE/dir_list.py` * `CODE/dump_memory.py` * `CODE/event_log.py` * `CODE/log_miner.py` * `CODE/logicytics/Execute.py` * `CODE/logicytics/FileManagement.py` * `CODE/logicytics/Flag.py` * `CODE/logicytics/Get.py` * `CODE/logicytics/Logger.py` * `CODE/logicytics/__init__.py` * `CODE/media_backup.py` * `CODE/packet_sniffer.py` * `CODE/sensitive_data_miner.py` * `CODE/vulnscan.py` * `CODE/wifi_stealer.py`
> [!WARNING] > The [docstrings feature](https://docs.coderabbit.ai/finishing-touches/docstrings) is in [beta](https://docs.coderabbit.ai/early-access/#beta). Docstrings generation was requested by @DefinetlyNotAI. * #176 (comment) The following files were modified: * `CODE/Logicytics.py` * `CODE/_debug.py` * `CODE/_dev.py` * `CODE/bluetooth_details.py` * `CODE/bluetooth_logger.py` * `CODE/dir_list.py` * `CODE/dump_memory.py` * `CODE/event_log.py` * `CODE/log_miner.py` * `CODE/logicytics/Execute.py` * `CODE/logicytics/FileManagement.py` * `CODE/logicytics/Flag.py` * `CODE/logicytics/Get.py` * `CODE/logicytics/Logger.py` * `CODE/logicytics/__init__.py` * `CODE/media_backup.py` * `CODE/packet_sniffer.py` * `CODE/sensitive_data_miner.py` * `CODE/vulnscan.py` * `CODE/wifi_stealer.py` <details> <summary>These files were kept as they were</summary> * `CODE/sys_internal.py` </details> <details> <summary>These file types are not supported</summary> * `.github/ISSUE_TEMPLATE/bug_report.yml` * `.gitignore` * `CODE/config.ini` * `CREDITS.md` * `PLANS.md` * `README.md` * `SECURITY.md` * `requirements.txt` </details> <details> <summary>ℹ️ Note</summary><blockquote> CodeRabbit cannot perform edits on its own pull requests yet. </blockquote></details>
## Pull Request Template ### Prerequisites <!-- Take a couple of minutes to help our maintainers work faster by checking of the pre-requisites. --> <!-- To tick the checkboxes replace the space with an 'x', so [ ] becomes [x] . --> - [x] I have [searched](https://github.com/DefinetlyNotAI/Logicytics/pulls) for duplicate or closed issues. - [x] I have read the [contributing guidelines](https://github.com/DefinetlyNotAI/Logicytics/blob/main/CONTRIBUTING.md). - [x] I have followed the instructions in the [wiki](https://github.com/DefinetlyNotAI/Logicytics/wiki) about contributions. - [x] I have updated the documentation accordingly, if required. - [x] I have tested my code with the `--dev` flag, if required. ### PR Type <!-- Take a couple of minutes to help our maintainers work faster by telling us what is the PR guided on. --> <!-- To tick the checkboxes replace the space with an 'x', so [ ] becomes [x] . --> - [x] Bug fix <!-- Non-Breaking Bug Fix - Usually relates to fixing an issue --> - [x] Deprecation Change <!-- Removing a deprecation --> - [x] New feature <!-- Non-Breaking Change that adds a new feature --> - [x] Refactoring <!-- Non-Breaking Change that modifies existing code to refactor it to become more organised --> - [x] Documentation update <!-- Non-Breaking Change that modifies existing documentation to refactor it or add extra comments - either wiki, md files or code is included here --> - [x]⚠️ Breaking change⚠️ <!-- Breaking Bug Fix / New Addition that changes how Logicytics works --> ### Description <!-- REQUIRED: Provide a summary of the PR and what you expected to happen. --> <!-- Made by copilot --> This pull request includes significant changes to the `Logicytics` project, focusing on code refactoring, logging improvements, and the removal of deprecated features. The most important changes include the refactoring of flag handling, the addition of detailed logging, and the cleanup of deprecated features. #### Code Refactoring and Improvements: * [`CODE/Logicytics.py`](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L78-R87): Refactored `get_flags` function to simplify flag retrieval and logging. Removed deprecated features `extra` and `unzip_extra` from `handle_special_actions`. Added the `Logicytics` main function to encapsulate the main process logic. [[1]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L78-R87) [[2]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L138-L145) [[3]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L176-L183) [[4]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L370-R359) [[5]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0R373-R376) #### Logging Enhancements: * [`CODE/_debug.py`](diffhunk://#diff-cddd7a4c003554a2fce729e954458aa39d397bf2910c94cdd093f39747848061R181-R188): Added detailed logging to `python_version` and `debug` functions. [[1]](diffhunk://#diff-cddd7a4c003554a2fce729e954458aa39d397bf2910c94cdd093f39747848061R181-R188) [[2]](diffhunk://#diff-cddd7a4c003554a2fce729e954458aa39d397bf2910c94cdd093f39747848061R222) * [`CODE/_dev.py`](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L50-R51): Enhanced `_prompt_user` function with more user-friendly prompts and added logging to `dev_checks` function. [[1]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L50-R51) [[2]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09R65) [[3]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L90-R106) [[4]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L127-R133) * [`CODE/bluetooth_details.py`](diffhunk://#diff-d15430c77b28ebd438edeec503e4666192dd9e256cc386ebcdc6a5012b398d59L1-R12): Improved logging in `get_bluetooth_device_details` and `_query_bluetooth_devices`. [[1]](diffhunk://#diff-d15430c77b28ebd438edeec503e4666192dd9e256cc386ebcdc6a5012b398d59L1-R12) [[2]](diffhunk://#diff-d15430c77b28ebd438edeec503e4666192dd9e256cc386ebcdc6a5012b398d59L30-R39) [[3]](diffhunk://#diff-d15430c77b28ebd438edeec503e4666192dd9e256cc386ebcdc6a5012b398d59L52-R74) [[4]](diffhunk://#diff-d15430c77b28ebd438edeec503e4666192dd9e256cc386ebcdc6a5012b398d59L97) * [`CODE/bluetooth_logger.py`](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aL1-R4): Added detailed logging and documentation to functions `save_to_file`, `run_powershell_command`, `parse_output`, `get_paired_bluetooth_devices`, and `log_bluetooth`. [[1]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aL1-R4) [[2]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aL12-R23) [[3]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aL24-R47) [[4]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aL38-R95) [[5]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aR117-R128) [[6]](diffhunk://#diff-1876b6113c2e2b1d8fa0dfe09ab9a1b20d3fb52852256fd0bbdd1f8bfc9ce27aR143-R149) #### Deprecated Feature Removal: * [`CODE/Logicytics.py`](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L138-L145): Removed deprecated features `extra` and `unzip_extra` from `handle_special_actions`. [[1]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L138-L145) [[2]](diffhunk://#diff-44a988332704ab86171610dcfe391d08df0f70f8177c3463e6e089aec9c5baa0L176-L183) #### Miscellaneous Changes: * [`.github/ISSUE_TEMPLATE/bug_report.yml`](diffhunk://#diff-637f7b97bba458badb691a1557c3d4648686292e948dbe3e8360564378b653efL47-R49): Renamed `flags` to `flags_list` for consistency. * [`CODE/_dev.py`](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L3-R6): Reorganized imports and added `EXCLUDE_FILES` to `dev_checks` function. [[1]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L3-R6) [[2]](diffhunk://#diff-8789fb31b28e15638e2117ffc4916c7d17b62b207559877dce4b69ffcfcfaa09L90-R106) * [`CODE/cmd_commands.py`](diffhunk://#diff-7422c369c3c1828e52aa953e050cf03d003b07f6f0a244908eb117002bbc4be1R30): Added `__main__` check to execute commands. These changes aim to enhance code readability, improve logging for debugging purposes, and remove outdated features to maintain code quality. ### Motivation and Context <!-- REQUIRED: Why is this PR required? What problem does it solve? Why do you want to do it? --> To move in version 3.3.0 and fix many bugs and improve Logicytics ### Credit <!-- If this PR is a contribution, please mention the contributors here using the appropriate syntax. --> <!-- ### File-Created/CONTRIBUTION by MAIN-Username What you did, created, removed, refactored, fixed, or discovered. - [Your GitHub Username](https://github.com/YourGitHubLink) - [Your GitHub Username](https://github.com/YourGitHubLink) etc... --> _N/A_ ### Issues Fixed <!-- REQUIRED: What issues will be fixed? (Format: "#50, #23" etc.) if none exist type _N/A_ --> _N/A_ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes for Logicytics v3.3.0 ### New Features - Enhanced flag suggestion system with historical data tracking. - Improved Bluetooth data collection and logging. - Added support for more file types in sensitive data mining. - Expanded system information and memory snapshot capabilities. - New configuration options for user preferences and accuracy settings. - Added a new XML configuration file for CSV file handling. ### Improvements - Refined error handling across multiple modules. - Enhanced logging and debugging mechanisms. - Updated configuration management. - Improved thread-based execution for certain operations. - Streamlined control flow to prevent unintended execution during imports. ### Bug Fixes - Resolved issues with file parsing and system checks. - Improved compatibility with various system configurations. ### Dependency Updates - Added `sentence-transformers` for advanced flag suggestions. - Added `WMI` for improved Windows system interactions. - Restored `scapy` package. - Removed `transformers` and `pathlib` packages. ### Security - Updated supported version statuses. - Enhanced logging for better tracking and debugging. ### Deprecations - Removed some deprecated actions and methods. - Streamlined code structure for better maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Pull Request Template
Prerequisites
--devflag, if required.PR Type
update
Description
This pull request includes significant changes to the
Logicyticsproject, focusing on code refactoring, logging improvements, and the removal of deprecated features. The most important changes include the refactoring of flag handling, the addition of detailed logging, and the cleanup of deprecated features.Code Refactoring and Improvements:
CODE/Logicytics.py: Refactoredget_flagsfunction to simplify flag retrieval and logging. Removed deprecated featuresextraandunzip_extrafromhandle_special_actions. Added theLogicyticsmain function to encapsulate the main process logic. [1] [2] [3] [4] [5]Logging Enhancements:
CODE/_debug.py: Added detailed logging topython_versionanddebugfunctions. [1] [2]CODE/_dev.py: Enhanced_prompt_userfunction with more user-friendly prompts and added logging todev_checksfunction. [1] [2] [3] [4]CODE/bluetooth_details.py: Improved logging inget_bluetooth_device_detailsand_query_bluetooth_devices. [1] [2] [3] [4]CODE/bluetooth_logger.py: Added detailed logging and documentation to functionssave_to_file,run_powershell_command,parse_output,get_paired_bluetooth_devices, andlog_bluetooth. [1] [2] [3] [4] [5] [6]Deprecated Feature Removal:
CODE/Logicytics.py: Removed deprecated featuresextraandunzip_extrafromhandle_special_actions. [1] [2]Miscellaneous Changes:
.github/ISSUE_TEMPLATE/bug_report.yml: Renamedflagstoflags_listfor consistency.CODE/_dev.py: Reorganized imports and addedEXCLUDE_FILEStodev_checksfunction. [1] [2]CODE/cmd_commands.py: Added__main__check to execute commands.These changes aim to enhance code readability, improve logging for debugging purposes, and remove outdated features to maintain code quality.
Motivation and Context
To move in version 3.3.0 and fix many bugs and improve Logicytics
Credit
N/A
Issues Fixed
N/A
Summary by CodeRabbit
Release Notes for Logicytics v3.3.0
New Features
Improvements
Bug Fixes
Dependency Updates
sentence-transformersfor advanced flag suggestions.WMIfor improved Windows system interactions.scapypackage.transformersandpathlibpackages.Security
Deprecations