Skip to content

Conversation

@DefinetlyNotAI
Copy link
Owner

@DefinetlyNotAI DefinetlyNotAI commented Jan 2, 2025

Pull Request Template

Prerequisites

  • I have searched for duplicate or closed issues.
  • I have read the contributing guidelines.
  • I have followed the instructions in the wiki about contributions.
  • I have updated the documentation accordingly, if required.
  • I have tested my code with the --dev flag, if required.

PR Type

  • Bug fix
  • Deprecation Change
  • New feature
  • Refactoring
  • Documentation
    update
  • ⚠️ Breaking change ⚠️

Description

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: 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] [2] [3] [4] [5]

Logging Enhancements:

Deprecated Feature Removal:

Miscellaneous Changes:

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

  • 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.

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]>
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]>
@DefinetlyNotAI DefinetlyNotAI self-assigned this Jan 2, 2025
@pull-request-size pull-request-size bot added the size/XXL Super Huge size pr label Jan 2, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2025

Walkthrough

The 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

File Change Summary
.github/ISSUE_TEMPLATE/bug_report.yml Updated dropdown field identifier and label for flags
.gitignore Added entries to ignore user history JSON files
CODE/Logicytics.py Refactored main execution logic, added Logicytics function
CODE/_debug.py Enhanced debug function with logging and added python_version function
CODE/_dev.py Improved error handling and user prompts
CODE/bluetooth_details.py Modified error handling in Bluetooth device queries
CODE/bluetooth_logger.py Enhanced documentation and error handling in utility functions
CODE/cmd_commands.py Encapsulated command execution in a conditional block
CODE/config.ini Added new settings for preferences and flag suggestions
CODE/dir_list.py Updated error handling in threaded command execution
CODE/dump_memory.py Replaced RAM dumping function with new methods for capturing memory
CODE/event_log.py Transitioned to WMI for event log parsing
CODE/log_miner.py Improved error handling in log backup function
CODE/logicytics/Flag.py Enhanced flag suggestion mechanism with historical data tracking
CODE/logicytics/Execute.py Updated return type for script method
CODE/media_backup.py Improved documentation and changed method invocation style
CODE/packet_sniffer.py Enhanced error handling and documentation
CODE/registry.py Encapsulated registry backup function call
CODE/sensitive_data_miner.py Expanded allowed file types and improved error handling
CODE/ssh_miner.py Encapsulated SSH miner function call
CODE/sys_internal.py Streamlined execution flow for system checks
CODE/tasklist.py Encapsulated tasklist function call
CODE/vulnscan.py Restructured scanning logic with new functions
CODE/wifi_stealer.py Improved modularity by encapsulating function calls
CODE/wmic.py Encapsulated WMIC function call
CREDITS.md Updated contributor information and removed third-party credits
SECURITY.md Updated version support statuses and release dates
requirements.txt Updated dependencies, added sentence-transformers and WMI
README.md Added new entry for bluetooth_logger.py and updated notes

Suggested Labels

type/Documentation

Poem

Code flows like a river wild,
Logicytics grows, features compiled 🚀
Flags dance with historical grace,
Bugs retreat without a trace 🐞
Innovation's sweet embrace! 💻


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f876aa and 77d7519.

📒 Files selected for processing (1)
  • CODE/vulnscan.py (5 hunks)

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@DefinetlyNotAI DefinetlyNotAI added request/Important New feature or request, top priority, for next update bug/Medium Something isn't working, it's affecting the running of the program! type/Dependencies Pull requests that update a dependency file type/Code Related to the Code part labels Jan 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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_files method is doing some heavy lifting without any safety rails:

  1. It's starting from C:\ (root drive) - that's like giving someone keys to your whole house!
  2. It's using multiple threads to copy files - cool for speed, but risky for system resources
  3. No limits on total file size or count

Here's what we should add:

  1. A configurable root directory (not just C:)
  2. File size limits
  3. Total copied files limit
  4. Skip system directories

Want me to show you how to make this safer?

🧰 Tools
🪛 Ruff (0.8.2)

91-91: Loop control variable files not used within loop body

Rename unused files to _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 files not used within loop body

