Omahub
← All plugins
Y

OmaFob

by Yogesh Ojha

TOTP codes in the bar. Import every account from Google Authenticator in one scan.

Security review

Review recommended · 5 findings

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
b0c93c4
Scanned
1 month ago
  • medium eval twofa/cli.py:166

    Shell sources dynamically generated content.

    . /dev/video0")
  • medium package_manager …/workflows/ci.yml:49

    System package manager operation.

    apt-get install -y gnupg
  • medium package_manager …/workflows/ci.yml:28

    System-wide Python package installation (not --user).

    pip install ruff==0.15.0
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo apt-get install -y gnupg
  • Docs sudo README.md:26

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo pacman -S --needed gnupg wl-clipboard zbar grim slurp

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
b0c93c4
Reviewed
1 month ago

OmaFob is a carefully written local TOTP manager: secrets are stored in a gpg-encrypted vault, passphrases are passed to gpg via a file descriptor, subprocess calls use fixed argument lists, and no network access is present. The deterministic "medium" rating is driven by CI/README package-manager commands and a false-positive shell-source match on an argparse help string, none of which execute during plugin installation or normal runtime. The remaining risk is the inherent exposure of 2FA secrets to a per-user, unsandboxed process, especially with auto-lock defaulting to off.

  • The flagged package-manager/sudo operations are in .github/workflows/ci.yml and README.md (CI dependencies and user-invoked dependency installation), not in plugin install or runtime code.
  • The flagged cli.py "shell sources" finding is a false positive: the matched text is the argparse help string "video device, e.g. /dev/video0", not a shell command.
  • Inherent design consideration: the vault stays unlocked by default (auto-lock "Never") and the helper runs as the user; users in shared or screen-shared environments should enable auto-lock and privacy mode.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/yogeshojha/omafob --enable
Productivity #system #security

OmaFob

Two-factor codes in the Omarchy bar. Import every account from Google Authenticator in one scan.

The OmaFob panel

Not a login guard for Omarchy. It replaces the authenticator app on your phone. Omarchy only.

Keybind, type gh, Enter. The code is on your clipboard, wiped 30 seconds later.

Why

When I am doing research work I keep my phone out of the room. It sits in the bedroom, and every code meant getting up to fetch it. So I built this.

Install

omarchy plugin add https://github.com/yogeshojha/omafob.git --enable
sudo pacman -S --needed gnupg wl-clipboard zbar grim slurp

Keybind, in ~/.config/hypr/bindings.conf:

bindd = SUPER SHIFT, O, OmaFob, exec, omarchy-shell yogeshojha.omafob toggle

Import

Google Authenticator: ⋮ → Transfer accounts → Export accounts. One QR holds every account you pick.

  • Camera: Ctrl+W, hold the phone up to the webcam.
  • Screen: Ctrl+I, drag a box over the QR.
  • Paste: an otpauth:// link, or a path to a QR image.

Re-importing the same export is safe. Accounts already stored are skipped.

Keys

Key
any letter filter the list
Enter copy the selected code
↑ ↓ move
Backspace / Ctrl+U edit or clear the filter
Del remove an account
Ctrl+I scan the screen
Ctrl+W scan from the camera
Ctrl+S settings
Ctrl+L lock
Esc clear the filter, then close

Letters go to the filter.

Settings

Ctrl+S, or Setup > Plugins.

Privacy mode codes stay masked in the panel, default off
Countdown ring ring around the bar icon, default off
Clear clipboard after default 30 seconds
Auto-lock vault default off
Group digits 418 293 instead of 418293

Privacy mode shows every account as ••• ••• and never reveals a code. Enter still copies. For screen sharing and open offices.

Privacy mode

Security

  • Vault: gpg --symmetric, AES-256, SHA-512, at ~/.local/share/omafob/vault.gpg, mode 0600 in a 0700 directory.
  • The passphrase reaches gpg on its own fd, never argv. --no-symkey-cache.
  • The helper holds the secrets. The shell receives codes and expiry times.
  • Copies use wl-copy --sensitive. Codes stay out of clipboard history.
  • QR images are never written to disk. grim pipes into zbar, the camera is decoded inside the helper. There is no camera preview.
  • Children carry PR_SET_PDEATHSIG. A killed helper releases the camera.
  • Deleting an account deletes vault.gpg.previous with it.

Plugins run unsandboxed inside omarchy-shell, and the helper runs as you. While the vault is unlocked, anything running as your user can ask it for codes. The encryption covers the vault at rest.

HOTP

Counter-based accounts import and show a COUNTER tag. Codes for them are not generated yet.

Command line

ln -s ~/.config/omarchy/plugins/yogeshojha.omafob/omafob ~/.local/bin/omafob
omafob status                   # where the vault is
omafob list                     # stored accounts
omafob code github              # one code
omafob scan                     # import from the screen
omafob camera                   # import from the webcam
omafob add <link-or-image>      # import a link or QR image
omafob remove github            # delete an account
omafob passwd                   # change the passphrase

--vault <path> for a vault elsewhere.

Development

python3 test/test_twofa.py
python3 test/test_security.py
ruff check .
qmllint -I /usr/share/omarchy/shell *.qml
omarchy plugin validate .

Panel.qml holds the views and the keyboard model, BarSlot.qml the bar item, AccountRow.qml a row, VaultController.qml the helper process and the countdown, Model.js the pure helpers, twofa/ the helper.

The helper speaks line-delimited JSON on stdin. Each request carries a seq that comes back on the reply. Account ids go in id.

Saving under ~/.config/omarchy/plugins/ reloads the shell and re-locks the vault. A QML compile error is cached; run omarchy-restart-shell after fixing one.

Remove

omarchy plugin remove yogeshojha.omafob

The vault stays. rm -rf ~/.local/share/omafob removes it too.

MIT