-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update #135
update #135
Conversation
Reviewer's Guide by SourceryThis PR introduces a series of refactorings and new feature additions. Key implementations include adding explicit type annotations and improving error handling, renaming classes to follow PascalCase conventions, enhancing user input validations, and expanding the functionality by introducing a dynamic tool generator alongside new information gathering tool modules. Class diagram for Utility and its subclasses (Updated)classDiagram
class Utility {
+__init__(description: str = None)
+__str__() -> str
+run() -> None
}
class Host2IP {
+__init__() -> None
+run() -> None
}
class Base64Decode {
+__init__() -> None
+run() -> None
}
class SpawnShell {
+__init__() -> None
+run() -> None
}
class SuggestTool {
+__init__() -> None
+run() -> None
}
class PrintContributors {
+__init__() -> None
+run() -> None
}
Utility <|-- Host2IP
Utility <|-- Base64Decode
Utility <|-- SpawnShell
Utility <|-- SuggestTool
Utility <|-- PrintContributors
Class diagram for Dynamic Tool Generator and New Information Gathering ToolsclassDiagram
%% Base class provided by the system
class GitHubRepo {
+__init__(path: str, install, description: str = None) -> None
+run()
}
class DynamicRepo {
+__init__() -> None
+run() -> int
}
%% DynamicRepo is created within the create_tool_class function
GitHubRepo <|-- DynamicRepo
class CuteitRepo {
+__init__() -> None
+run() -> int
}
class ReconSpiderRepo {
+__init__() -> None
+run() -> int
}
class rang3rRepo {
+__init__() -> None
+run() -> int
}
class SecretFinderRepo {
+__init__() -> None
+run() -> int
}
GitHubRepo <|-- CuteitRepo
GitHubRepo <|-- ReconSpiderRepo
GitHubRepo <|-- rang3rRepo
GitHubRepo <|-- SecretFinderRepo
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughThe pull request refactors multiple modules across the project. In the CLI’s main loop and supporting functions, type annotations, docstrings, and error handling have been improved. Several utility classes have been renamed to follow PascalCase, with updated constructors and method signatures. New repository classes for additional information gathering tools have been added with their own interactive run methods. Furthermore, a new dynamic tool generator in Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainLoop
participant CommandHandler
User->>MainLoop: Display menu
User->>MainLoop: Enter command
MainLoop->>CommandHandler: Validate command
alt Valid command
MainLoop->>CommandHandler: Execute command
else Invalid command
MainLoop->>User: Print error message
end
MainLoop->>User: Continue loop
sequenceDiagram
participant User
participant GenerateScript
participant ToolGenerator
participant FileSystem
User->>GenerateScript: Run generate.py with args
GenerateScript->>ToolGenerator: Call create_tool_class()
ToolGenerator->>ToolGenerator: Define DynamicRepo class
GenerateScript->>FileSystem: Write new tool file
FileSystem-->>GenerateScript: Confirm file creation
GenerateScript->>User: Print confirmation message
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) |
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | ||
return os.system('python3 rang3r.py -v -d ' + user_domain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Prevent command injection vulnerability
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | |
return os.system('python3 rang3r.py -v -d ' + user_domain) | |
from shlex import quote | |
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | |
return os.system('python3 rang3r.py -v -d ' + quote(user_domain)) |
Co-authored-by: qodo-merge-pro[bot] <151058649+qodo-merge-pro[bot]@users.noreply.github.com> Signed-off-by: fortishield <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
cybersf/core/utilities.py (1)
31-38
: Add error handling for DNS resolution.The Host2IP.run method should handle DNS resolution failures gracefully.
Apply this diff:
def run(self) -> None: hosts = get_hosts() set_readline(hosts) user_host = input("\nEnter a host: ").strip() if user_host not in hosts: add_host(user_host) - ip = gethostbyname(user_host) - console.print(f"\n{user_host} has the IP of {ip}") + try: + ip = gethostbyname(user_host) + console.print(f"\n{user_host} has the IP of {ip}") + except Exception as e: + console.print(f"Error resolving host: {e}", style="bold red")
🧹 Nitpick comments (4)
cybersf/obfuscation/cuteit.py (1)
7-7
: Enhance IP validation.While the empty input check is good, consider adding more robust IP validation to ensure the input is a valid IP address format.
Here's a suggested implementation:
def run(self) -> int: os.chdir(self.full_path) user_ip = input("\nEnter an IP: ").strip() - if not user_ip: + import re + ip_pattern = r'^(\d{1,3}\.){3}\d{1,3}$' + if not user_ip or not re.match(ip_pattern, user_ip): print("Invalid IP") return 1 + # Optional: Validate each octet is between 0-255 + if not all(0 <= int(octet) <= 255 for octet in user_ip.split('.')): + print("Invalid IP: octets must be between 0-255") + return 1Also applies to: 14-19
cybersf/information_gathering/rang3r.py (1)
7-12
: Add type hints for consistency.For consistency with other files like
cuteit.py
, consider adding return type hints to the methods.class rang3rRepo(GitHubRepo): - def __init__(self): + def __init__(self) -> None: super().__init__( path='floriankunushevci/rang3r', install={'pip': 'requirements.txt'}, description='rang3r is a python script which scans in multi thread', )cybersf/information_gathering/secretfinder.py (1)
7-12
: Add type hints for consistency.For consistency with other files like
cuteit.py
, consider adding return type hints to the methods.class SecretFinderRepo(GitHubRepo): - def __init__(self): + def __init__(self) -> None: super().__init__( path='m4ll0k/SecretFinder', install={'pip': 'requirements.txt'}, description='SecretFinder - A python script for find sensitive data', )generate.py (1)
44-60
: Remove unnecessary f-strings and improve file writing.The static analysis tool correctly identified unnecessary f-strings.
Apply this diff:
- tool_file.write(f"import os\n\n") - tool_file.write(f"from cybersf.core.menu import set_readline\n") - tool_file.write(f"from cybersf.core.repo import GitHubRepo\n\n") + imports = [ + "import os", + "from cybersf.core.menu import set_readline", + "from cybersf.core.repo import GitHubRepo", + "" + ] + tool_file.write("\n".join(imports) + "\n")🧰 Tools
🪛 Ruff (0.8.2)
44-44: f-string without any placeholders
Remove extraneous
f
prefix(F541)
45-45: f-string without any placeholders
Remove extraneous
f
prefix(F541)
46-46: f-string without any placeholders
Remove extraneous
f
prefix(F541)
49-49: f-string without any placeholders
Remove extraneous
f
prefix(F541)
50-50: f-string without any placeholders
Remove extraneous
f
prefix(F541)
54-54: f-string without any placeholders
Remove extraneous
f
prefix(F541)
55-55: f-string without any placeholders
Remove extraneous
f
prefix(F541)
56-56: f-string without any placeholders
Remove extraneous
f
prefix(F541)
57-57: f-string without any placeholders
Remove extraneous
f
prefix(F541)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
cybersf/__main__.py
(1 hunks)cybersf/core/menu.py
(1 hunks)cybersf/core/repo.py
(2 hunks)cybersf/core/utilities.py
(4 hunks)cybersf/information_gathering/cli.py
(1 hunks)cybersf/information_gathering/rang3r.py
(1 hunks)cybersf/information_gathering/reconspider.py
(1 hunks)cybersf/information_gathering/secretfinder.py
(1 hunks)cybersf/obfuscation/cuteit.py
(1 hunks)generate.py
(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
generate.py
44-44: f-string without any placeholders
Remove extraneous f
prefix
(F541)
45-45: f-string without any placeholders
Remove extraneous f
prefix
(F541)
46-46: f-string without any placeholders
Remove extraneous f
prefix
(F541)
49-49: f-string without any placeholders
Remove extraneous f
prefix
(F541)
50-50: f-string without any placeholders
Remove extraneous f
prefix
(F541)
54-54: f-string without any placeholders
Remove extraneous f
prefix
(F541)
55-55: f-string without any placeholders
Remove extraneous f
prefix
(F541)
56-56: f-string without any placeholders
Remove extraneous f
prefix
(F541)
57-57: f-string without any placeholders
Remove extraneous f
prefix
(F541)
🔇 Additional comments (8)
cybersf/information_gathering/cli.py (1)
11-13
: LGTM!The new tools are correctly imported and added to the
__tools__
list, maintaining consistency with the existing code structure.Also applies to: 15-15
cybersf/core/utilities.py (2)
27-28
: LGTM! Good improvements in naming conventions.The class renames to PascalCase improve code consistency and follow Python naming conventions.
Also applies to: 41-42, 54-55, 65-66, 75-76
45-51
: Good addition of error handling for base64 decoding.The try-except block with specific error messaging improves user experience.
cybersf/core/menu.py (1)
128-142
: LGTM! Excellent improvements to the confirm function.The changes enhance the function through:
- Clear type hints
- Comprehensive docstring
- Robust input validation with user feedback
cybersf/__main__.py (2)
128-132
: LGTM! Well-documented function signature.The return type annotation and docstring follow Python best practices, improving code clarity and maintainability.
138-154
: LGTM! Improved error handling.The error handling has been enhanced with:
- Simplified conditional check
- More descriptive error messages
- Streamlined control flow
cybersf/core/repo.py (2)
27-27
: LGTM! Improved error message.The descriptive error message helps users understand why the error occurred.
98-98
: LGTM! Added type annotation for optional parameter.The type annotation
Optional[str]
improves type safety and code clarity.
def run(self): | ||
os.chdir(self.full_path) | ||
set_readline([]) | ||
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | ||
return os.system('python3 rang3r.py -v -d ' + user_domain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix command injection vulnerability.
The user input is directly used in a system command, which could allow command injection. Consider sanitizing the input and using shell argument escaping.
- def run(self):
+ def run(self) -> int:
os.chdir(self.full_path)
set_readline([])
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip()
- return os.system('python3 rang3r.py -v -d ' + user_domain)
+ import shlex
+ if not user_domain:
+ print("Invalid domain")
+ return 1
+ return os.system(f"python3 rang3r.py -v -d {shlex.quote(user_domain)}")
📝 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 run(self): | |
os.chdir(self.full_path) | |
set_readline([]) | |
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | |
return os.system('python3 rang3r.py -v -d ' + user_domain) | |
def run(self) -> int: | |
os.chdir(self.full_path) | |
set_readline([]) | |
user_domain = input('\nEnter a domain to enumerate for rang3r: ').strip() | |
import shlex | |
if not user_domain: | |
print("Invalid domain") | |
return 1 | |
return os.system(f"python3 rang3r.py -v -d {shlex.quote(user_domain)}") |
user_domain = input('\nEnter a domain to enumerate for ReconSpider: ').strip() | ||
return os.system('python3 reconspider.py -v -d ' + user_domain) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation and sanitization for the domain.
The user input is directly used in os.system without validation or sanitization, which could lead to command injection vulnerabilities.
Apply this diff to add basic validation:
- user_domain = input('\nEnter a domain to enumerate for ReconSpider: ').strip()
- return os.system('python3 reconspider.py -v -d ' + user_domain)
+ user_domain = input('\nEnter a domain to enumerate for ReconSpider: ').strip()
+ if not user_domain or ' ' in user_domain:
+ console.print("Invalid domain format", style="bold red")
+ return 1
+ return os.system(f"python3 reconspider.py -v -d {shlex.quote(user_domain)}")
Also add these imports:
import shlex
from cybersf.console import console
category_dir = os.path.join("cybersf", args.item) | ||
if not os.path.exists(category_dir): | ||
os.makedirs(category_dir) | ||
|
||
tool_file_path = os.path.join(category_dir, f"{args.name.lower()}.py") | ||
with open(tool_file_path, "w") as tool_file: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add path validation and error handling for file operations.
The file path handling needs validation and proper error handling.
Apply this diff:
- category_dir = os.path.join("cybersf", args.item)
- if not os.path.exists(category_dir):
- os.makedirs(category_dir)
-
- tool_file_path = os.path.join(category_dir, f"{args.name.lower()}.py")
- with open(tool_file_path, "w") as tool_file:
+ if not args.item.isalnum() or not args.name.isalnum():
+ raise ValueError("Category and tool names must be alphanumeric")
+
+ category_dir = os.path.join("cybersf", args.item)
+ try:
+ os.makedirs(category_dir, exist_ok=True)
+ tool_file_path = os.path.join(category_dir, f"{args.name.lower()}.py")
+ with open(tool_file_path, "w") as tool_file:
Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- if not args.item.isalnum() or not args.name.isalnum():
-
raise ValueError("Category and tool names must be alphanumeric")
- category_dir = os.path.join("cybersf", args.item)
- try:
-
os.makedirs(category_dir, exist_ok=True)
-
tool_file_path = os.path.join(category_dir, f"{args.name.lower()}.py")
-
with open(tool_file_path, "w") as tool_file:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FortiShield Thanks for considering these security improvements! Have you implemented these changes? Let me know once they're in place so we can ensure the file operations are properly secured.
🐰 thoughtfully taking notes about secure file operations
✏️ Learnings added
Learnt from: FortiShield
PR: khulnasoft/CyberSF#135
File: generate.py:38-0
Timestamp: 2025-02-10T10:34:08.316Z
Learning: When handling file operations in CLI tools, always validate input paths (using isalnum() for directory/file names), use os.makedirs() with exist_ok=True to handle race conditions, and wrap file operations in try-except blocks to handle potential IOErrors gracefully.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
Signed-off-by: fortishield <[email protected]>
|
User description
Notes for Reviewers
This PR fixes #
Signed commits
PR Type
Enhancement, Documentation
Description
Enhanced type annotations and added docstrings for better clarity.
Introduced new tools:
rang3r
,reconspider
, andsecretfinder
.Improved error handling and user input validation across utilities.
Added a dynamic tool generation script (
generate.py
) for extensibility.Changes walkthrough 📝
10 files
Enhanced main loop with type annotations and error handling
Improved user confirmation prompt with validation and docstring
Enhanced error messages and added type annotations
Refactored utility classes with type annotations and error handling
Added new tools to the information gathering CLI
Added `rang3r` tool for multi-threaded domain scanning
Added `reconspider` tool for advanced OSINT
Added `secretfinder` tool for sensitive data discovery
Improved IP validation and added type annotations
Introduced dynamic tool generation script
1 files
Summary by CodeRabbit
New Features
reconspider
,secretfinder
, andrang3r
.Bug Fixes
Refactor
Documentation