| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Masks displayed values whose key looks sensitive (case-insensitive substring match against a keyword list: KEY, SECRET, TOKEN, PASSWORD, PASSWD, PWD, CREDENTIAL, AUTH, PRIVATE, ACCESS, CERT, DSN, CONNECTION_STRING, CONN_STRING - the convention used by mise-en-place, Airflow, and gitleaks). Values longer than 4 chars show first/last 2 chars with **** in between, values of 4 chars or fewer become **** entirely. Non-sensitive keys and None/unset values are left untouched. The transform is applied once to the values dict before the --format branch, so simple/shell/export/json output are all masked consistently.
|
Closing - this was a draft opened for internal review only, not an upstream contribution proposal. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
⚠️ Draft — not a contribution proposal
This is a draft PR opened for internal review only. It is not being proposed as an
official contribution to python-dotenv and is not ready to merge. Please do not review
or merge it as an upstream contribution.
What this adds
A -m/--mask flag on dotenv list that redacts values whose key looks sensitive,
so secrets don't get printed in plaintext by dotenv list (e.g. in a terminal recording,
CI log, or screen share).
Masking rule
Two independent pieces, both gated per-key:
match against a fixed keyword list: KEY, SECRET, TOKEN, PASSWORD, PASSWD,
PWD, CREDENTIAL, AUTH, PRIVATE, ACCESS, CERT, DSN, CONNECTION_STRING,
CONN_STRING. This is the same substring-match convention used by mise-en-place,
Apache Airflow's keyword-based masking, and gitleaks' keyword list — e.g. MY_API_KEY
matches on KEY, DB_PASSWORD matches on PASSWORD. A key that doesn't match prints
its value completely unchanged, even with --mask on.
key matched the heuristic:
MY_SECRET_KEY → MY****EY
None/unset values (a bare key with no =value in the .env file) are left untouched
either way, so --format=json's null output and the plain formats' existing
"skip if value is None" behavior are unchanged.
Format-agnostic by construction
The masking transform is applied once, to the values dict returned by
dotenv_values(stream=stream), immediately after that call and before the --format
branch in list_values (src/dotenv/cli.py). That means simple (default), json,
shell, and export output are all masked consistently — the transform isn't
duplicated per format branch.
Tests
Added to tests/test_cli.py, following the file's existing cli/dotenv_path fixture
and CliRunner-based style:
actually gates masking rather than masking everything (PORT=8080 prints unmasked).
key with no = at all) masks to ****.
the partial-reveal branch.
--file path.
sensitive and a non-sensitive key in the same file, so per-key gating is visible in
one result rather than only single-key cases.
Full suite: 266 passed, 1 skipped locally (plus 3 pre-existing failures in
test_run_with_invalid_cmd/test_run_with_version/test_run_with_command_flags that
reproduce identically on unmodified main — they're a macOS BSD-printenv environment
incompatibility, unrelated to this change). ruff check and mypy are clean on both
changed files.
CHANGELOG
Added an ## [Unreleased] / ### Added entry describing the sensitivity-gated behavior.