Rename unused files to _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_use and vectorizer_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 Exception catch 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 code 1 might 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:

  1. Security:

    • It's copying sensitive files to one place - that's risky!
    • No encryption for the copied files
    • No access controls
  2. System Impact:

    • Could eat up disk space
    • Might slow down the system
    • No resource limits

Here's what we should add:

  1. File encryption
  2. Resource monitoring
  3. Access logging
  4. 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 f prefix

(F541)


251-266: Cool new feature for handling multiple log messages! 📝

The parse_execution method 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 stats
CODE/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.0
CODE/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_data and G) 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 handling

The 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 cleanup

It'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 here
CODE/logicytics/Flag.py (3)

4-36: Neat config approach, watch for missing config
Yo, it's dope how you load config from config.ini or 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_sim function is sweet, but you might want to catch if sentence_transformers isn’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 issue

Yo! 🚨 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:

  1. Adding a warning when copying these high-risk files
  2. Implementing file size limits
  3. Adding checksums to track file integrity

Want me to help create a safer implementation?

CODE/logicytics/Logger.py (1)

269-295: 🛠️ Refactor suggestion

⚠️ Potential issue

Awesome 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 result

These changes will:

  1. Check for callable before wrapping (no need to use exception logging here)
  2. Log the actual arguments being passed
  3. 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 result
CODE/event_log.py (3)

32-34: ⚠️ Potential issue

Whoa 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_type to 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 issue

Hey! 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 issue

Watch 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:

  1. Check available disk space before dumping
  2. Add a timeout for large dumps
  3. 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")
+            return

Committable 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.ini file:

[Models]
vulnscan_model_path = VulnScan/models/sensemini.pth
vulnscan_vectorizer_path = VulnScan/models/vectorizer.pkl

151-188: ⚠️ Potential issue

