DEV Community

Fernando Paladini
Fernando Paladini

Posted on

Run a Safe Local Review of Env Team Vault Before Sharing .env Files

Team environment variables are easy to share badly. A .env file sent through chat is convenient, but it is difficult to audit, easy to lose track of, and often contains more access than a teammate needs.

Env Team Vault is an open-source, self-hosted Node.js and TypeScript application that organizes teams, applications, variables, API tokens, and audit events around local development configuration. The useful question is not only how to install it. The useful question is whether the current code and package are ready for the boundary where you want to use them.

This tutorial shows a safe evaluation path for the current main branch and package version 1.0.0. You will build the project, inspect the CLI flow, and verify the environment-file route. This is a reproducible review, not a production recommendation.

TL;DR

  • Clone paladini/env-team-vault and install its locked dependencies.
  • Run the TypeScript build and inspect the CLI package before sending real values.
  • The project documents Docker Compose, a web UI, SQLite with Prisma, and env-team-vault sync.
  • The current root CLI imports axios, but axios is not declared in the root package.json, so the documented npx env-team-vault --help check currently fails after npm ci.
  • The API controller also has an unauthenticated compatibility branch. Treat the current code as a local-development experiment until that boundary is fixed and tested.

Prerequisites

You need Git, Node.js, npm, and a disposable working directory. The repository declares Node.js type definitions for Node 20, while its Dockerfile starts from Node 18 Alpine. Use a current supported Node release for the local build, and record the exact version in your review.

Do not put real API keys, production database URLs, or customer data into a first run. Use fake values and a disposable SQLite database.

1. Clone the current source and install it

The repository README documents Docker Compose and a manual npm setup. Use the owner repository URL, not the placeholder your-org URL in its copy-paste examples.

git clone https://github.com/paladini/env-team-vault.git
cd env-team-vault
npm ci
Enter fullscreen mode Exit fullscreen mode

The lockfile pins the application package at version 1.0.0 and includes its Prisma, Express, Passport, SQLite session, and TypeScript dependency tree. npm ci tests the package as committed rather than silently resolving a new dependency graph.

Before continuing, inspect the installation result:

npm audit
npm run build
Enter fullscreen mode Exit fullscreen mode

The build compiles src/main.ts and the application layers into dist. It does not prove that the web server is configured correctly, that the database has been initialized, or that the CLI can run. Keep those checks separate.

2. Understand the local architecture

The application combines Express with server-rendered EJS views. Prisma stores teams, users, applications, variables, API tokens, and audit logs in SQLite. The schema makes variable keys unique per application.

The main configuration values are:

NODE_ENV=development
PORT=3000
SESSION_SECRET=use-a-random-local-value
DATABASE_URL=file:./prod.db
Enter fullscreen mode Exit fullscreen mode

The source defaults the HTTP port to 3000, enables the SQLite-backed session store, and uses a fallback session secret when SESSION_SECRET is absent. That fallback is convenient for a local experiment but is not an acceptable production setting.

The documented Docker path exposes port 3000 and persists the Prisma database and sessions in named volumes:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000, register a disposable account, create a team, and create an application. Do not add a real secret while evaluating the flow.

3. Verify the documented CLI before trusting it

The README documents a sync command that writes the response into a local .env file:

npx env-team-vault sync <APP_ID> --url http://localhost:3000 --token <API_TOKEN>
Enter fullscreen mode Exit fullscreen mode

The current root bin/cli.js imports axios, fs, yargs, and Node path utilities. The root package.json declares yargs and the other server dependencies, but it does not declare axios. A fresh npm ci followed by npx env-team-vault --help therefore reaches the CLI file and fails with Cannot find module 'axios'.

That failure separates a documented interface from a verified interface. Do not work around it by installing an undeclared package and then report the repository as working. A fix should add the dependency, update the lockfile, and add a smoke test for the executable path.

The CLI also writes the server response directly to .env in the current directory. That is convenient, but it can overwrite an existing file. Use a disposable directory until the command has a confirmed backup or safe-write policy.

4. Inspect the authentication boundary

The API route documented for the CLI is:

