Files
lazysecrets/docs/repos.md
T
keb dbe4fbeb5f
CI / Checks (pull_request) Successful in 39s
PR title / Conventional title (pull_request) Successful in 1s
feat: H shows what's hidden; Spring keys that don't look secret are hidden
Sources, files and secrets get a Hidden flag. The repo provider marks
Spring keys that match neither pattern, files with only those, and repos
with only such files, instead of leaving them out.

- Hidden items are left out of the panes, Go to and lazysecrets list;
  a pane's counter says how many it hides.
- H (lists.toggleHidden) shows them, dimmed whole in mutedColor;
  list --hidden lists them, json marks them "hidden".
- A revealed empty value shows "∅ no value (an empty string)", muted,
  instead of a blank line.
2026-10-15 13:43:37 +02:00

6.8 KiB

SOPS, .env and Spring files in git repos

lazysecrets shows git repositories under Repos: their SOPS-encrypted files (YAML, JSON, .env, INI), plain env files and Spring Boot config as vaults, and the keys in them (db.password, list[0]) as secrets. A dot or bracket inside a key is escaped, app\.name, so it doesn't read as nesting.

Which repos

Repos lists every repo with secret files under the roots (by default whichever of ~/git, ~/repo, ~/repos, ~/projects, ~/code, ~/source and ~/src exist; one or two levels down, repo or org/repo), any listed in paths, and any you starred something in (the repo, a file or a key), wherever it is. They're checked in the background.

Started inside a repo, that repo gets a row of its own at the top, Repo · <name>, and lazysecrets opens on it, with the files under the directory you started in first. In the flat list (`) it sorts first, marked · here.

A repo without secret files isn't listed. --dir <path> starts somewhere else, for example in one project of a monorepo.

Repos load themselves as they're found, files and keys, since they're local and cheap: Go to searches them without loading anything by hand.

Which files

Env files: .env, .env.local, prod.env and the like, also when git-ignored (as they usually are), in the folders git tracks files in; not .env.example, .sample, .template and the like. They're read directly; a file with SOPS metadata is always treated as SOPS, whatever its name.

Folders of dependencies and caches are never looked in, tracked or not: node_modules, vendor, .venv, venv, __pycache__, .terraform, .gradle, .yarn, .next and the like.

SOPS files: those tracked by git, then the first of

  1. include/exclude in the repo's own .lazysecrets.yaml (committed, so everyone sees the same files),
  2. include/exclude in the config,
  3. where the repo's .sops.yaml creation_rules say SOPS files go,
  4. the whole repo.

include/exclude apply to env and Spring files too.

providers:
  repos:
    roots: [~/git]                             # folders of repos (replaces the defaults; [] turns it off)
    paths: [~/work/infra]                      # single repos elsewhere
    include: ["secrets/**", "**/*.sops.yaml"]  # globs from the repo root; ** for any depth
    exclude: ["**/testdata/**"]

A repo's .lazysecrets.yaml can also name the secret its env files are shared with:

sharing:
  key: https://kv-team.vault.azure.net/secrets/env-share   # or its lazysecrets:// link

Spring Boot config

application.yml, application-prod.properties, bootstrap.yaml and the like, tracked by git (not those in a Helm chart's templates/). Most of their keys aren't secret, so only those that look like one are listed; the rest are hidden:

  • keys named like a secret: ending in password, pwd, secret, token, key, credentials, salt, connection-string and the like (spring.datasource.password, client-secret, checkoutKey),
  • values that look like one: Jasypt's ENC(...), a URL with a password (jdbc:postgresql://app:pw@db/app), or a connection string with AccountKey=, SharedAccessKey= or Password=.

A file with none is hidden too, and a repo with only such files. H shows what's hidden, dimmed, in the panes and in Go to (lazysecrets list --hidden lists it); a pane's counter says how many it hides. A file's details count its hidden keys, and e opens it whole. A ${DB_PASSWORD} value is marked as a reference: the secret is set elsewhere. A tracked file is marked in red only when a listed key has its value in plain text.

Each list of regexps replaces its default; keys: [".*"] lists every key:

providers:
  repos:
    spring:
      keys: ["(?i)(password|secret|token|key)$", "bearer$"]   # matched against the key's name
      values: ["^ENC\\(.+\\)$"]                               # and against its value

A repo's .lazysecrets.yaml can set spring too, for everyone, and wins over the config, one list at a time.

Keys are named as Spring names them, spring.datasource.password; in a file with several documents (---, or #--- in .properties), a later document's keys get its profile, spring.datasource.password (prod). Values Maven fills in at build time (@project.version@) are read as they are.

Decrypting

Listing never decrypts: SOPS and Jasypt encrypt values only, so keys and metadata (encryption, last modified) are read straight from the files. Revealing, copying or lazysecrets get decrypts one value; SOPS's with your sops binary, so whatever sops uses works (age keys, Azure Key Vault through az, AWS/GCP KMS, PGP). When sops can't decrypt, its whole error message is shown.

On a file, the right pane shows how it's encrypted and the keys it's encrypted for (public: age recipients, Key Vault keys, KMS ARNs, PGP fingerprints), when it was last encrypted, and what git knows of it: tracked, ignored or neither, and its last commit. A plain .env file that git tracks, or that isn't ignored, is marked in red: its values are in the repo's history, or easily could be.

Jasypt

A value like ENC(...) in a plain .env or Spring file is Jasypt's, decrypted when it's revealed or copied with jasypt-spring-boot's default algorithm (3.0+: PBEWITHHMACSHA512ANDAES_256). The password is, as in Spring:

  1. $JASYPT_ENCRYPTOR_PASSWORD,
  2. the file's own: jasypt.encryptor.password in a Spring file, JASYPT_ENCRYPTOR_PASSWORD in a .env; a ${VAR} (or ${VAR:default}) in it is read from the environment.

Environment variables are lazysecrets' own: a link opened from the browser starts it without your shell's. A .env whose values are all Jasypt's isn't marked in red.

Opening files

e opens the selected file, or on a secret, its file at that key's line:

  • SOPS files open with sops edit, which decrypts them into your editor ($SOPS_EDITOR or $EDITOR) and encrypts them again when you save. lazysecrets comes back after, with the file's keys reloaded.
  • Other files, when lazysecrets runs inside nvim (its plugin, or :terminal): lazysecrets quits and the file opens in that nvim, in the window you came from.
  • Otherwise in $VISUAL or $EDITOR in the terminal, coming back after; without either, in the system's default app for the file.

Editors that take a line (vim, nvim, nano, emacs, micro, helix, VS Code, Zed, Sublime and others) start on the key. With sops edit that works for editors taking +N (vim, nvim, nano, emacs, micro and others), and needs sops 3.8 or later.

Repo links name the repo by its git remote, so they open in a colleague's clone wherever it is (sharing).