
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@kdbx/pak-lib
Advanced tools
PAK (Password Age Kit) - A simple, secure password manager in JavaScript using age encryption.
📦 Package Moved: This package has been renamed from
@kdbx/pak-libto@kdbx/pak. Please update your installations to use the new package name. See https://www.npmjs.com/package/@kdbx/pak
A simple, secure password manager in JavaScript using age encryption. This is a TypeScript port of the shell script from https://github.com/tonidy/pa-cli, providing cross-platform compatibility and modern features.
npm install -g @kdbx/pak-lib
Or use directly with npx:
npx @kdbx/pak-lib --help
Note: Both
paandpakcommands are available after installation.
# Add a password (will prompt to generate or enter manually)
pa add mysite
# Show a password
pa show mysite
# List all passwords
pa list
# Edit a password with your $EDITOR
pa edit mysite
# Delete a password
pa del mysite
# Search passwords with fzf
pa find
# Search and perform action
pa find show # or edit, del
# Git operations
pa git log
pa git status
# Version information
pa version
# Secure Enclave information (macOS only)
pa se-info
# Convert recipients between formats
pa convert age1se1qfn44rsw... yubikey
pa convert age1yubikey1qfn44rsw... se
PAK provides comprehensive support for Apple's Secure Enclave through age-plugin-se, offering hardware-backed encryption with biometric authentication.
# Install age-plugin-se
brew install age-plugin-se
# Verify installation
pa se-info
# Auto-select access control (non-interactive)
export PA_SE_ACCESS_CONTROL=any-biometry-or-passcode
# Auto-confirm Secure Enclave usage (non-interactive)
export PA_SE_AUTO_CONFIRM=1
# Check Secure Enclave support
pa se-info
# Generate identity with custom access control
PA_SE_ACCESS_CONTROL=any-biometry pa add mysite
# Convert between plugin formats
pa convert age1se1qfn44rsw0xvmez3pky46nghmnd5up0jpj97nd39zptlh83a0nja6skde3ak yubikey
# Output: age1yubikey1qfn44rsw0xvmez3pky46nghmnd5up0jpj97nd39zptlh83a0nja6skde3ak
# Use converted recipient for encryption on systems without age-plugin-se
echo "secret" | age -r age1yubikey1qfn44rsw0xvmez3pky46nghmnd5up0jpj97nd39zptlh83a0nja6skde3ak
Use the SE integration programmatically:
const { AgeManager, AppleSecureEnclave } = require('@kdbx/pak-lib');
// Initialize with SE support
const config = {
useAgeBinary: false, // Use native SE integration
seAccessControl: 'any-biometry-or-passcode'
};
const ageManager = new AgeManager(config);
// Check SE availability
const isAvailable = await ageManager.isSecureEnclaveAvailable();
// Generate SE identity
const identity = await ageManager.generateSecureEnclaveIdentity('any-biometry');
// Use direct SE module
const secureEnclave = new AppleSecureEnclave({
accessControl: 'any-biometry-or-passcode',
recipientType: 'piv-p256',
useNative: true
});
const keyPair = await secureEnclave.generateKeyPair('any-biometry');
const capabilities = await secureEnclave.getCapabilities();
PAK can be configured through environment variables, a config.json file, or programmatically.
Configure the password manager behavior with these environment variables:
# Data directory (default: ~/.local/share/pa)
export PA_DIR=~/.local/share/pa
# Default password length (default: 50)
export PA_LENGTH=50
# Password character pattern (default: A-Za-z0-9-_)
export PA_PATTERN=A-Za-z0-9-_
# Disable git tracking
export PA_NOGIT=1
# Disable system credential storage
export PA_NO_KEYRING=1
# Editor command (default: vi)
export EDITOR=nano
# Force age binary usage (instead of JS library)
export PA_USE_AGE_BINARY=1
# Custom age binary path
export PA_AGE_BINARY_PATH=/opt/homebrew/bin/age
# Secure Enclave access control
export PA_SE_ACCESS_CONTROL=any-biometry-or-passcode
# Auto-confirm Secure Enclave usage
export PA_SE_AUTO_CONFIRM=1
Create a config.json file in your working directory:
{
"paDir": "~/.local/share/pa",
"paLength": 50,
"paPattern": "A-Za-z0-9-_",
"paNoGit": false,
"paNoKeyring": false,
"editor": "vi",
"useAgeBinary": true,
"ageBinaryPath": "/opt/homebrew/bin/age",
"seAccessControl": "any-biometry-or-passcode",
"seAutoConfirm": false
}
Configuration is applied in this order (highest priority first):
config.json filePAK supports two age encryption backends:
The age binary is automatically used when:
useAgeBinary: true is set in configPA_USE_AGE_BINARY=1 environment variable is set# Force age binary usage for full plugin support
export PA_USE_AGE_BINARY=1
pa add mysite # Will use age binary with Touch ID support
The pure JavaScript implementation has some limitations when working with CLI-generated identities:
age or age-plugin-se command-line toolsCompatible combinations:
Incompatible combinations:
# Example: Using CLI-generated identity with useAgeBinary=false
# This will show fallback message but still work correctly
export PA_USE_AGE_BINARY=0
pa show mysite # Shows: "SE native decryption failed, falling back to CLI"
~/.local/share/pa/
├── identities # Age private keys
├── recipients # Age public keys
└── passwords/ # Encrypted password files
├── .git/ # Git repository (optional)
├── .gitattributes # Git diff configuration
└── *.age # Encrypted password files
You can also use PAK programmatically:
import { PasswordManager } from '@kdbx/pak-lib';
const pm = new PasswordManager();
// Add a password
await pm.add('mysite', { generate: true, length: 32 });
// Retrieve a password
const password = await pm.show('mysite');
// List all passwords
const passwords = await pm.list();
// Delete a password
await pm.delete('mysite');
git clone https://github.com/tonidy/pak-cli.git
cd pak-cli
npm install
npm run build
npm test
npm run dev -- add mysite
If you're migrating from the original pa shell script:
PA_DIR to your existing password directoryIf you're already using age-plugin-se with pa-cli:
npm install -g @kdbx/pak-lib
brew install age-plugin-se
export PA_DIR=/path/to/your/existing/pa/directory
pa se-info
If you have recipients in different formats, you can convert them:
# Convert Secure Enclave recipient to YubiKey format
pa convert age1se1qfn44rsw0xvmez3pky46nghmnd5up0jpj97nd39zptlh83a0nja6skde3ak yubikey
# Convert YubiKey recipient to Secure Enclave format
pa convert age1yubikey1qfn44rsw0xvmez3pky46nghmnd5up0jpj97nd39zptlh83a0nja6skde3ak se
MIT License - see LICENSE file for details.
If you discover a security vulnerability, please email tonidy@users.noreply.github.com instead of using the issue tracker.
FAQs
PAK (Password Age Kit) - A simple, secure password manager in JavaScript using age encryption.
We found that @kdbx/pak-lib demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.