GET /api/vault/:appId
Enter fullscreen mode Exit fullscreen mode

When an Authorization: Bearer ... header is present, VaultController looks up the API token, checks revocation, verifies team membership, verifies that the application belongs to that team, and records a SYNC_ENV audit event.

However, the same controller has an else branch for requests without an authorization header. It checks only that the application exists and then returns the environment content. The route is registered as a public Express route, without the authentication middleware used by other parts of the application.

This is the most important boundary in the current review. The README calls the project secure and audited, but the implementation currently permits an unauthenticated request for a known application ID. Do not expose this route to an untrusted network or put production secrets behind it. A safe contribution would remove the compatibility branch, require a valid token, add an integration test for unauthorized requests, and then document the changed contract.

This conclusion comes from the current controller and route source, not from treating the README's security language as a guarantee. Source behavior wins when documentation and implementation differ.

5. Verify the expected result without real secrets

For a local evaluation, the expected result is a buildable application and a reviewable data flow:

  1. The server starts on port 3000 after the database has been initialized.
  2. A disposable account can create a team and an application.
  3. A fake variable such as DEMO_VALUE=not-a-secret can be associated with that application.
  4. A valid API token can be used to request the application's .env representation.
  5. The request creates an audit record when the token path is used.

The source formats the response as plain text, so a successful response should look like this:

DEMO_VALUE=not-a-secret
Enter fullscreen mode Exit fullscreen mode

Check the HTTP status, response content type, and resulting file. Then inspect the audit log in the application. Never use a successful response as evidence that the deployment is safe by itself. The unauthenticated branch and the default session secret still need to be addressed.

Why this review order works

The order follows operational risk. npm ci and npm run build establish a baseline. The CLI check tests whether the documented command exists in the dependency graph. The controller review tests authorization before any real value crosses the boundary.

This is also why a green TypeScript build is not enough. TypeScript checks the files included in compilation. It does not guarantee that a JavaScript CLI has every runtime dependency, that a database migration exists, or that an HTTP route enforces the intended authorization policy.

Failure modes and honest limitations

The CLI reports a missing module

Confirm the package manifest and lockfile before installing anything manually. The current root CLI's undeclared axios import is a repository issue, not a user configuration error.

Prisma has no migration to apply

The current repository contains prisma/schema.prisma but no migration directory in the checked-in Prisma folder. Treat database initialization as a development setup step and review the resulting database before using the application. Do not point this first run at an existing production database.

A token request returns 401 or 403

Check the Bearer prefix, token revocation state, user team membership, and application team ownership. The controller intentionally rejects invalid or revoked tokens on the authenticated path.

You need production secret management

This project is explicitly positioned for local development variables. It is not a replacement for a mature production secret manager. The current unauthenticated route, fallback session secret, local SQLite storage, and missing CLI dependency are enough reason to keep the evaluation local and disposable.

FAQ

Is Env Team Vault a production secrets manager?

No. The README describes a self-hosted local-development tool, and the current route implementation has an unauthenticated compatibility path. Treat it as an experiment or contribution target until that behavior changes.

Why use npm ci instead of npm install?

npm ci uses the committed lockfile and exposes undeclared runtime dependencies more reliably. It makes the first verification closer to what a clean deployment or package consumer will see.

Should I publish the .env file generated by the CLI?

No. Keep it outside version control, use fake values while testing, and check your ignore rules before running a sync command in a repository.

Where is the source of truth for behavior?

Use the repository README for the documented workflow, then compare it with the package manifest, Prisma schema, CLI implementation, and vault controller for current behavior.

Takeaway

Env Team Vault has a clear local-development idea: keep team variables in one self-hosted application, expose a CLI, and record synchronization events. The responsible way to evaluate it is to verify each layer independently. The current build succeeds, but the documented CLI has an undeclared runtime dependency and the API has an unauthenticated response path. Those findings should shape how you use the project and what you fix next.

This tutorial was prepared with AI assistance for research organization and editorial review. The repository behavior, commands, and limitations were checked against the current public source and a fresh local checkout.

Would you use a tool like this for disposable development environments, and which authorization test would you add first?

Top comments (0)