July was a big one. We shipped a credential proxy that hands AI agents placeholder secrets instead of real ones, code generation for Python, Rust, Go, PHP, Java, and C#, array and record value types, and a new varlock flatten command for monorepo Docker builds. A new Sandboxes docs section covers running agents in ten different sandboxing tools with varlock holding the credentials.
🔧 Core Improvements
Credential proxy for AI agents (preview)
The headline feature: run an agent (or any untrusted tool) through a local MITM proxy so it only ever sees placeholder secrets. Real values are injected at the wire, bound to a verified upstream TLS identity, responses are scrubbed back to placeholders, and every request is policy-checked and audited. Mark a secret with @proxy(domain="api.example.com") and route with host/path/method rules. See the proxy guide and varlock proxy reference.
- Routing rules and egress control -
blockandapprovalrules, per-domain grouping, and@proxyConfig={egress="strict"}to control what the child can reach at all. See proxy routing rules and egress modes. - Named substitution targets - Secrets are substituted into request headers only by default (excluding forward and log headers like
cookieandx-forwarded-*), and a placeholder may appear at most once per request. Widen with@proxy(substituteIn=[...])using targets likeheader:authorization,path,query:api_key, orbody:client_secret, and raise the cap withmaxOccurrences. See substitution surface. - Sandboxing -
proxy run --sandboxruns the agent in a sandbox whose only egress is the proxy: a built-in macOS credential and egress jail, or--sandbox=docker(or=podman) to run it in a container while your secrets stay on the host. See the sandboxing guide. - Remote sandboxes -
proxy startandrungain--exposeplus a built-in CONNECT-over-WebSocket tunnel, so a client behind provider HTTP ingress (E2B, Modal, and similar) can route through it.varlock proxy run --url <wss-url> -- <command>runs a command through a broker running elsewhere, self-wiring env and CA certs while holding only placeholders.varlock proxy tokenprints a session’s data-plane token, and--persist-cakeeps a broker’s CA across restarts. See remote proxy setup. - Live policy reload -
varlock proxy reloadno longer requires the schema to resolve in the requesting shell. The proxy validates the edit in its own context before applying and reports failures back, so a remote broker can be reloaded with a bare provider exec. See editing the schema while a session is running. - Client compatibility - Minted MITM certs now include subject and authority key identifiers so strict TLS verifiers (Python 3.13+ urllib and httpx defaults) accept them; the injected env sets
NODE_USE_ENV_PROXY=1so Node’s built-in fetch (Node 24+) routes through the proxy instead of silently bypassing it, andDENO_CERTso Deno trusts the proxy CA. Also fixed a roughly 1-in-512 cert failure from non-minimal DER serial numbers. See client compatibility. - Proxying through a proxy -
proxy run --urlnow dials its tunnel through an HTTP proxy (HTTP(S)_PROXY/NO_PROXY), so a sandboxed agent whose only egress is a gateway (for example Docker Sandboxes) can still reach a broker.
Code generation for seven languages
- Per-language decorators -
@generatePythonEnv(),@generateRustEnv(),@generateGoEnv(),@generatePhpEnv(),@generateJavaEnv(), and@generateCsharpEnv(). Each emits a self-contained, idiomatic module with typed coerced values, a loader that parses the injected env, and aSENSITIVE_KEYSconstant. See the code generation guide and the new Python, Rust, Go, PHP, Java, and C# integration docs. - TypeScript generator moved -
@generateTypes(lang=ts)is now@generateTsTypes(), with options to controlprocess.env/import.meta.envaugmentation and a monorepo-friendlyexposeEnv=localmode. The old form still works as a deprecated alias. varlock typegenis nowvarlock codegen-typegenis kept as a deprecated alias. Seevarlock codegen.- Plugins can extend codegen - Plugin-registered data types can declare
coercedTypeso generated env modules type their fields correctly instead of emitting everything as strings. See extending with plugins.
Schema and CLI
- Array and record types -
@type=array(...)and@type=record(...)with per-element validation, native[a, b]and{k=v}literal values, JSON and separator string input, configurable serialization back toprocess.env, and per-element redaction. --filterand@tag()- Select env vars by key or glob, by@sensitive/@required/@dynamic, or by tag with the new@tag()decorator.@generate*decorators take a matchingfilter=arg, so one schema can emit multiple generated files scoped to different subsets. Decorator-based filters also scope resolution and validation, so a build-time--filter='!@dynamic'skips runtime-only vars entirely, including their@requiredchecks. See filtering items.- Static and dynamic config controls -
@dynamicand@staticitem decorators,@defaultDynamic, and dynamic-plus-public framework and runtime support. See the new static vs dynamic vars guide. varlock flatten- Collapses the@importgraph into a self-contained directory, rewriting import paths and pinning plugin versions, so a single package can be deployed without the rest of the monorepo.--vendor-pluginscopies plugins into the output for a fully self-contained artifact that resolves with no runtime npm fetch, no shell, and no trust prompt. Seevarlock flattenand the Docker guide.generateOtp()- Generate TOTP 2FA codes from a stored seed. SeegenerateOtp().- Load failure reporting -
varlock/auto-loadcan now throw the load error instead of exiting silently, so a reporter like Sentry can capture it. Opt in with aglobalThis._varlockOnLoadErrorhook or_VARLOCK_THROW_ON_LOAD_ERROR=1. See reporting load failures. - Injected env blob reuse -
varlock/auto-loadandvarlock runreuse an injected__VARLOCK_ENVblob instead of re-resolving when it was resolved in the same directory. Pin the behavior with_VARLOCK_USE_INJECTED_ENV, which is useful when handing env into a sandbox with no.envfiles. See reusing an injected env blob. - Better CLI errors - Unknown or misspelled flags are rejected with a did-you-mean suggestion instead of being silently ignored.
Platform, runtime, and OS detection
@varlock/ci-env-info- The new0.1.0release adds detection for Railway, AWS Amplify, Google Cloud Run, Deno Deploy, Zeabur, and Firebase App Hosting, and detects dev sandboxes (CodeSandbox, StackBlitz, GitHub Codespaces, Gitpod, Replit) withisCI: false.VARLOCK_RUNTIMEandVARLOCK_OS- New builtin variables backed bydetectRuntimeanddetectOs. See builtin variables.- Detection fixes - An audit against
std-envfixed several wrong env var names (GitHub Actions PR number, GitLab MR IID, Netlify build URL, Semaphore and Azure Pipelines PR numbers, Bitbucket repo owner) and madevercel dev/netlify devreportisCI: false.
Security and reliability
- Compressed response leak scanning - Gzipped responses that fit in a single chunk were never scanned, so browsers could receive leaked sensitive values the scanner should have blocked. Brotli and zstd are now scanned too, and compressed chunks containing a leak fail closed. Note that an app with an existing undetected leak will start seeing those responses blocked after upgrading: look for
DETECTED LEAKED SENSITIVE CONFIGin server logs. @internalitems excluded fromload --format json-full- Framework integrations shell out to this exact command for their injected config, so this closes a leak where an@internalsecret-zero credential could reach client or SSR runtime code. Pass--include-internalto opt in for local debugging.- Signed and verified release artifacts - The install script verifies the sha256 of the downloaded archive against the release’s published
checksums.txtand fails without installing on a mismatch. - Windows TPM and WSL - Windows local encryption now uses TPM-sealed keys via NCrypt when available, with existing DPAPI keys auto-upgrading on the next decrypt.
install.shalso installsvarlock-local-encrypt.exeon WSL so local encryption can use the Windows TPM/Hello backend (--skip-win-exeto opt out). Thanks @cturner8. - Encrypted blob injection from the CLI -
@encryptInjectedEnvis now honored whenvarlock runandvarlock proxy runinject the env blob, not just on the library auto-load and build-time paths. - Cache lock recovery - Locks left behind by an interrupted run are reclaimed immediately instead of stalling later runs for minutes and hiding the real error.
varlock cache clearalso clears locks. - Fixes -
varlock auditnow honors@auditIgnore; nestedvarlock runcommand-local overrides win over the parent’s injected value again;pickandomitfilters apply to directory imports; root decorators resolve the full dependency chain of items referenced in their args; refs in@cachevalues no longer resolve as undefined;forEnv()errors on arguments that resolve to undefined; numericInfinityis rejected in number coercion; andvarlock runno longer OOMs on a bare PATH binary likenode.
Breaking changes worth noting: ENV is no longer exported from the package root (import it from varlock/env), the minimum supported Node version is now 22.3, and @disableProcessEnvInjection requires a static true / false value since generated code must not differ per environment.
🔌 Integrations and Plugins
Integrations
@varlock/nextjs-integration- Fixed dev-server env reloading on turbopack and Next 16, added pages router and middleware support (webpack builds, edge bundle analysis, encrypted deployments in middleware and edge routes), and made turbopack staticENV.xreplacement AST-based so string literals and comments are no longer corrupted. Also preserves all"use ..."directives including stacked ones. Thanks @mhornbacher.@varlock/vite-integration- Fixed Astro plus Cloudflare static and prerendered builds (REQUIRE_TLAerrors), and now warns when deploying to Vercel with resolved env injection and no encryption enabled.@varlock/cloudflare-integration- Fixed.dev.varsquoting so secrets with apostrophes, quotes, and backslashes round-trip correctly through Wrangler, and stopped embedding.dev.varscontents in the preview helper’s process argv.@varlock/astro-integrationand@varlock/expo-integration- Compatibility updates alongside core releases.- FIFO env sources - Non-regular env sources such as 1Password Environments are now detected and skipped for dev-server restart watching across the Next.js, Vite, and Cloudflare integrations, fixing dev-server hangs and endless no-op reload logs.
Plugins
@varlock/hashicorp-vault-plugin- NewvaultToken()resolver exposes the authenticated Vault client token.@varlock/infisical-plugin-allowMissingflag oninfisical()and@initInfisical()for optional secrets.@varlock/1password-plugin- Fixed CLI batch reads failing with “expected data on stdin but none found” on Windows, and one-time password codes are never cached.env-spec-languageand@env-spec/parser- Array and record types, autocomplete and hover docs for@tag(),filter=,@internal, andgenerateOtp(), plus a fix for$(...)truncation on nested parentheses.
🌐 Content Highlights
- New Sandboxes docs section - Recipes for running agents in E2B, Fly.io, Docker Sandboxes, smolvm, Fence, yolobox, Agent Safehouse, bubblewrap, MXC, and minimal setups, with varlock holding the real credentials. Start with topologies to pick a shape.
- Software Defined Talk #580 - The founders sat down with the show to talk about why almost nobody manages their
.envfiles well. Thanks @brandonwhichard.com for the conversation. - New guides - Code generation, static vs dynamic vars, and a reorganized CLI reference split by command group.
💬 Community
We’re always looking for feedback and ideas. Join our community:
- Discord - Chat with us and other users.
- GitHub Discussions - Suggestions, questions, and feature ideas.
- GitHub - Star the project and follow updates.
- X - Follow us on X.
- Bluesky - Follow us on Bluesky.