Skip to content

Prevent secret leakage#1103

Draft
mxsrc wants to merge 4 commits into
mainfrom
prevent-secret-leakage
Draft

Prevent secret leakage#1103
mxsrc wants to merge 4 commits into
mainfrom
prevent-secret-leakage

Conversation

@mxsrc

@mxsrc mxsrc commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

The extensive logging done throughout the application may inadvertently leak confidential data. This PR aims to mitigate this, preventing secrets to be present in the logs.

The core tool in this PR is the use of pydantic's SecretStr/SecretBytes. They are a simple wrapper around str/bytes, that, when converted to string yield a redacted string (**********). The actual value needs to be explicitly unwrapped via get_secret_value().

This changeset introduces:

  • support for using fields of the secret type in models
  • unwrapping of secret values in the clients, s.t. the secret values are correctly unwrapped before transmitting them
  • Entrypoints in CLI/API wrap confidential values as soon as possible

What htis PR notably does not do, is prevent explicit leakage through endpoints that currently allow access to the confidential values. Handling that in a better way is left as a follow-up.

Comment thread simplyblock_cli/cli.py Fixed
Comment thread simplyblock_core/cluster_ops.py Fixed
Comment thread simplyblock_core/cluster_ops.py Fixed
Comment thread simplyblock_core/utils/secrets.py Fixed
Comment thread simplyblock_core/utils/secrets.py Fixed
mxsrc added 4 commits June 17, 2026 17:03
RPCClient, SNodeClient, mgmt_node_ops, and the Grafana/Graylog
helpers in cluster_ops now accept SecretStr-typed credentials so
payload dicts and model objects can be logged at DEBUG without
leaking the value (SecretStr masks in repr/str/dict-repr). Secrets
are unwrapped only at the wire-send site via the shared helper
``unwrap_secrets_for_send``.

Response bodies are gated behind a new ``SB_LOG_RESPONSE_BODIES``
setting (default off). The previous wholesale ``response.text`` /
``response.content`` logging at DEBUG is the leak vector here:
responses are untyped, so there is no equivalent of SecretStr
masking once a body is in hand. Drop the body from exception
messages too — keep the status code, hide the text.
@mxsrc mxsrc force-pushed the prevent-secret-leakage branch from e11b049 to 97d1167 Compare June 17, 2026 15:10

default_cluster = None
monitoring_secret = os.environ.get("MONITORING_SECRET", "")
monitoring_secret = SecretStr(os.environ.get("MONITORING_SECRET", ""))
db_controller = DBController()

def _create_update_user(cluster_id, grafana_url, grafana_secret, user_secret, update_secret=False):
def _create_update_user(cluster_id, grafana_url, grafana_secret: SecretStr, user_secret: SecretStr, update_secret=False):
from pydantic import SecretBytes, SecretStr


def unwrap_secrets_for_send(obj: Any) -> Any:
return obj


def unwrap_secret(value: Union[SecretStr, str, None]) -> Optional[str]:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant