npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

yamlock

v0.3.0

Published

Value-level encryption for YAML/JSON configuration files with CLI + Node.js APIs.

Readme

░█░█░█▀█░█▄░▄█░█░░░█▀█░█▀▀░█░█░
░░█░░█▀█░█░▀░█░█░░░█░█░█░░░█▀▄░
░░▀░░▀░▀░▀░░░▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░

npm version Tests

yamlock

Value-level encryption for YAML and JSON configuration files. The name yamlock combines "YAML" and "lock" while also sounding like "warlock", hinting at a little configuration magic.

Requirements

  • Node.js 22.x via asdf
  • Yarn Classic (1.x)

Installation

npm

npm install -g yamlock      # CLI usage
npm install yamlock         # project dependency

Yarn Classic

yarn global add yamlock     # CLI usage
yarn add yamlock            # project dependency

Features

  • Encrypt/decrypt individual configuration values with deterministic field-path salts.
  • CLI workflow that processes YAML or JSON files in place.
  • Recursively lock/unlock entire objects via processConfig.
  • Public API exports that mirror CLI behavior for programmatic use.
  • Focus on Node.js 22+, ESM modules, and a lightweight dependency set (js-yaml).

Usage

CLI

# Encrypt values in a YAML file
YAMLOCK_KEY="super-secret" yamlock encrypt config.yaml

# Decrypt values in place using explicit key/algorithm flags
yamlock decrypt settings.json --key "super-secret" --algorithm aes-256-cbc

# Encrypt only selected fields into a new file
yamlock encrypt config.json --key "$YAMLOCK_KEY" --paths "db.password,api.token" --output config.secure.json

# Inspect CLI metadata
yamlock version
yamlock algorithms

# Generate a random key for YAMLOCK_KEY
yamlock keygen --length 64 --format base64

# Preview changes without touching files
yamlock encrypt config.yml -o config.enc.yml -p db.password -k "my-secret-key" -d

The CLI detects YAML (.yaml/.yml) and JSON extensions automatically and writes the file back in the same format.

Options of note:

  • --output <file> writes the result to a separate file instead of overwriting the input.
  • --paths <path1,path2> targets only the specified fields (dot/bracket notation like db.password or users[0].token).
  • --dry-run shows the would-be changes without modifying files (prints original vs new content).
  • Command keygen produces a random key and shows how to store it (shell export or .env).
  • Command algorithms prints two lists: tested presets (covered by yamlock) and additional ciphers available from the runtime.
  • Command version prints the installed CLI version.

Node.js API

import { encryptValue, decryptValue, processConfig } from 'yamlock';

const encrypted = encryptValue('swordfish', process.env.YAMLOCK_KEY, 'db.password');
const decrypted = decryptValue(encrypted, process.env.YAMLOCK_KEY, 'db.password');

const config = { db: { password: 'swordfish' } };
const locked = processConfig(config, { mode: 'encrypt', key: process.env.YAMLOCK_KEY });
const unlocked = processConfig(locked, { mode: 'decrypt', key: process.env.YAMLOCK_KEY });

See examples/basic.js for a runnable end-to-end script (node examples/basic.js).

Algorithm customization

Each function accepts either a cipher name or an options object:

const encrypted = encryptValue('swordfish', KEY, 'db.password', {
  algorithm: 'chacha20-poly1305',
  ivLength: 12 // override the IV size used during encryption
});

// When decrypting, the algorithm is inferred from the payload,
// but you can still override key/IV sizes if the cipher requires it.
const decrypted = decryptValue(encrypted, KEY, 'db.password', /* optional overrides */);

// processConfig propagates the same options through every nested field.
const processed = processConfig(
  { db: { password: 'swordfish' }, api: { token: 'secret' } },
  {
    mode: 'encrypt',
    key: KEY,
    algorithm: { algorithm: 'aes-192-cbc', ivLength: 24 }
  }
);

// Later you can decrypt with the same options:
const restored = processConfig(processed, {
  mode: 'decrypt',
  key: KEY,
  algorithm: { algorithm: 'aes-192-cbc', ivLength: 24 }
});

// Control what happens when encountering non-string values and customize path IDs
const mixedConfig = { db: { password: 'secret', retries: 3 } };
const lockedMixed = processConfig(mixedConfig, {
  mode: 'encrypt',
  key: KEY,
  nonStringPolicy: 'stringify', // stringifies numbers/objects before encrypting
  pathSerializer: (segments) => segments.join('/') // custom path naming (db/password instead of dot notation)
});

// Example of a path serializer that includes array indexes explicitly
const lockedUsers = processConfig(
  { users: [{ tokens: ['abc'] }] },
  {
    mode: 'encrypt',
    key: KEY,
    pathSerializer: (segments) =>
      segments
        .map((segment, index) =>
          typeof segment === 'number' ? `[${segment}]` : index === 0 ? segment : `/${segment}`
        )
        .join('')
  }
);

Advanced usage

  • Selective encryption: combine --paths on the CLI or paths: [] in processConfig to encrypt only sensitive sections of a config file.
  • Non-string handling: use nonStringPolicy: 'ignore' | 'stringify' | 'error' to control how numbers/objects are treated, and pathSerializer to change how traversal paths are represented (e.g., db/password instead of dot notation).
  • CI/CD flows: see examples/docs/ci-cd.md for a GitHub Actions job that decrypts configs for builds and re-encrypts them before publishing artifacts.
  • Key rotation: follow examples/docs/key-rotation.md for a step-by-step process, including scripting tips for large repos.

Supported algorithms

| Algorithm | Type | Notes | |-----------|------|-------| | aes-128-cbc | Block cipher (CBC) | 128-bit keys, 16-byte IV. Works well for backward-compatibility scenarios. | | aes-192-cbc | Block cipher (CBC) | 192-bit keys, 16-byte IV. Slightly stronger than AES-128 with the same IV requirements. | | aes-256-cbc (default) | Block cipher (CBC) | 256-bit keys, 16-byte IV. Balanced combination of strength and compatibility. | | chacha20-poly1305 | AEAD stream cipher | 256-bit keys, 12-byte nonce, 16-byte auth tag. Provides built-in integrity/authentication. |

You can also pass any algorithm supported by the current Node.js runtime (crypto.getCiphers()), along with custom keyLength, ivLength, or authTagLength overrides. Only the algorithms above are actively tested; additional presets may be added or revised in future releases.

Release information

  • The badges at the top show the latest npm version and the status of the Node test suite.
  • See CHANGELOG.md for detailed release notes; install a specific tag via npm install yamlock@<version>.

Encrypted value format

Every locked string follows the format:

yl|<algorithm>|<salt_base64>|<iv_base64>|<data_base64>

Where:

  • yl - format marker prefix
  • <algorithm> - algorithm name (e.g., aes-256-cbc)
  • <salt_base64> - Base64-encoded field path
  • <iv_base64> - Base64-encoded initialization vector
  • <data_base64> - Base64-encoded encrypted data

The salt is derived from the full field path. Moving or renaming the field invalidates the salt, preventing accidental decryption in the wrong location.

Key rotation

See docs/key-rotation.md for a step-by-step guide to rotating YAMLOCK_KEY without losing data.

Inspiration and motivation

I have worked with Ruby on Rails apps for more than ten years and appreciated how its secret management evolved between 4.2 and 6.x. That flow influenced yamlock, but I also explored modern tools such as:

Each of those projects solves secure config storage differently, yet none fit my exact needs. yamlock is the bicycle I am building for my own projects to add an extra layer of encryption for sensitive YAML/JSON values while keeping the workflow lightweight.

Contributing

See CONTRIBUTING.md for development workflow, available scripts, and release instructions.

Exit codes

yamlock returns 0 when encryption/decryption completes successfully and 1 on validation or runtime errors (missing keys, malformed payloads, failed file reads). Use these exit codes to gate CI jobs or deployment steps.

Future work

  • Additional cipher presets and stronger default algorithms.
  • More CLI/API examples for rotating keys, selective field targeting, and CI automation.
  • Configurable behavior for non-string values (skip vs. coerce) and stricter file format validation.

License

MIT © PAVEL TKACHEV