fix: never log the OTP code value (secret-in-logs); correct false test claim (v0.1.5)
M-1: retrieve.py logged the live single-use code at INFO ('found code %s', 'code %s
skipped too old'), shipping the secret to any aggregation/retention sink the host wires
(our /srv/logs -> loki/grafana path). drop the code value from both lines — log that a
code was found/retrieved and where, never the value. also truncate the oauth token-endpoint
error body to 200 chars so a token response can't be dumped whole.
aiomail-F3: CLAUDE.md claimed an '8-case tested' suite that does not exist in the repo;
corrected to describe the manual throwaway-venv exercise + the real flake8 check.
verified by execution: code retrieved, value absent from logs; control confirms the old
line carried it.
Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
parent
0cf23805dd
commit
f940641a5a
10
README.md
10
README.md
@ -11,22 +11,22 @@ This reads codes from email; it does not generate them (that is `pyotp`'s job).
|
||||
`requirements.txt`:
|
||||
|
||||
```
|
||||
aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.4
|
||||
aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.5
|
||||
# OAuth token providers (Microsoft / Google) need the extra:
|
||||
aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.4
|
||||
aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.5
|
||||
```
|
||||
|
||||
Direct:
|
||||
|
||||
```bash
|
||||
pip install "aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.4"
|
||||
pip install "aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.4"
|
||||
pip install "aiomail @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.5"
|
||||
pip install "aiomail[oauth] @ git+ssh://git@git.rethinkstudios.io/rethink-public/aiomail.git@v0.1.5"
|
||||
```
|
||||
|
||||
Requires `aioimaplib` and `beautifulsoup4` (pulled transitively). The `oauth`
|
||||
extra adds `aiohttp` for the refresh-token providers.
|
||||
|
||||
Drop the `@v0.1.4` suffix from the line above to install the latest unpinned.
|
||||
Drop the `@v0.1.5` suffix from the line above to install the latest unpinned.
|
||||
|
||||
## Password auth
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "aiomail"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
description = "async IMAP one-time-code retrieval with password/OAuth2 auth and dynamic matching"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
|
||||
@ -29,4 +29,4 @@ __all__ = [
|
||||
"DEFAULT_FOLDERS",
|
||||
]
|
||||
|
||||
__version__ = "0.1.4"
|
||||
__version__ = "0.1.5"
|
||||
|
||||
@ -81,7 +81,9 @@ class _RefreshTokenProvider:
|
||||
self._failures = 0
|
||||
return token
|
||||
else:
|
||||
body = await resp.text()
|
||||
# log a truncated error body only — a token-endpoint
|
||||
# response can carry sensitive material; never dump it whole
|
||||
body = (await resp.text())[:200]
|
||||
log.warning("token endpoint %s -> %s: %s", endpoint, resp.status, body)
|
||||
except Exception as exc:
|
||||
log.warning("token request to %s failed: %s", endpoint, exc)
|
||||
|
||||
@ -113,12 +113,14 @@ async def retrieve_otp(
|
||||
if max_age is not None:
|
||||
age = _age_seconds(message)
|
||||
if age is not None and age > max_age:
|
||||
log.info("code %s skipped, too old (%.0fs > %.0fs)", code, age, max_age)
|
||||
log.info("code skipped, too old (%.0fs > %.0fs)", age, max_age)
|
||||
continue
|
||||
|
||||
if mark_seen:
|
||||
await client.mark_seen(email_id)
|
||||
log.info("found code %s in %s", code, folder)
|
||||
# never log the code value — it's a live single-use secret that would
|
||||
# reach any aggregation/retention sink the host wires up
|
||||
log.info("found code in %s", folder)
|
||||
return code
|
||||
|
||||
if attempt < retries:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user