uttrflow / uttrflow/uttrflow-swift

AI suggestions saves one-time codes, card security codes and PINs typed into web forms, because only fields named "password", "passwd" or "passcode" count as secure

Open
#644 0 comments 0 reactions 0 assignees View on GitHub
area:ai-suggestions enhancement needs-info P0 security
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

When the master switch is on, capture runs in every application except the four editors that ship off and any the user has switched off (`Sources/UttrflowPredict/SuggestionPreferences.swift:22-27`, `:125-130`). Consent for an app is recorded as allowed automatically on first use (`Sources/Uttrflow/Suggestion/SuggestionCoordinator.swift:616`).

The app uses `.whereReturnSends` (`SuggestionCoordinator.swift:119`). Outside terminals and chat apps, that policy counts a field as finished when focus leaves it, the app is deactivated, or the line goes idle, not only on Return (`Sources/UttrflowPredictCapture/CommitPolicy.swift:24-33`; reasons at `CommitDetector.swift:29-37`). A finished value of 2 or more characters is written as plain text to `predict.v1.sqlite`. It is skipped only in these cases (`Sources/UttrflowPredictCapture/CaptureGate.swift:33-42`):

- the field is secure;
- the value matches the clipboard's secret shapes (`SecretShapes`);
- the value is a destructive command.

A field counts as secure only if one of these holds (`Sources/UttrflowPredict/SecureField.swift:11-26`):

- it publishes `AXSecureTextField`;
- its identifier, placeholder or description contains `password`, `passwd` or `passcode`;
- its value reads back as mask characters only.

A browser field for a one-time code, a card security code, a PIN, an account or card number without separators, a date of birth or a security answer usually meets none of these. Nothing in the app excludes password managers or banking apps by default either. #544 covers the separate problem that an app cannot be switched off before something has been learned there.

## Why it matters

Codes and PINs are among the most sensitive things typed, and a web form is where most of them are typed. Once stored, they sit in an unencrypted file and can be offered back as a suggestion in the same field. The person never pressed anything that looked like "save".

## Decision needed

1. Which field signals mark a field "never learn". Candidates include web `autocomplete` hints exposed through Accessibility (`one-time-code`, `cc-csc`, `cc-number`, `current-password`, `new-password`), `inputmode=numeric` with a short max length, and names or placeholders such as `otp`, `code`, `pin`, `cvv`, `cvc`, `security`, `ssn`.
2. Whether to refuse to learn short all-digit values anywhere outside terminals.
3. Whether to ship a default "never learn" list of app categories (password managers, banking), switched off like the four editors.

## Acceptance criteria

- The decision is written down in `Docs/predict.md` under what is never learned.
- `SecureField` or `CaptureGate` implements it, with table-driven tests in `Tests/UttrflowPredictTests` / `Tests/UttrflowPredictCaptureTests` covering each field shape above.
- The Settings copy for AI suggestions says what is never learned.

Contributor guide

Open the contributing guide

Research direction

Start with Sources/UttrflowPredict/SecureField.swift, Sources/UttrflowPredictCapture/CaptureGate.swift, and the related commit-policy files to trace how fields are classified and saved. Read Docs/predict.md and the Settings implementation, then inspect the test targets under Tests/UttrflowPredictTests and Tests/UttrflowPredictCaptureTests. Done means the decision is documented, the protection is implemented, table-driven tests cover the listed field shapes, and the AI suggestions Settings copy explains what is never learned.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
desktop, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.