Secrets management
varlock uses the term sensitive to describe any value that should not be exposed to the outside world. This includes secret api keys, passwords, and other generally sensitive information. Instead of relying on prefixes (e.g., NEXT_PUBLIC_) to know which items may be “public”, varlock relies on @decorators to mark sensitive items explicitly.
Marking @sensitive items
Section titled “Marking @sensitive items”Whether each item is sensitive or not is controlled by the @defaultSensitive root decorator and the @sensitive item decorator. Whether you want to default to sensitive or not, or infer based on key names is up to you. For example:
# @defaultSensitive=false# ---# not sensitive by default (because of the root decorator)NON_SECRET_FOO=# @sensitive # explicitly marking this item as sensitiveSECRET_FOO=Loading secrets from external sources
Section titled “Loading secrets from external sources”Using plugins (recommended)
Section titled “Using plugins (recommended)”varlock provides official plugins for popular secret management platforms, offering a seamless and type-safe way to fetch secrets directly in your .env files.
Available plugins include:
- 1Password
- AWS Secrets Manager & Parameter Store
- Azure Key Vault
- Bitwarden
- Google Secret Manager
- HashiCorp Vault
- Infisical
- Pass
- Proton Pass
See the plugins overview for the complete list.
Plugins are able to register new decorators and resolver functions that declaratively fetch secrets:
# Install and initialize the 1Password plugin# @plugin(@varlock/1password-plugin)# @initOp(token=$OP_TOKEN, allowAppAuth=forEnv(dev))# ---
# Load secrets using the op() resolver function# @sensitive @requiredMY_SECRET=op(op://my-vault/item-name/field-name)Benefits of using plugins:
- Declarative secret references safe to check into version control
- Built-in validation and type safety applied to fetched values
- Built-in authentication handling
- Better error messages and debugging
- Platform-specific features (e.g., biometric unlock for 1Password)
See each plugin’s documentation for detailed setup instructions.
Using exec() as a fallback
Section titled “Using exec() as a fallback”For cases where a plugin doesn’t exist or you need custom logic, varlock supports fetching secrets via CLI commands using exec() function syntax.
# A secret fetched via CLI# @sensitive @requiredMY_SECRET=exec(`op read "op://devTest/myVault/credential"`);This approach works with any CLI tool, ensuring no secrets are left in plaintext on your system, even if they are gitignored.
Bulk injection with @setValuesBulk()
Section titled “Bulk injection with @setValuesBulk()”For some secret management platforms, you may already be setting key names that match your environment variable names - in which case, wiring up each value can feel like a lot of boilerplate.
In case like this, you can set many values at once using the @setValuesBulk() root decorator.
For example, using 1Password, you could store a .env style blob within a text field, or you could fetch values from their new environments tool.
# fetch a dotenv style blob within a text field# @setValuesBulk(op("op://vault/field/item"))## load values in a 1Password environment# @setValuesBulk(opLoadEnvironment(your-environment-id), createMissing=true)## load all secrets from an Infisical project environment# @setValuesBulk(infisicalBulk())## load Infisical secrets filtered by path or tag# @setValuesBulk(infisicalBulk(path="/database", tag="backend"))## Fetch all secrets from HashiCorp Vault as JSON# @setValuesBulk(exec("vault kv get -format=json secret/myapp"), format=json)The bulk values are injected at the precedence level of the file containing the decorator — so .env.local and process.env will still override them as expected. See the reference docs for full details.
Security enhancements
Section titled “Security enhancements”Unlike other tools where you have to rely on pattern matching to detect sensitive-looking data, varlock knows exactly which values are sensitive, and can take extra precautions to protect them.
For example, some of the features supported by our libraries and integrations:
- Redact sensitive values from logs
- Scan client-facing bundled code at build time
- Scan outgoing HTTP responses at runtime
- Pre-commit git hooks to keep sensitive values out of version control
Scanning for leaked secrets
Section titled “Scanning for leaked secrets”The varlock scan command checks your project files for any plaintext occurrences of your @sensitive values. It loads your varlock config, resolves all sensitive values, and then searches through files to detect leaks.
varlock scanThis is intended to be used as a pre-commit git hook to prevent accidentally committing secrets into version control. If no sensitive values are found in plaintext, it exits successfully. If any are detected, it reports the file, line number,and which secret was found, then exits with a non-zero status code.
Scanning modes
Section titled “Scanning modes”varlock scan- default mode, scans all files except gitignored onesvarlock scan --include-ignored- scans all files including gitignored onesvarlock scan --staged- scans only the files you have staged for commit
Automatic setup
Section titled “Automatic setup”The easiest way to set this up is:
varlock scan --install-hookThis will detect if you use a hook manager (like husky or lefthook) and provide appropriate instructions. If no hook manager is detected, it will create a .git/hooks/pre-commit script for you.
Manual setup
Section titled “Manual setup”If you prefer to set it up yourself, add the following to your pre-commit hook:
Plain git hook (.git/hooks/pre-commit):
#!/bin/shvarlock scanMake sure the hook file is executable:
chmod +x .git/hooks/pre-commitWith husky (.husky/pre-commit):
varlock scanWith lefthook (lefthook.yml):
pre-commit: commands: varlock-scan: run: varlock scan