Skip to content

Commit 9cac7c7

Browse files
committed
chore: Remediate Vulnerabilites across all repos with shared utilities
1 parent fdd1adb commit 9cac7c7

File tree

3 files changed

+51
-28
lines changed

3 files changed

+51
-28
lines changed

.hooks/check-compiled-requirements.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22
if they are out of sync with requirements.in and requirements-dev.in.
33
"""
44

5-
import subprocess # nosec B404
5+
import subprocess # nosec B404 - subprocess is used safely with controlled arguments
66
import sys
77
from pathlib import Path
88
from shutil import which
9-
from typing import Optional
9+
10+
11+
def get_pip_compile_path() -> str:
12+
"""Resolve the full path to pip-compile."""
13+
pip_compile = which("pip-compile")
14+
if not pip_compile:
15+
print("[Error] pip-compile not found in PATH.")
16+
sys.exit(1)
17+
return pip_compile
18+
19+
20+
PIP_COMPILE = get_pip_compile_path()
1021

1122

1223
def recompile(in_file: str, out_file: str) -> bool:
@@ -21,8 +32,8 @@ def recompile(in_file: str, out_file: str) -> bool:
2132
"""
2233
print(f"[Fix] Recompiling {in_file} -> {out_file}")
2334
try:
24-
subprocess.run( # nosec B603
25-
["pip-compile", in_file, "--resolver=backtracking", "--output-file", out_file],
35+
subprocess.run( # nosec B603 - fully qualified pip-compile path and safe args
36+
[PIP_COMPILE, in_file, "--resolver=backtracking", "--output-file", out_file],
2637
check=True,
2738
)
2839
return True
@@ -49,8 +60,8 @@ def check_file(in_file: str, out_file: str, autofix: bool = True) -> bool:
4960
tmp_out = Path(out_file + ".tmp")
5061

5162
try:
52-
subprocess.run( # nosec B603
53-
["pip-compile", in_file, "--resolver=backtracking", "--output-file", str(tmp_out)],
63+
subprocess.run( # nosec B603 - safe, static argument list
64+
[PIP_COMPILE, in_file, "--resolver=backtracking", "--output-file", str(tmp_out)],
5465
check=True,
5566
stdout=subprocess.DEVNULL,
5667
stderr=subprocess.DEVNULL,
@@ -73,10 +84,6 @@ def check_file(in_file: str, out_file: str, autofix: bool = True) -> bool:
7384

7485
def main() -> int:
7586
"""Main entry point for the hook."""
76-
if not which("pip-compile"):
77-
print("[Error] pip-compile not found in PATH.")
78-
return 1
79-
8087
ok1 = check_file("requirements.in", "requirements.txt", autofix=True)
8188
ok2 = check_file("requirements-dev.in", "requirements-dev.txt", autofix=True)
8289

src/app/queue_handler.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@
1818
logger = setup_logger(__name__)
1919
shutdown_event = threading.Event()
2020

21+
REDACT_SENSITIVE_LOGS = config.get_config_value("REDACT_SENSITIVE_LOGS", "true").lower() == "true"
22+
23+
24+
def safe_log(msg: str) -> str:
25+
"""Standardized redacted log message."""
26+
return f"{msg}: [REDACTED]" if REDACT_SENSITIVE_LOGS else msg
27+
2128

2229
def consume_messages(callback: Callable[[list[dict]], None]) -> None:
2330
"""Start the queue listener for the configured queue type.
2431
2532
Args:
2633
callback: A function that takes a list of messages and processes them.
27-
2834
"""
2935
signal.signal(signal.SIGINT, _graceful_shutdown)
3036
signal.signal(signal.SIGTERM, _graceful_shutdown)
@@ -35,7 +41,7 @@ def consume_messages(callback: Callable[[list[dict]], None]) -> None:
3541
elif queue_type == "sqs":
3642
_start_sqs_listener(callback)
3743
else:
38-
raise ValueError(f"Unsupported QUEUE_TYPE: {queue_type}")
44+
raise ValueError("Unsupported QUEUE_TYPE: [REDACTED]")
3945

4046

4147
def _graceful_shutdown(signum, frame) -> None:
@@ -50,7 +56,6 @@ def _start_rabbitmq_listener(callback: Callable[[list[dict]], None]) -> None:
5056
5157
Args:
5258
callback: Function to process received messages.
53-
5459
"""
5560
connection = pika.BlockingConnection(
5661
pika.ConnectionParameters(
@@ -76,11 +81,11 @@ def on_message(ch: BlockingChannel, method, properties, body: bytes) -> None:
7681
callback([message])
7782
ch.basic_ack(delivery_tag=method.delivery_tag)
7883
logger.debug("✅ RabbitMQ message processed and acknowledged.")
79-
except Exception as e:
80-
logger.error(f"❌ Error processing RabbitMQ message: {e}")
84+
except Exception:
85+
logger.error("❌ RabbitMQ message processing failed (details redacted)")
8186
ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)
8287

83-
logger.info("🚀 Consuming RabbitMQ messages from queue: %s", queue_name)
88+
logger.info(safe_log("🚀 Consuming RabbitMQ messages from queue"))
8489

8590
try:
8691
channel.basic_qos(prefetch_count=config.get_batch_size())
@@ -99,12 +104,11 @@ def _start_sqs_listener(callback: Callable[[list[dict]], None]) -> None:
99104
100105
Args:
101106
callback: Function to process a batch of messages.
102-
103107
"""
104108
sqs = boto3.client("sqs", region_name=config.get_sqs_region())
105109
queue_url = config.get_sqs_queue_url()
106110

107-
logger.info("🚀 Polling SQS queue: %s", queue_url)
111+
logger.info(safe_log("🚀 Polling SQS queue"))
108112

109113
while not shutdown_event.is_set():
110114
try:
@@ -125,17 +129,17 @@ def _start_sqs_listener(callback: Callable[[list[dict]], None]) -> None:
125129
payload = json.loads(msg["Body"])
126130
payloads.append(payload)
127131
receipt_handles.append(msg["ReceiptHandle"])
128-
except Exception as e:
129-
logger.warning(f"⚠️ Failed to parse SQS message: {e}")
132+
except Exception:
133+
logger.warning("⚠️ Failed to parse SQS message body (redacted)")
130134

131135
if payloads:
132136
callback(payloads)
133137
for handle in receipt_handles:
134138
sqs.delete_message(QueueUrl=queue_url, ReceiptHandle=handle)
135139
logger.debug("✅ SQS: Processed and deleted %d message(s)", len(payloads))
136140

137-
except (BotoCoreError, NoCredentialsError) as e:
138-
logger.error("❌ SQS error: %s", e)
141+
except (BotoCoreError, NoCredentialsError):
142+
logger.error("❌ SQS error encountered (details redacted)")
139143
time.sleep(5)
140144

141145
logger.info("🛑 SQS polling stopped.")

src/app/queue_sender.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020

2121
logger = setup_logger(__name__)
2222

23+
REDACT_SENSITIVE_LOGS = config_shared.get_config_value("REDACT_SENSITIVE_LOGS", "true").lower() == "true"
24+
25+
26+
def safe_log_message(data: dict[str, Any]) -> str:
27+
"""Return redacted or full string for logging."""
28+
return "[REDACTED]" if REDACT_SENSITIVE_LOGS else json.dumps(data, ensure_ascii=False)
29+
2330

2431
def publish_to_queue(payload: list[dict[str, Any]]) -> None:
2532
"""Publish processed results to RabbitMQ or SQS.
@@ -28,8 +35,11 @@ def publish_to_queue(payload: list[dict[str, Any]]) -> None:
2835
----------
2936
payload : list[dict[str, Any]]
3037
A list of message payloads to publish.
31-
3238
"""
39+
if not isinstance(payload, list):
40+
logger.error("❌ Invalid payload type: expected list, got %s", type(payload).__name__)
41+
return
42+
3343
queue_type = config_shared.get_queue_type().lower()
3444

3545
for message in payload:
@@ -38,7 +48,8 @@ def publish_to_queue(payload: list[dict[str, Any]]) -> None:
3848
elif queue_type == "sqs":
3949
_send_to_sqs(message)
4050
else:
41-
logger.error("❌ Invalid QUEUE_TYPE specified: %s", queue_type)
51+
redacted_type = "[REDACTED]" if REDACT_SENSITIVE_LOGS else queue_type
52+
logger.error("❌ Invalid QUEUE_TYPE specified. Value may be misconfigured or missing.")
4253

4354

4455
@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=2, max=10))
@@ -56,7 +67,6 @@ def _send_to_rabbitmq(data: dict[str, Any]) -> None:
5667
If connection to RabbitMQ fails.
5768
Exception
5869
If message publishing fails.
59-
6070
"""
6171
try:
6272
credentials = pika.PlainCredentials(
@@ -77,7 +87,9 @@ def _send_to_rabbitmq(data: dict[str, Any]) -> None:
7787
routing_key=config_shared.get_rabbitmq_routing_key(),
7888
body=json.dumps(data, ensure_ascii=False),
7989
)
80-
logger.info("✅ Published message to RabbitMQ.")
90+
91+
logger.info("✅ Published message to RabbitMQ: %s", safe_log_message(data)) # nosec
92+
8193
except AMQPConnectionError as e:
8294
logger.exception("❌ RabbitMQ publish connection error: %s", e)
8395
raise
@@ -103,7 +115,6 @@ def _send_to_sqs(data: dict[str, Any]) -> None:
103115
If credentials are not available.
104116
Exception
105117
If message publishing fails.
106-
107118
"""
108119
sqs_url = config_shared.get_sqs_queue_url()
109120
region = config_shared.get_sqs_region()
@@ -114,7 +125,8 @@ def _send_to_sqs(data: dict[str, Any]) -> None:
114125
QueueUrl=sqs_url,
115126
MessageBody=json.dumps(data, ensure_ascii=False),
116127
)
117-
logger.info("✅ Published message to SQS (MessageId: %s)", response.get("MessageId"))
128+
logger.info("✅ Published message to SQS: %s", safe_log_message(data)) # nosec
129+
118130
except (BotoCoreError, NoCredentialsError) as e:
119131
logger.exception("❌ Failed to initialize SQS client: %s", e)
120132
raise

0 commit comments

Comments
 (0)