mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-16 16:34:24 +00:00
114 lines
3.8 KiB
Python
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."
|
|
)
|