Whoa 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_graph is using that global G variable. 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 PacketSniffer class:

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`
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2025

Note

We have generated docstrings for this pull request, at #178

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>
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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_data and G) 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:

  1. Encrypt the copied files
  2. Add access controls to the destination folder
  3. 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_use and vectorizer_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! 👀

  1. That f-string on line 269 doesn't need to be an f-string since it's just a regular string.
  2. 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 f prefix

(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:

  1. Add user authentication and authorization
  2. Log all operations for audit trails
  3. Add rate limiting and resource controls
  4. Implement secure storage with encryption
  5. 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:

  1. The file path is hardcoded - maybe we should make it configurable?
  2. 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_device
CODE/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 f prefix

(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 issue

Whoa! 🚨 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:

  1. Adding a warning message before copying these sensitive files
  2. Implementing file size limits to prevent copying large database files
  3. 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:

  1. Add a max worker limit to ThreadPoolExecutor
  2. Add a progress bar
  3. 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 issue

Oops! Found a sneaky bug in the disk space check! 🐛

The return statement is inside the if block 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 success
CODE/vulnscan.py (1)

166-171: ⚠️ Potential issue

Those 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}"
                    )

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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:

  1. The logs are showing full file paths - that's risky!
  2. We're not checking file permissions
  3. 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:

  1. Let users specify which drives/folders to scan
  2. Add a progress bar (using tqdm)
  3. 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:

  1. Move keywords to a config file
  2. Add regex pattern support
  3. 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 permissions
CODE/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:

  1. It uses Python's built-in thread pool 🎯
  2. It handles errors better 🛠️
  3. It shows progress as scripts complete ✨
  4. 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:

  1. Track which steps completed successfully 📝
  2. Tell you exactly where it failed if something goes wrong 🎯
  3. 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 __colorify method! 🚨

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_SIZE constant 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 datetime at 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_device
CODE/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_files parameter is super helpful for filtering out unwanted files. Just one tiny thing - adding a type hint for exclude_files would 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 function
CODE/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 Exception at 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 result
CODE/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:

  1. Move the corrections to a config file so it's easier to update
  2. Add more common variations
  3. 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:

  1. Moving the debug log outside the callback
  2. Using a closure instead of nonlocal
  3. 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_graph method 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 --webhook and --restore flags 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 issue

Oops! Found a bug in the disk space check! 🐛

There's a sneaky bug here - the return statement is inside the if block that checks disk space, which means it'll return None when 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")
                        return
CODE/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:

  1. A file size limit to avoid huge files
  2. A depth limit for directory searching
  3. 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:

  1. Have proper authorization to scan these files
  2. Handle the found data with extreme care
  3. 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.py is 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.py

Length of output: 532

CODE/logicytics/__init__.py (1)

12-14: ⚠️ Potential issue

Yo, 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 issue

Watch 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 issue

Watch out! There's a potential bug here! 🐛

If exclude_files is None (which is its default value), trying to check if a filename is in exclude_files will 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 use tuple[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", None
CODE/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.

Repository owner deleted a comment from coderabbitai bot Jan 3, 2025
Repository owner deleted a comment from coderabbitai bot Jan 3, 2025
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]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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! 🛑

  1. Hard-coding "C:" is not cool - what if someone's sensitive stuff is on another drive?
  2. Putting all sensitive files in one folder called "Password_Files" is like painting a target on it
  3. We're not cleaning up after ourselves - these copied files just stay there!

Here's what we should do:

  1. Make the search path configurable
  2. Use a less obvious directory name
  3. Add an option to securely delete files after analysis
  4. 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:

  1. Add rate limiting to avoid system overload
  2. Keep track of which files we've copied (maybe in a secure log)
  3. Add a way to exclude certain directories (like Program Files)
  4. 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_file fails, 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_MSG is 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! 🚀

  1. 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'),
  1. 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:

  1. The 10-minute timeout is hardcoded
  2. Thread names would help with debugging
  3. Use os.path.join() for file paths to avoid problems on different systems

Here'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 than os.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 shorter

Hey! 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 better

The 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 False is 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 False

Remove 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 += RESET
CODE/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_execution method 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 result
CODE/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 file

Add 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:

  1. Add error handling for matplotlib
  2. Add progress indicators for long operations
  3. 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 issue

Whoa! 🚨 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:

  1. Add a big warning in the docs about the responsibility of using this tool
  2. Consider adding file size limits for these types
  3. 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 issue

We 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 issue

Watch 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:

  1. The success log at line 94 is showing the full file path again
  2. 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 issue

Watch 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 issue

Heads up! You've got an unused import hanging around 🎯

The static analysis tool caught that we're importing Log but never using it. Let's clean that up!

-from logicytics.Logger import Log
🧰 Tools
🪛 Ruff (0.8.2)

9-9: logicytics.Logger.Log imported 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:

  1. There's a blanket warnings.filterwarnings("ignore") that blocks ALL warnings
  2. 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 py

Length 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, None
CODE/logicytics/Flag.py (3)

658-658: ⚠️ Potential issue

What 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 issue

Oops! This return statement is in the wrong place! 🙈

The early return when SAVE_PREFERENCES is 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:
+                return

Committable 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_sim for 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
@qlty-cloud-legacy
Copy link

Code Climate has analyzed commit 77d7519 and detected 4 issues on this pull request.

Here's the issue category breakdown:

Category Count
Bug Risk 4

View more on Code Climate.

@DefinetlyNotAI
Copy link
Owner Author

@CodeRabbit Provide a very thorough and in detail release note for version 3.3.0

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2025

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

  • Removal of Deprecated Features: Old methods like unzip_extra and extra are completely removed. This streamlines the code and makes the main operational flow simpler.
  • New Main Entry Point: Logicytics.py now has a dedicated Logicytics() function that consolidates the tool’s workflow, helping you trace the complete process more clearly.
  • Flag Management: The get_flags function’s logic is simplified. It directly retrieves the main action and sub-action, eliminating the previous error-prone tuple unpacking.

2. Logging Enhancements

  • Granular Logging: Decorators like @log.function and @log_debug.function are used across multiple scripts, emphasizing detailed logging for essential functions.
  • Extended Logs for System Checks: Scripts such as _debug.py and bluetooth_logger.py include more logs for system version checks, debug steps, and possible error outcomes.
  • Console vs. File Logging: Some methods have updated try-except blocks to ensure any errors (e.g. UnicodeDecodeError or config loading issues) get a robust log entry without crashing the entire script.

3. Better Device & Event Coverage

  • Bluetooth Improvements:
    • bluetooth_details.py and bluetooth_logger.py have more precise error handling.
    • Any device that fails to respond or lacks certain info now logs fallback messages instead of prematurely stopping.
  • Transition to WMI: event_log.py replaced win32evtlog calls with WMI queries for broader Windows event coverage. Expect more consistent event data retrieval, plus improved concurrency when parsing logs.

4. Configuration & User Interface

  • Refreshed config.ini:
    • New [Flag Settings] section, which holds accuracy_min, model_to_use, and model_debug to refine how flags are auto-suggested and displayed.
    • A save_preferences setting is added to let you opt in or out of saving user history and preferences.
  • Flag.py Enhancements:
    • A new class Match manages user-input similarity scoring using Sentence Transformers.
    • User history is stored in gzipped JSON to preserve data in a smaller footprint, with logic to load and save that history automatically.

5. Streamlined Execution

  • Threaded Operations: In scripts like dir_list.py, vulnscan.py, and dump_memory.py, the older concurrency approach has been upgraded to ThreadPoolExecutor. This yields more efficient parallel execution and better scaling on multicore systems.
  • Safe Conditional Imports: Many scripts (cmd_commands.py, ssh_miner.py, registry.py, etc.) now call their main functions only if __name__ == "__main__". This prevents accidental execution when importing modules and gives you clearer, more modular usage in larger pipelines.

6. Deprecated Feature Removal

  • FileManagement.unzip: The unzipping method is completely removed. If your flow depended on that, you’ll need an external library or script for unarchiving.
  • Legacy Settings: The old extra parameters are gone from handle_special_actions. This reduces confusion about rarely used tasks and slims down the codebase.

7. Upgrade Path

  1. Check Dependencies:
    • requirements.txt now uses sentence-transformers~=3.3.1 and WMI~=1.5.1. Make sure to install or update these packages accordingly.
    • numpy is pinned at ~=2.0.2, and transformers plus pathlib got removed.
  2. Configuration Changes:
    • If you used any of the removed settings (like unzip_extra), review your workflow.
    • Adjust any references to the updated config options in [Flag Settings].
  3. Review Scripts:
    • Many scripts are only executed when run directly. If you automated them or import them, ensure you call the new main or relevant function explicitly.

8. Known Limitations & Considerations

  • Experimental Flag Suggestions: The new Match class for similarity suggestions is a big step forward, but you may still see inaccurate suggestions if your user history is limited or if your data is extremely varied.
  • Partial Platform Support: Tools relying on Windows-specific libraries (like WMI) might not function on non-Windows systems. Linux-based setups will need alternative approaches or stubs for such functionality.
  • Concurrent Execution: While concurrency speeds up scanning/logging, be mindful of system constraints. For extremely large directories or event logs, you may need to tweak thread pool sizing for best performance.

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!

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 issue

Hey! 🤔 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 issue

Yo! 🎯 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:\Windows might 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 issue

Yo! 🚫 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.txt to avoid any surprise breaks!

Committable suggestion skipped: line range outside the PR's diff.


205-236: ⚠️ Potential issue

Hold 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.

@DefinetlyNotAI DefinetlyNotAI merged commit 29ba9f4 into main Jan 4, 2025
9 checks passed
@DefinetlyNotAI DefinetlyNotAI deleted the bug-fixes-and-v3.3.0 branch January 4, 2025 15:38
@coderabbitai coderabbitai bot mentioned this pull request Jul 27, 2025
11 tasks
DefinetlyNotAI pushed a commit that referenced this pull request Sep 18, 2025
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`
DefinetlyNotAI added a commit that referenced this pull request Sep 18, 2025
> [!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>
DefinetlyNotAI added a commit that referenced this pull request Sep 18, 2025
## 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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug/Medium Something isn't working, it's affecting the running of the program! request/Important New feature or request, top priority, for next update size/XXL Super Huge size pr type/Code Related to the Code part type/Dependencies Pull requests that update a dependency file type/Development Related to Development issues type/System Related to System Code for Logicytics

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants