Skip to content

Add local-2fa extension#28429

Open
vayaSEO wants to merge 4 commits into
raycast:mainfrom
vayaSEO:ext/local-2fa
Open

Add local-2fa extension#28429
vayaSEO wants to merge 4 commits into
raycast:mainfrom
vayaSEO:ext/local-2fa

Conversation

@vayaSEO
Copy link
Copy Markdown

@vayaSEO vayaSEO commented May 30, 2026

Description

Local 2FA Codes — fully offline, local-first 2FA TOTP code generator for Raycast on macOS.

What it does

  • Generates RFC 6238 TOTP codes (SHA1 / SHA256 / SHA512, 6 or 8 digits, configurable period)
  • Stores accounts locally, encrypted with AES-256-GCM + PBKDF2-SHA256 (600,000 iterations, OWASP 2023)
  • Master password kept in Raycast password preference (macOS Keychain)

Commands

  • List Codes — view, copy, paste, delete accounts
  • Add Account — unified flow: paste otpauth:// URL with autofill, or fill manually
  • Import Google Migration — paste otpauth-migration://... URLs
  • Import from QR Image — select local PNG QR images (decoded in pure JS via qr + pngjs)

Why a new extension

No existing Raycast extension offers fully offline TOTP with local encrypted storage, otpauth URL + Google Authenticator migration + QR image import in one place. All competing extensions rely on cloud services or external password managers.

Security

  • AES-256-GCM authenticated encryption, random 16-byte salt + 12-byte IV per save
  • PBKDF2-SHA256 600k iterations (transparent backward-compat with legacy 210k vaults)
  • In-process write mutex prevents concurrent-write races
  • Input caps on Base32 / otpauth / migration parsers to prevent DoS
  • Generic crypto errors (no leaks)
  • Clipboard.copy uses concealed: true
  • No network calls. No external binaries. No child_process.

Full threat model in SECURITY.md.

Tests

19 unit tests covering TOTP RFC 6238 vectors, parseOtpauthUrl edge cases, parseGoogleMigrationUrl edge cases, and decodeBase32 bounds. Run with npm test.

Screencast

Screenshots are included in extensions/local-2fa/metadata/ (6 images at 2000×1250).

Checklist

  • I read the extension guidelines
  • I read the documentation about publishing
  • I ran npm run build and tested this distribution build in Raycast
  • I checked that files in the assets folder are used by the extension itself
  • I checked that assets used by the README are placed outside of the metadata folder

- chore: prepare for Raycast Store submission
- docs: consolidate CHANGELOG for v1.0.0 first public release
- chore: initial public release prep (v1.0.0)
@raycastbot raycastbot added new extension Label for PRs with new extensions platform: macOS labels May 30, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@vayaSEO vayaSEO marked this pull request as ready for review May 30, 2026 02:04
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Greptile Summary

Adds a new fully-offline, local-first 2FA TOTP extension for Raycast, with AES-256-GCM encrypted storage, four commands (list, add, Google migration import, QR image import), and 19 unit tests covering RFC 6238 vectors and parser edge cases.

  • google-migration.ts: Algorithm enum mapping corrected — value === 2 now resolves to \"SHA256\" (was \"SHA1\" in an earlier revision); default algorithm field correctly initialises to 1 (SHA1); unsupported entries (e.g., SHA384) are skipped rather than aborting the whole import.
  • storage.ts: AES-256-GCM vault with PBKDF2-SHA256 (600 k iterations), forward/backward-compatible v1/v2 payload format, and an in-process promise mutex preventing concurrent-write races.
  • package.json: Categorised as \"Security\", $schema present, all listed dependencies verified as used in source.

Confidence Score: 4/5

New security-focused extension with crypto-heavy storage and a custom protobuf parser — the algorithm mapping bug from the previous review round is fixed, but the crypto and serialization paths warrant a careful second read before merge.

The previously flagged algorithm mapping error (SHA256 silently resolving to SHA1) is corrected in this revision and the test suite now validates the fixed mapping. The custom protobuf parser, AES-GCM vault, and PBKDF2 key derivation are all non-trivial crypto paths that benefit from an extra set of eyes, but no new defects were found in this pass.

extensions/local-2fa/src/storage.ts and extensions/local-2fa/src/google-migration.ts contain the most sensitive logic and are worth a focused read.

Important Files Changed

Filename Overview
extensions/local-2fa/src/google-migration.ts Custom protobuf parser for Google Authenticator migration format; algorithm enum mapping corrected (SHA256=2, SHA512=4), unsupported entries now skipped gracefully, input caps in place.
extensions/local-2fa/src/storage.ts AES-256-GCM encrypted local storage with PBKDF2-SHA256 key derivation; write serialization mutex, backward-compat v1/v2 vault support, and a key cache on the read path.
extensions/local-2fa/src/totp.ts RFC 6238 TOTP implementation with Base32 decode, HMAC-based OTP, and otpauth URL parser; input validation and length caps throughout.
extensions/local-2fa/src/list-codes.tsx Main list view; updates every second, copies with concealed:true, delete confirmation in place, correct use of sorted/memoized accounts.
extensions/local-2fa/src/import-from-qr-image.tsx PNG QR decoder using pure-JS pngjs + qr; supports both otpauth and otpauth-migration payloads, with clear error messages.
extensions/local-2fa/package.json Correct Security category, $schema present, macOS platform, all four dependencies verified as used in source files.
extensions/local-2fa/src/google-migration.test.ts Tests now correctly assert SHA256 for enum value 2, cover mixed-payload (valid + unsupported), HOTP filtering, and edge cases.

Reviews (4): Last reviewed commit: "fix: async PBKDF2 in storage to avoid UI..." | Re-trigger Greptile

Comment thread extensions/local-2fa/package.json
Comment thread extensions/local-2fa/eslint.config.js Outdated
Comment thread extensions/local-2fa/CHANGELOG.md Outdated
@vayaSEO
Copy link
Copy Markdown
Author

vayaSEO commented May 30, 2026

Addressed in 5bc575e: algorithm mapping fixed (1=SHA1, 2=SHA256, 4=SHA512, 3=SHA384 unsupported), default algorithm changed to 1, category set to Security, ESLint config wrapped with defineConfig, CHANGELOG header pdated to [Initial Release].

Comment thread extensions/local-2fa/src/google-migration.ts
Comment thread extensions/local-2fa/src/storage.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new extension Label for PRs with new extensions platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants