[Bug]: macOS browser import reports inaccessible encryption keys as missing
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 28/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- macos, rust, typescript
Direzione di ricerca
Start with readKeychainSecret and the falsy-secret branch in apps/desktop/src/preview/BrowserImport/ChromiumKeys.ts, then the denial fixture in ChromiumKeys.test.ts. The root cause sits in the pinned @napi-rs/keyring 1.3.0 dependency (pnpm-lock.yaml), which converts native read errors to absent values, so the fix likely needs a dependency decision as well as code. Done means an access failure yields needsKeychainApproval, a missing key still yields keychainItemMissing, and a successful read is unchanged.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
When a macOS browser encryption-key read fails, browser import reports that the key does not exist and tells the user to sign in to the source browser again. An existing key that could not be read should retain its access failure so the user receives the appropriate approval or keyring error. A source trace through the exact pinned native binding establishes that it discards the failure before the application's error handler can see it; no real Keychain access was performed.
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Credentials, private paths, and sensitive data were excluded from this report.
Area
apps/desktop
Observed behavior
Source-only finding: the supported Chromium browser-import path on macOS calls AsyncEntry.getPassword(), but the resolved @napi-rs/keyring 1.3.0 implementation converts every native read error into an absent optional value. For an existing key whose platform read fails with an access error, T3 therefore takes the falsy-secret branch and produces keychainItemMissing, rather than taking the catch branch that produces needsKeychainApproval. The import error preserves that reason through ChromiumCookieReadError and BrowserImportFailedError, selecting the missing-key instruction to sign in to the source browser again.
Reproduction
- Inspect the desktop dependency resolution at the stated commit: pnpm-lock.yaml resolves @napi-rs/keyring to 1.3.0.
- Follow Settings → Browser → Browser profiles → Add profile → Import from a Chromium browser into BrowserImport.importCookies, readChromiumCookies, resolveChromiumKeys with platform darwin, and readKeychainSecret.
- Follow the published package's npm gitHead to PasswordTask.compute. For a platform result Err(NoStorageAccess), the .ok() conversion yields None and the N-API task resolves successfully with an absent value; it does not reject.
- Follow that value into readKeychainSecret: the catch handler is bypassed and the falsy-secret branch emits keychainItemMissing. Compare this with the rejected-promise denial fixture in ChromiumKeys.test.ts, which never models the pinned wrapper's error-erasing behavior.
These are source-inspection steps, not a native reproduction. The conversion is unconditional for any native read error. NOT_ENOUGH_INFO: the frequency of macOS users hitting native access failures was not measured; a disposable macOS account with a synthetic item and denied access would establish a live incident without exposing real credentials.
Reproduction script: NOT_ENOUGH_INFO — no native Keychain lookup was run, and there is no public dependency hook for injecting a native credential-store result. This report supplies the exact source path; a disposable macOS account or a native binding fixture would permit an executable end-to-end check.
Expected behavior
An inaccessible existing browser key must remain distinguishable from an absent key. T3 already represents these outcomes separately: its rejected-read handler produces needsKeychainApproval, and its missing-result handler produces keychainItemMissing in apps/desktop/src/preview/BrowserImport/ChromiumKeys.ts#L62-L75. The distinct user guidance is defined in packages/contracts/src/browserImport.ts#L79-L94, and apps/desktop/src/preview/BrowserImport/ChromiumKeys.test.ts#L114-L123 expects an access denial to retain the approval reason and original cause.
The pinned AsyncEntry declaration also documents missing and ambiguous results separately. The dependency's later released src/result.rs#L3-L16 preserves this distinction, mapping only NoEntry to absence and propagating other errors.
Impact and scope
Form impact: Minor bug or occasional failure.
Impact: P2 - Native read failures lose their cause and select an incorrect recovery instruction during macOS Chromium session import. The operation fails safely without importing cookies, but users are sent to source-browser sign-in instead of the actual access problem.
The source path is shared by the supported macOS Chromium browsers. Successful reads and genuinely missing keys are unaffected by this finding. Linux uses the separate libsecret helper and is outside this defect. NOT_ENOUGH_INFO: no native prompt was denied in this investigation, and no practical recovery procedure was exercised; those require a disposable macOS account with synthetic credentials.
Version
T3 Code commit 59e64eef881632a23f89c4138bcf37f23d92bf93. The desktop pnpm-lock.yaml#L434-L436 resolves @napi-rs/keyring 1.3.0. Its published npm metadata identifies gitHead e46be75c3ba8d5fde6b88a17c6153b87ffe4b946. No keyring patch exists in this checkout's patches directory. No dependency or installed application was changed.
Runtime and platform
Affects the desktop macOS Chromium import branch. Inspection ran on macOS arm64. No native keyring method, browser-secret executable, real credential, or Keychain item was accessed. NOT_ENOUGH_INFO: no affected packaged application's macOS version or architecture-specific native run was established; this is a source-only report against the pinned dependency and application code.
Interface
UI: desktop browser profile session import, backed by the @napi-rs/keyring AsyncEntry library API.
Earliest failure stage
Integration or transport: the native binding erases the credential-store read error before returning to TypeScript.
Relevant output or evidence
The exact dependency implementation is src/async_entry.rs#L247-L258. Its PasswordTask.compute contains:
fn compute(&mut self) -> Result<Self::Output> {
Ok(self.inner.get_password().ok())
}
Thus Err(NoStorageAccess), Err(PlatformFailure), and Err(NoEntry) all become a successful absent optional result. The subsequent T3 read mapping cannot recover the discarded cause. ChromiumCookies.ts#L280-L289 and BrowserImport.ts#L316-L323 preserve the resulting missing-key reason to the import boundary.
The upstream Apple backend's keychain.rs#L360-L373 distinguishes item-not-found from access errors. The wrapper removes that distinction. Evidence provenance: static. Local verification: static-proof. Reproduction completeness: incomplete for a native macOS incident; complete for the conditional source path from a native read error to the incorrect application reason.
Expected outcome or recovery
For a native access-denied result, import reports an access/approval failure rather than claiming the key is absent. A genuinely missing key retains missing-key guidance, and a successful read still derives the same cookie key. A check of the released integration must exercise those three native outcomes, not just a JavaScript promise mock that rejects even though the pinned native implementation resolves.
Additional context
- https://github.com/Brooooooklyn/keyring-node/pull/136 — reports and fixes this exact dependency error-erasure behavior; the discussion identifies its release in 2.0.0. The latest published 2.1.2 source also preserves non-missing errors, while this T3 checkout still resolves 1.3.0.
- https://github.com/pingdotgg/t3code/pull/23157 — switched this T3 path to AsyncEntry and added resolved-undefined and rejected-denial mocks; its stated untested cases include denial on the async branch. Responsiveness is a separate contract from preserving native failure reasons.
- https://github.com/pingdotgg/t3code/issues/29234 — concerns Linux KWallet attribute lookup rather than macOS native read-error translation; its remedy does not cover this path.
- Lingua principale
- TypeScript
- Stelle
- 24.8k
- Fork
- 6.4k
- Merge medio
- 59m
- PR unite (30g)
- 418
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di pingdotgg/t3code
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
via-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 Mezza giornata Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
Question card options show LaTeX as raw source, though the question text renders itForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: Settings inheritance popover shows raw slugs for branch naming, default permissions and response streamingForse già presa @juliusmarminge l’ha presa 1 giorno fa. Apertavouch:denounced
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di pingdotgg/t3code
Issue simili
-
bug platform:mobile root-cause:found
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
openchamber/openchamber#6926 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
push-based/user-flow#356 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
Cygnux-Labs/Tracekit#827 ·
I maintainer di solito rispondono entro 1 giorno
-
www build: a refused import shows only "ENOENT scandir <outDir>", never the build-audience errorApertakind:defect
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 91/100
I maintainer di solito rispondono entro 1 giorno
-
type:bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
nightgauge/nightgauge#3266 ·
I maintainer di solito rispondono entro 1 giorno