Files
prowler/prowler/lib/cli/redact.py
T

114 lines
3.8 KiB
Python

from functools import lru_cache
from importlib import import_module
from colorama import Fore, Style
from prowler.lib.cli.sensitive import SENSITIVE_ARGUMENTS as COMMON_SENSITIVE_ARGUMENTS
from prowler.lib.logger import logger
from prowler.providers.common.provider import Provider, providers_path
REDACTED_VALUE = "REDACTED"
@lru_cache(maxsize=None)
def get_sensitive_arguments() -> frozenset:
"""Collect SENSITIVE_ARGUMENTS from all provider argument modules and the common parser."""
sensitive: set[str] = set()
# Common parser sensitive arguments (e.g., --shodan)
sensitive.update(COMMON_SENSITIVE_ARGUMENTS)
# Provider-specific sensitive arguments
for provider in Provider.get_available_providers():
try:
module = import_module(
f"{providers_path}.{provider}.lib.arguments.arguments"
)
sensitive.update(getattr(module, "SENSITIVE_ARGUMENTS", frozenset()))
except Exception as error:
logger.debug(f"Could not load SENSITIVE_ARGUMENTS from {provider}: {error}")
return frozenset(sensitive)
def redact_argv(argv: list[str]) -> str:
"""Redact values of sensitive CLI flags from an argument list.
Handles both ``--flag value`` and ``--flag=value`` syntax.
Returns a single joined string suitable for display.
"""
sensitive = get_sensitive_arguments()
result: list[str] = []
skip_next = False
for i, arg in enumerate(argv):
if skip_next:
result.append(REDACTED_VALUE)
skip_next = False
continue
# Handle --flag=value syntax
if "=" in arg:
flag = arg.split("=", 1)[0]
if flag in sensitive:
result.append(f"{flag}={REDACTED_VALUE}")
continue
# Handle --flag value syntax
if arg in sensitive:
result.append(arg)
# Only redact the next token if it exists and is not another flag
if i + 1 < len(argv) and not argv[i + 1].startswith("-"):
skip_next = True
continue
result.append(arg)
return " ".join(result)
def warn_sensitive_argument_values(argv: list[str]) -> None:
"""Log a warning for each sensitive CLI flag that was passed with an explicit value.
Scans the raw argv list (not parsed args) to detect when users pass
secret values directly on the command line instead of using environment
variables. Handles both ``--flag value`` and ``--flag=value`` syntax.
Args:
argv: The argument list to check (typically ``sys.argv[1:]``).
"""
sensitive = get_sensitive_arguments()
if not sensitive:
return
use_color = "--no-color" not in argv
flags_with_values: list[str] = []
for i, arg in enumerate(argv):
# --flag=value syntax
if "=" in arg:
flag = arg.split("=", 1)[0]
if flag in sensitive:
flags_with_values.append(flag)
continue
# --flag value syntax
if arg in sensitive:
if i + 1 < len(argv) and not argv[i + 1].startswith("-"):
flags_with_values.append(arg)
for flag in flags_with_values:
if use_color:
logger.warning(
f"{Fore.YELLOW}{Style.BRIGHT}WARNING:{Style.RESET_ALL}{Fore.YELLOW} "
f"Passing a value directly to {flag} is not recommended. "
f"Use the corresponding environment variable instead to avoid "
f"exposing secrets in process listings and shell history.{Style.RESET_ALL}"
)
else:
logger.warning(
f"Passing a value directly to {flag} is not recommended. "
f"Use the corresponding environment variable instead to avoid "
f"exposing secrets in process listings and shell history."
)