Aug 26 - Update password detect against off field
CI / Python lint (flake8) (push) Has been cancelled
CI / Python syntax check (push) Has been cancelled
CI / Alembic migration chain (push) Has been cancelled
CI / JavaScript syntax check (push) Has been cancelled
CI / Pytest (push) Has been cancelled
CI / Build extension zip (push) Has been cancelled
CI / Python lint (flake8) (push) Has been cancelled
CI / Python syntax check (push) Has been cancelled
CI / Alembic migration chain (push) Has been cancelled
CI / JavaScript syntax check (push) Has been cancelled
CI / Pytest (push) Has been cancelled
CI / Build extension zip (push) Has been cancelled
This commit is contained in:
@@ -121,7 +121,9 @@ passkeeper/
|
||||
│ ├── test_registration_privacy.py # register does not disclose account existence
|
||||
│ ├── test_emergency_visibility.py # grantor sees requests + retrievals
|
||||
│ ├── test_deploy_config.py # nginx/gunicorn/systemd/extension packaging guards
|
||||
│ └── js/test_psl.js # PSL same-site matching (node, run in CI)
|
||||
│ └── js/
|
||||
│ ├── test_psl.js # PSL same-site matching (node, run in CI)
|
||||
│ └── test_field_heuristics.js # login-field detection predicates
|
||||
├── gunicorn.conf.py # worker class, timeouts, preload_app=False
|
||||
├── pytest.ini
|
||||
├── requirements-dev.txt
|
||||
@@ -618,7 +620,32 @@ In both `content.js` and `popup.js`. Prevents silent match failures for bare dom
|
||||
1. **YES:** `autocomplete="username|email|tel"`
|
||||
2. **NO:** non-credential autocomplete (`name`, `organization`, `search`, etc.)
|
||||
3. **YES:** `name/id/placeholder/aria-label` matches `user|email|mail|login|phone|tel|mobile|account`
|
||||
4. **Otherwise:** not decorated
|
||||
4. **Then:** `_hasPasswordSibling()` must also pass
|
||||
5. **Otherwise:** not decorated
|
||||
|
||||
**`autocomplete="off"` is NOT a negative signal** and must never be added back to
|
||||
`NON_CRED_AC`. Routers, banks and admin panels set it on login fields precisely
|
||||
to discourage password managers. It previously caused step 2 to reject fields as
|
||||
obvious as `<input id="login_username" placeholder="Username" autocomplete="off">`
|
||||
before step 3 ever ran (ASUS RT-AX88U admin login). Letting it fall through is
|
||||
safe — the field still needs a credential keyword AND a nearby password input.
|
||||
|
||||
### Credential capture without a `<form>`
|
||||
|
||||
Many login UIs never use a `<form>` — the ASUS router admin page submits with
|
||||
`<div class="button" onclick="preLogin();">Sign In</div>`, so no `submit` event
|
||||
is ever dispatched and the save-credentials banner never appeared.
|
||||
|
||||
`watchSubmissions()` therefore registers three triggers, all routed through
|
||||
`maybeCaptureCredentials(scope)`:
|
||||
|
||||
1. `submit` on any form (scope = the form)
|
||||
2. `click` on anything `_looksLikeSubmitControl()` accepts — `<button>`,
|
||||
`input[type=submit|button|image]`, `[role=button]`, any element with an
|
||||
inline `onclick`, or a button-ish class name (scope = document)
|
||||
3. `Enter` keydown inside a password or likely-username field (scope = document)
|
||||
|
||||
`_captureCooldown` (2 s) prevents two triggers double-prompting for one login.
|
||||
|
||||
### MutationObserver guard
|
||||
|
||||
@@ -663,6 +690,8 @@ Audit log details **never** contain plaintext item names, shared item names, or
|
||||
- `/register` must return the SAME body and status for new and existing addresses, and hash on both paths — returning early on duplicate reinstates a timing oracle
|
||||
- Never return `str(e)` from exception handlers — log with `_log.exception(...)` and return a generic user-facing message to avoid leaking DB schema details or query fragments
|
||||
- `extension/shared/psl.js` is GENERATED — never hand-edit; run `python scripts/update_psl.py`. It must load BEFORE content.js / popup.js / background.js in every manifest
|
||||
- Never add `off` back to `NON_CRED_AC` in `content.js` — `tests/js/test_field_heuristics.js` fails the build if you do
|
||||
- Login detection must not assume a `<form>` exists; route new capture triggers through `maybeCaptureCredentials()`
|
||||
- Never reintroduce `endsWith("." + host)` host matching anywhere in the extension — `tests/test_deploy_config.py` fails the build if it reappears
|
||||
- nginx rate zones: mind `r/s` vs `r/m`. `api_limit` was `60r/m` (1 req/s for the whole API) and caused spurious 429s on normal vault use
|
||||
- `preload_app` must stay `False` in `gunicorn.conf.py` — APScheduler's thread does not survive `fork()`, so `--preload` silently disables the cleanup job
|
||||
|
||||
Reference in New Issue
Block a user