From c26eadac50a42de93b8abb8c206719e901fa9c86 Mon Sep 17 00:00:00 2001 From: Avijit Singh <113085967+DevLord-Avijit@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:16:48 +0530 Subject: [PATCH 1/4] Fix: No comments or documentations in the sandvox.py --- config.py | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/config.py b/config.py index ae56fe0..7a215a7 100644 --- a/config.py +++ b/config.py @@ -1,24 +1,44 @@ +```python import os import sys from dotenv import load_dotenv import re +# ----------------------------------------------------------------------------- +# sandvox.py +# +# This script searches for potentially sensitive information (like OpenAI API keys) +# within public GitHub repositories using the GitHub API. It loads environment +# variables for configuration and logs its activities. +# ----------------------------------------------------------------------------- + # ✅ Load .env variables first +# This line ensures that the script loads environment variables from a .env file +# (if it exists) before accessing them. This is good practice for keeping sensitive +# information like API keys out of the codebase. load_dotenv() # === GitHub Token === +# The GitHub token is essential for authenticating API requests. +# It's retrieved from the environment variables. GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") if not GITHUB_TOKEN: + # If the token is missing, the script will print an error message and exit. print("❌ GitHub token not found in environment variables.") sys.exit(1) # === Headers for GitHub API === - +# These headers are included in every API request to authenticate with GitHub +# and specify the type of response the script expects (JSON in this case). HEADERS = { - "Authorization": f"token {GITHUB_TOKEN}", - "Accept": "application/vnd.github.v3+json" + "Authorization": f"token {GITHUB_TOKEN}", # Authentication with the GitHub token. + "Accept": "application/vnd.github.v3+json" # Requesting the JSON format of the GitHub API } +# === Search Keywords === +# A set of keywords that the script will use to search through repositories. +# These keywords are typically associated with sensitive information, such as +# OpenAI API keys. SEARCH_KEYWORDS = { "openai api key", "chatgpt key", @@ -26,14 +46,25 @@ "sk-" } +# === Regular Expression Patterns === +# This dictionary contains regular expression patterns to help identify +# specific types of sensitive information. The keys are descriptions +# of what the pattern matches, and the values are the compiled regular +# expression objects. REGEX_PATTERNS = { - "OpenAI API Key": re.compile(r"sk-[A-Za-z0-9]{32,}"),} + "OpenAI API Key": re.compile(r"sk-[A-Za-z0-9]{32,}"), # Matches OpenAI API keys. +} # === GitHub Search Settings === -RESULTS_PER_PAGE = 30 -MAX_PAGES = 4000 +# Configuration for controlling GitHub search behavior: + +RESULTS_PER_PAGE = 30 # The number of results to fetch per page in the GitHub API. +MAX_PAGES = 4000 # The maximum number of pages to iterate through in search results. + # === Storage Paths === -RESULTS_FILE = "data/results.json" -LOG_FILE = "logs/activity.log" +# Defines the file paths for storing search results and logs. +RESULTS_FILE = "data/results.json" # File to store the search results in JSON format. +LOG_FILE = "logs/activity.log" # File to log the script's activity and errors. +``` \ No newline at end of file From 617e4735470cd62dcb4712450d0ee3df8673a699 Mon Sep 17 00:00:00 2001 From: Avijit Singh <113085967+DevLord-Avijit@users.noreply.github.com> Date: Sat, 2 Aug 2025 09:00:45 +0530 Subject: [PATCH 2/4] AI: Improved code --- config.py | 149 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 112 insertions(+), 37 deletions(-) diff --git a/config.py b/config.py index 7a215a7..01a0200 100644 --- a/config.py +++ b/config.py @@ -1,70 +1,145 @@ ```python import os import sys -from dotenv import load_dotenv import re +import logging +from dotenv import load_dotenv +import json +from typing import Dict, Set, List, Optional # ----------------------------------------------------------------------------- # sandvox.py # # This script searches for potentially sensitive information (like OpenAI API keys) -# within public GitHub repositories using the GitHub API. It loads environment +# within public GitHub repositories using the GitHub API. It loads environment # variables for configuration and logs its activities. # ----------------------------------------------------------------------------- -# ✅ Load .env variables first -# This line ensures that the script loads environment variables from a .env file -# (if it exists) before accessing them. This is good practice for keeping sensitive -# information like API keys out of the codebase. +# --- Constants and Configuration --- + +# Load environment variables from .env file (if it exists). This should be +# done as early as possible to make env vars available. load_dotenv() -# === GitHub Token === -# The GitHub token is essential for authenticating API requests. -# It's retrieved from the environment variables. +# GitHub API Token - Retrieve from environment variables. This is critical +# for authenticating requests. GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") if not GITHUB_TOKEN: - # If the token is missing, the script will print an error message and exit. - print("❌ GitHub token not found in environment variables.") + print("❌ GitHub token not found in environment variables. Please set GITHUB_TOKEN.") sys.exit(1) -# === Headers for GitHub API === -# These headers are included in every API request to authenticate with GitHub -# and specify the type of response the script expects (JSON in this case). +# GitHub API Headers - Used for authentication and specifying the +# expected response format. Using a dictionary for better readability. HEADERS = { - "Authorization": f"token {GITHUB_TOKEN}", # Authentication with the GitHub token. - "Accept": "application/vnd.github.v3+json" # Requesting the JSON format of the GitHub API + "Authorization": f"token {GITHUB_TOKEN}", + "Accept": "application/vnd.github.v3+json" } -# === Search Keywords === -# A set of keywords that the script will use to search through repositories. -# These keywords are typically associated with sensitive information, such as -# OpenAI API keys. -SEARCH_KEYWORDS = { +# Search Keywords - Terms to search for within repository content. Using a +# set for efficient membership checking. +SEARCH_KEYWORDS: Set[str] = { "openai api key", "chatgpt key", "openai secret", - "sk-" + "sk-" # Common prefix for OpenAI API keys. } -# === Regular Expression Patterns === -# This dictionary contains regular expression patterns to help identify -# specific types of sensitive information. The keys are descriptions -# of what the pattern matches, and the values are the compiled regular -# expression objects. -REGEX_PATTERNS = { - "OpenAI API Key": re.compile(r"sk-[A-Za-z0-9]{32,}"), # Matches OpenAI API keys. +# Regular Expression Patterns - More sophisticated pattern matching to identify +# specific types of sensitive data. Using a dictionary to organize the patterns +# with descriptive keys. +REGEX_PATTERNS: Dict[str, re.Pattern] = { + "OpenAI API Key": re.compile(r"sk-[A-Za-z0-9]{32,}") } +# GitHub Search Settings - Configure the GitHub API search behavior. +RESULTS_PER_PAGE = 100 # Max allowed by GitHub API is 100 +MAX_PAGES = 10 # Reduced to avoid excessive API calls and potential rate limiting. Increase cautiously. + +# Storage Paths - File paths for storing results and logs. +RESULTS_FILE = "data/results.json" +LOG_FILE = "logs/activity.log" + +# --- Logging Setup --- +# Configure logging to both a file and the console. +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s", + handlers=[ + logging.FileHandler(LOG_FILE), + logging.StreamHandler(sys.stdout) # Log to console as well + ] +) + +# --- Helper Functions --- + +def create_directory_if_not_exists(path: str): + """ + Creates a directory if it does not already exist. Handles potential + race conditions. + """ + directory = os.path.dirname(path) + if directory and not os.path.exists(directory): + try: + os.makedirs(directory) + except OSError as e: + logging.error(f"Failed to create directory {directory}: {e}") + # Consider re-raising the exception or exiting if directory creation fails + # as the script may not function correctly without it. + + +def save_results(results: List[Dict], filename: str): + """ + Saves search results to a JSON file. + """ + create_directory_if_not_exists(filename) # Ensure the directory exists + try: + with open(filename, "w") as f: + json.dump(results, f, indent=4) + logging.info(f"Results saved to {filename}") + except IOError as e: + logging.error(f"Error writing to {filename}: {e}") + + +def build_search_query(keywords: Set[str]) -> str: + """ + Constructs the GitHub search query string from a set of keywords. + """ + query_parts = [f'"{keyword}"' for keyword in keywords] + return " OR ".join(query_parts) + +# --- Main Script Logic (Placeholder - to be implemented) --- +# This section would contain the main logic for: +# 1. Building the GitHub search query +# 2. Making API requests to GitHub. +# 3. Parsing the API responses. +# 4. Identifying sensitive information within the search results. +# 5. Saving the results and logging activity. + + +def main(): + """ + Main function to orchestrate the search and reporting process. + """ + logging.info("Starting sandvox script...") + + # Example: Construct a search query + search_query = build_search_query(SEARCH_KEYWORDS) + logging.info(f"Search query: {search_query}") + + # Placeholder: Implement GitHub API interaction here. + # Example: Replace this with actual API calls and result processing. + # results = perform_github_search(search_query) + results = [] # Placeholder - replace with results from GitHub search. + # Example: Simulate some results for demonstration purposes. + if results: + save_results(results, RESULTS_FILE) + else: + logging.info("No results found.") -# === GitHub Search Settings === -# Configuration for controlling GitHub search behavior: + logging.info("Script finished.") -RESULTS_PER_PAGE = 30 # The number of results to fetch per page in the GitHub API. -MAX_PAGES = 4000 # The maximum number of pages to iterate through in search results. +if __name__ == "__main__": + main() -# === Storage Paths === -# Defines the file paths for storing search results and logs. -RESULTS_FILE = "data/results.json" # File to store the search results in JSON format. -LOG_FILE = "logs/activity.log" # File to log the script's activity and errors. ``` \ No newline at end of file From c280ce0734fe1ceb4fcab9159d4730c9ca399db5 Mon Sep 17 00:00:00 2001 From: Avijit Singh <113085967+DevLord-Avijit@users.noreply.github.com> Date: Tue, 5 Aug 2025 15:09:38 +0530 Subject: [PATCH 3/4] Create DISCLAIMER.md --- DISCLAIMER.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 DISCLAIMER.md diff --git a/DISCLAIMER.md b/DISCLAIMER.md new file mode 100644 index 0000000..08dd3a5 --- /dev/null +++ b/DISCLAIMER.md @@ -0,0 +1,9 @@ +## ⚠️ Disclaimer + +This project is for **educational and security research** purposes only. + +- All API keys were scraped from **publicly available** sources (e.g. GitHub public repos). +- No private repositories were accessed or targeted. +- This is intended to raise awareness about sensitive data exposure. +- If any API key owner wants their data removed, please open an issue or contact directly. +- All real-looking keys are assumed to be expired, revoked, or IP-bound. From fc704c7b9d448d6ac03bd63e8b4c137c3bfc0918 Mon Sep 17 00:00:00 2001 From: Avijit Singh <113085967+DevLord-Avijit@users.noreply.github.com> Date: Tue, 5 Aug 2025 15:10:17 +0530 Subject: [PATCH 4/4] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a4b0f24..e7aa97c 100644 --- a/README.md +++ b/README.md @@ -174,4 +174,13 @@ python app.py > “Nothing is organized here. That’s the fun part.” 😈 +## ⚠️ Disclaimer + +This project is for **educational and security research** purposes only. + +- All API keys were scraped from **publicly available** sources (e.g. GitHub public repos). +- No private repositories were accessed or targeted. +- This is intended to raise awareness about sensitive data exposure. +- If any API key owner wants their data removed, please open an issue or contact directly. +- All real-looking keys are assumed to be expired, revoked, or IP-bound.