A Safari extension for the pass standard Unix password manager.
- Manage your pass password store from Safari
- Create / update / delete entries
- Auto-suggest passwords based on the current URL
- Support for TOTP/OTP codes
- Integrated password generator
- Sync the store with git
- Secure architecture with minimal permissions
- Simple file-based communication between extension and app
Suggestions for the current URL
- macOS 11.0 or later
- Xcode 13.0 or later (for building)
- pass password manager installed and configured
- pass-otp extension
-
Clone the repository:
git clone https://github.com/yourusername/pass-safari.git cd pass-safari -
Open the project in Xcode:
open pass-safari.xcodeproj
-
Build and run the project (⌘R)
-
Enable the extension in Safari:
- Safari → Preferences → Extensions
- Enable "pass-safari Extension"
The extension uses a simple, proven approach with files in the bundle's cache directory:
~/Library/Group Containers/group.de.zisoft.pass-safari/Library/Caches/pass-safari
├── PassRequest-*.plist # Request files from extension
├── PassResponse-*.plist # Response files from app
├── URLIndexCache.json # Cached URL mappings
└── URLIndexRefresh.lock # Lock file for index refresh
- Extension is sandboxed - Can only access app group directory
- App is NOT sandboxed - Can execute the
passexecutable without issues - Works reliably - Standard approach used by many Safari extensions
-
Safari Extension (
pass-safari Extension)- Runs in Safari's sandboxed environment
- Lists password entries
- Manages UI and user interactions
- Creates pass request files in the app group cache directory
-
Companion App (
pass-safari)- Runs WITHOUT sandbox (needs to execute
pass) - Executes pass commands
- Generates OTP codes
- Writes pass response files to the app group cache directory
- Runs WITHOUT sandbox (needs to execute
Safari Extension → PassRequest-*.plist (in the app group cache directory)
↓
Companion App reads request
↓
Executes: pass executable to perform the required action
↓
Companion App → PassResponse-*.plist (in the app group cache directory)
↓
Safari Extension reads response → Displays result
- Launch the pass-safari app
- Navigate to a website
- Click the pass-safari extension icon
- Click on a password entry from the list
- The password is automatically filled
The extension automatically suggests passwords based on:
- Exact hostname matches
- Subdomain matches
- URL fields in password entries
For quick access, a URLIndexCache.json file is created in the app group container cache directory ~/Library/Group Containers/group.de.zisoft.pass-safari/Library/Caches/pass-safari. On the first run this may take some time, so please be patient. On subsequent runs only the changed entries are used to update the cache file, which is much faster. All fields from the password entries starting with one of:
urlwebsitesite
are stored in the cache. So you can easily use multiple URLs in one password entry like url:, url2:, etc.
- Extension runs in macOS App Sandbox with minimal permissions
- Communication via simple files in
~/Library/Group Containers/group.de.zisoft.pass-safari/Library/Caches/pass-safari - No network access required
- No telemetry or tracking
pass-safari/
├── pass-safari/ # Companion app (NOT sandboxed)
│ ├── AppDelegate.swift # App lifecycle & pass execution
│ ├── ViewController.swift # UI
│ └── pass-safari.entitlements # AppGroup
├── pass-safari Extension/ # Safari extension (sandboxed)
│ ├── SafariWebExtensionHandler.swift # Native messaging
│ ├── pass-safari Extension.entitlements # AppGroup, ReadOnly access to `~/.password-store`
│ └── Resources/
│ ├── popup.html # Extension UI
│ ├── popup.js # Extension logic
│ └── background.js # Background tasks
└── pass-safari.xcodeproj/ # Xcode project
SafariWebExtensionHandler.swift- Handles messages from JavaScriptAppDelegate.swift- Executes pass commandspopup.js- Extension UI logic and user interactions
Extension (pass-safari Extension.entitlements):
com.apple.security.app-sandbox- Required for Safari extensionscom.apple.security.temporary-exception.files.home-relative-path.read-only- Read password store
Companion App (pass-safari.entitlements):
- Empty! No sandbox, so it can execute
passexecutable
The app looks for pass in:
/opt/homebrew/bin/pass/usr/local/bin/pass/usr/bin/pass/bin/pass- Or via
which passin your PATH
Make sure pass is installed and properly set up.
Check Console.app and filter by "pass-safari" for detailed logs.
MIT — see LICENSE.
- Built for pass by Jason A. Donenfeld
- Password generator by Dania Usman



