<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: yalelet dessalegn</title>
    <description>The latest articles on DEV Community by yalelet dessalegn (@yalelet_dessalegn_b87ed18).</description>
    <link>https://dev.to/yalelet_dessalegn_b87ed18</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3767786%2F100f3b2f-d94b-4b71-a205-ebe931232740.png</url>
      <title>DEV Community: yalelet dessalegn</title>
      <link>https://dev.to/yalelet_dessalegn_b87ed18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yalelet_dessalegn_b87ed18"/>
    <language>en</language>
    <item>
      <title>I Built a Security Firewall for AI Agents — Here's Why Every MCP Server Needs One</title>
      <dc:creator>yalelet dessalegn</dc:creator>
      <pubDate>Tue, 17 Feb 2026 18:25:10 +0000</pubDate>
      <link>https://dev.to/yalelet_dessalegn_b87ed18/i-built-a-security-firewall-for-ai-agents-heres-why-every-mcp-server-needs-one-1jha</link>
      <guid>https://dev.to/yalelet_dessalegn_b87ed18/i-built-a-security-firewall-for-ai-agents-heres-why-every-mcp-server-needs-one-1jha</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Nobody's Talking About
&lt;/h2&gt;

&lt;p&gt;AI agents can now execute tools  read files, run shell commands, query databases, make HTTP requests. Claude Code, Cursor, Windsurf  they all use the Model Context Protocol (MCP) to talk to tool servers.&lt;/p&gt;

&lt;p&gt;Here's the scary part: &lt;strong&gt;a single prompt injection can weaponize any AI agent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An attacker embeds instructions in a document, email, or web page. The AI reads it, follows the injected instructions, and suddenly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reads&lt;/strong&gt; your &lt;code&gt;.ssh/id_rsa&lt;/code&gt;, &lt;code&gt;.env&lt;/code&gt; files, API keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exfiltrates&lt;/strong&gt; data via &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, or DNS tunneling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Executes&lt;/strong&gt; arbitrary shell commands with YOUR permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chains&lt;/strong&gt; multiple tools to escalate from read → exfil → execute&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn't theoretical. These attacks work TODAY against unprotected MCP servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenClaw: The "Personal JARVIS" or a Security Nightmare?
&lt;/h2&gt;

&lt;p&gt;In early 2026, OpenClaw (formerly ClawdBot/MoltBot) became the fastest-growing repo in history. It promises a "24/7 JARVIS" that lives in your WhatsApp and Slack. But because it has direct access to your shell and filesystem, it has become the #1 target for Agentic Hijacking.&lt;br&gt;
Recent reports show that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Malicious "Skills": Over 12% of the skills on ClawHub were found to be malicious, designed to steal session tokens.&lt;/li&gt;
&lt;li&gt;Exposed Instances: Over 18,000 OpenClaw instances are currently exposed to the public internet with full shell access.
The One-Click RCE: Vulnerabilities like CVE-2026-25253 allow hackers to hijack an agent just by making the user visit a malicious website.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Introducing Agent-Wall: The Firewall for the Agentic Era&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Agent Wall&lt;/strong&gt;  an open-source security firewall that sits between any MCP client and server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MCP Client  ←→  Agent Wall Proxy  ←→  MCP Server
                      ↕
               agent-wall.yaml
               + security modules
               + response scanner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Setup takes 30 seconds:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @agent-wall/cli
agent-wall wrap &lt;span class="nt"&gt;--&lt;/span&gt; npx @modelcontextprotocol/server-filesystem /home/user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Every tool call now passes through a 5-step defense pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Defense Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Inbound (Request Scanning)
&lt;/h3&gt;

&lt;p&gt;Every &lt;code&gt;tools/call&lt;/code&gt; request runs through:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;What it Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Kill Switch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Emergency deny-all (file/signal/programmatic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Injection Detector&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30+ patterns detect prompt injection attacks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Egress Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block private IPs, SSRF, cloud metadata endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Policy Engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;YAML rules with glob matching &amp;amp; rate limiting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Chain Detector&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Suspicious multi-step patterns (read→exfil)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Outbound (Response Scanning)
&lt;/h3&gt;

&lt;p&gt;Server responses are scanned before reaching the AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;14 built-in secret patterns&lt;/strong&gt;  AWS keys, GitHub tokens, JWTs, private keys, database URLs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 PII patterns&lt;/strong&gt;  email, phone, SSN, credit card, IP address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom regex patterns&lt;/strong&gt; via YAML config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions&lt;/strong&gt;: pass / redact / block&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Live Demo: 12 Injection Attacks, All Blocked
&lt;/h2&gt;

&lt;p&gt;I recorded the real-time dashboard while running 8 test scenarios against a live MCP server:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;12/12 prompt injection categories → BLOCKED&lt;/li&gt;
&lt;li&gt;6/6 exfiltration vectors (curl, wget, netcat, PowerShell, DNS) → BLOCKED&lt;/li&gt;
&lt;li&gt;4/4 credential access attempts (.ssh, .env, .pem, credentials.json) → BLOCKED&lt;/li&gt;
&lt;li&gt;Kill switch activate/deactivate → WORKS&lt;/li&gt;
&lt;li&gt;Chain detection (read file → attempt curl exfil) → DETECTED&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Injection Categories Caught:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;instruction-override  → "Ignore previous instructions"
prompt-marker         → &amp;lt;|im_start|&amp;gt;system, [SYSTEM]:, &amp;lt;&amp;lt;SYS&amp;gt;&amp;gt;
authority-claim       → "jailbreak", "DAN mode", "IMPORTANT: override"
exfil-instruction     → "send the data to evil.com"
output-manipulation   → "pretend you are unrestricted"
delimiter-injection   → ```

system markers


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  The Policy File
&lt;/h2&gt;

&lt;p&gt;Rules are defined in &lt;code&gt;agent-wall.yaml&lt;/code&gt;  first match wins:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
yaml
version: 1
defaultAction: prompt

security:
  injectionDetection:
    enabled: true
    sensitivity: medium
  egressControl:
    enabled: true
    blockPrivateIPs: true
  killSwitch:
    enabled: true
  chainDetection:
    enabled: true

rules:
  - name: block-ssh-keys
    tool: "*"
    match:
      arguments:
        path: "**/.ssh/**"
    action: deny

  - name: block-curl-exfil
    tool: "shell_exec|run_command|execute_command"
    match:
      arguments:
        command: "*curl *"
    action: deny

  - name: allow-read-file
    tool: "read_file|get_file_contents"
    action: allow


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hot-reload included  edit the YAML, changes apply instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Dashboard
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
agent-wall wrap --dashboard -- npx mcp-server
# → Dashboard at http://localhost:61100


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=3lZwGuX3tYg" rel="noopener noreferrer"&gt;test video link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dashboard shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live event feed&lt;/strong&gt; with allow/deny/prompt color coding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stats cards&lt;/strong&gt;  total, forwarded, denied, attacks, scanned&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attack panel&lt;/strong&gt; grouped by category (injections, SSRF, chains)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rule hit table&lt;/strong&gt; with visual bars (sortable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kill switch toggle&lt;/strong&gt; with confirmation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit log&lt;/strong&gt; with search &amp;amp; filter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All via WebSocket — updates in real-time as tool calls flow through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

packages/
  core/        @agent-wall/core       — Proxy engine, policy, security modules
  cli/         @agent-wall/cli             — CLI (wrap, init, test, audit, scan, validate, doctor)
  dashboard/   @agent-wall/dashboard  — React SPA for real-time monitoring


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key decisions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero MCP SDK dependency&lt;/strong&gt;  own JSON-RPC parser, works with any MCP version&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMAC-SHA256 signed audit logs&lt;/strong&gt; with log rotation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Express, no Socket.IO&lt;/strong&gt;  Node &lt;code&gt;http&lt;/code&gt; + &lt;code&gt;ws&lt;/code&gt; library. Minimal footprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CLI Tools
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
# Wrap any MCP server
agent-wall wrap --dashboard -- npx mcp-server

# Generate starter config
agent-wall init

# Dry-run a tool call against your policy
agent-wall test --tool read_file --arg path=/home/.ssh/id_rsa
# → DENIED by rule "block-ssh-keys"

# Scan for unprotected MCP servers
agent-wall scan

# View audit log
agent-wall audit --log ./audit.log --filter denied

# Validate config
agent-wall validate

# Health check
agent-wall doctor


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;The MCP ecosystem is exploding. There are hundreds of community MCP servers  filesystem, database, git, shell, browser, email. Many are built quickly without security in mind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent Wall protects you regardless of which MCP server you use.&lt;/strong&gt; It operates at the protocol level, enforcing policies on every &lt;code&gt;tools/call&lt;/code&gt; before it reaches the server.&lt;/p&gt;

&lt;p&gt;Think of it as &lt;strong&gt;Cloudflare for AI agents&lt;/strong&gt;  you don't modify your backend, you put a proxy in front.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
npm install -g @agent-wall/cli
agent-wall init
agent-wall wrap -- npx your-mcp-server


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/agent-wall/agent-wall" rel="noopener noreferrer"&gt;agent-wall&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/@agent-wall/cli" rel="noopener noreferrer"&gt;agent-wall&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://agent-wall.github.io/agent-wall/" rel="noopener noreferrer"&gt;agent-wall&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Star the repo if you think AI agent security should be a first-class concern, not an afterthought.&lt;/p&gt;

&lt;p&gt;Every AI agent deserves a firewall.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Why I Built nevr-env — And Why process.env Deserves Better</title>
      <dc:creator>yalelet dessalegn</dc:creator>
      <pubDate>Thu, 12 Feb 2026 05:19:32 +0000</pubDate>
      <link>https://dev.to/yalelet_dessalegn_b87ed18/why-i-built-nevr-env-and-why-processenv-deserves-better-4iod</link>
      <guid>https://dev.to/yalelet_dessalegn_b87ed18/why-i-built-nevr-env-and-why-processenv-deserves-better-4iod</guid>
      <description>&lt;p&gt;I got tired of crashing apps, leaked secrets, and copy-pasting .env files on Slack. So I built an environment lifecycle framework.&lt;/p&gt;

&lt;p&gt;Every developer has that moment.&lt;/p&gt;

&lt;p&gt;You deploy on Friday. CI passes. You go home feeling productive.&lt;/p&gt;

&lt;p&gt;Then the ping comes: &lt;strong&gt;"App is crashing in production."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The culprit? &lt;code&gt;DATABASE_URL&lt;/code&gt; was never set. Your app accessed &lt;code&gt;process.env.DATABASE_URL&lt;/code&gt;, got &lt;code&gt;undefined&lt;/code&gt;, and silently passed it as a connection string. Postgres didn't appreciate that.&lt;/p&gt;

&lt;p&gt;I've hit this exact bug more times than I want to admit. And every time, the fix was the same: add another line to &lt;code&gt;.env.example&lt;/code&gt;, hope your teammates read the README, and move on.&lt;/p&gt;

&lt;p&gt;I got tired of hoping. So I built &lt;strong&gt;nevr-env&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually Wrong With .env Files?
&lt;/h2&gt;

&lt;p&gt;Nothing — as a concept. Environment variables are the right way to configure apps. The problem is the &lt;strong&gt;tooling around them&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No validation at startup&lt;/strong&gt; — &lt;code&gt;process.env.PORT&lt;/code&gt; returns &lt;code&gt;string | undefined&lt;/code&gt;. If you forget &lt;code&gt;PORT&lt;/code&gt;, your server silently listens on &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No type safety&lt;/strong&gt; — &lt;code&gt;process.env.ENABLE_CACHE&lt;/code&gt; is &lt;code&gt;"true"&lt;/code&gt; (a string), not &lt;code&gt;true&lt;/code&gt; (a boolean). Every developer writes their own parsing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secret sprawl&lt;/strong&gt; — Your team shares secrets via Slack DMs, Google Docs, or worse. &lt;code&gt;.env.example&lt;/code&gt; is always outdated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Boilerplate everywhere&lt;/strong&gt; — Every new project: copy the Zod schemas, write the same &lt;code&gt;DATABASE_URL: z.string().url()&lt;/code&gt;, same &lt;code&gt;PORT: z.coerce.number()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The t3-env Gap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://env.t3.gg" rel="noopener noreferrer"&gt;t3-env&lt;/a&gt; was a step forward. Type-safe env validation with Zod. I used it. I liked it.&lt;/p&gt;

&lt;p&gt;But as my projects grew, the gaps showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Every. Single. Project.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEnv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;REDIS_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sk_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;STRIPE_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;whsec_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sk-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;re_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// ... 20 more lines of the same patterns&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was writing the same schemas across 8 projects. When Stripe changed their key format, I had to update all of them.&lt;/p&gt;

&lt;p&gt;And when a new teammate joined? They'd clone the repo, run &lt;code&gt;npm run dev&lt;/code&gt;, see a wall of validation errors, and spend 30 minutes figuring out what goes where.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I Built nevr-env
&lt;/h2&gt;

&lt;p&gt;nevr-env is an &lt;strong&gt;environment lifecycle framework&lt;/strong&gt;. Not just validation — the entire lifecycle from setup to production monitoring.&lt;/p&gt;

&lt;p&gt;Here's what the same code looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createEnv&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nevr-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;postgres&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nevr-env/plugins/postgres&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nevr-env/plugins/stripe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nevr-env/plugins/openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEnv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;API_SECRET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 plugins replace 15+ lines of manual schemas. Each plugin knows the correct format, provides proper validation, and even includes &lt;strong&gt;auto-discovery&lt;/strong&gt; — if you have a Postgres container running on Docker, the plugin detects it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Features That Changed Everything
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Interactive Fix Wizard
&lt;/h3&gt;

&lt;p&gt;When a new developer runs your app with missing variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx nevr-env fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of a wall of errors, they get an interactive wizard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? DATABASE_URL is missing
  This is: PostgreSQL connection URL
  Format: postgresql://user:pass@host:port/db
  &amp;gt; Paste your value: █
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onboarding time went from "ask someone on Slack" to "run one command."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Encrypted Vault
&lt;/h3&gt;

&lt;p&gt;This is the feature I'm most proud of.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a key (once per team)&lt;/span&gt;
npx nevr-env vault keygen

&lt;span class="c"&gt;# Encrypt your .env into a vault file&lt;/span&gt;
npx nevr-env vault push
&lt;span class="c"&gt;# Creates .nevr-env.vault (safe to commit to git!)&lt;/span&gt;

&lt;span class="c"&gt;# New teammate clones repo and pulls&lt;/span&gt;
npx nevr-env vault pull
&lt;span class="c"&gt;# Decrypts vault → creates .env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vault file uses &lt;strong&gt;AES-256-GCM&lt;/strong&gt; encryption with &lt;strong&gt;PBKDF2 600K iteration&lt;/strong&gt; key derivation. It's safe to commit to git. The encryption key never touches your repo.&lt;/p&gt;

&lt;p&gt;No more Slack DMs. No more "hey can you send me the .env?" No more paid secret management SaaS for small teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Secret Scanning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx nevr-env scan

  Found 2 secrets &lt;span class="k"&gt;in &lt;/span&gt;codebase:

  CRITICAL  src/config.ts:14  AWS Access Key &lt;span class="o"&gt;(&lt;/span&gt;AKIA...&lt;span class="o"&gt;)&lt;/span&gt;
  HIGH      lib/api.ts:8      Stripe Secret Key &lt;span class="o"&gt;(&lt;/span&gt;sk_live_...&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs in CI and catches secrets before they hit your git history. Built-in, no extra tools needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  13 Plugins and Counting
&lt;/h2&gt;

&lt;p&gt;Every plugin encapsulates the knowledge of how a service works:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Plugins&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;postgres()&lt;/code&gt;, &lt;code&gt;redis()&lt;/code&gt;, &lt;code&gt;supabase()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clerk()&lt;/code&gt;, &lt;code&gt;auth0()&lt;/code&gt;, &lt;code&gt;better-auth()&lt;/code&gt;, &lt;code&gt;nextauth()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payment&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stripe()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;td&gt;&lt;code&gt;resend()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Presets&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;vercel()&lt;/code&gt;, &lt;code&gt;railway()&lt;/code&gt;, &lt;code&gt;netlify()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And you can create your own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nevr-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;MY_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;MY_API_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Full CLI
&lt;/h2&gt;

&lt;p&gt;nevr-env ships with 12 CLI commands:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set up nevr-env in your project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Validate all env vars (CI-friendly)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Interactive wizard for missing vars&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-generate &lt;code&gt;.env.example&lt;/code&gt; from schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;types&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate &lt;code&gt;env.d.ts&lt;/code&gt; type definitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find leaked secrets in code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compare schemas between versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rotate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Track secret rotation status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ci&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate CI config (GitHub Actions, Vercel, Railway)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Validate + run your dev server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Live-reload validation on .env changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vault&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Encrypted secret management (keygen/push/pull/status)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add nevr-env zod
npx nevr-env init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The init wizard detects your framework, finds running services, and generates a complete configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/nevr-ts/nevr-env" rel="noopener noreferrer"&gt;github.com/nevr-ts/nevr-env&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://npmjs.com/package/nevr-env" rel="noopener noreferrer"&gt;npmjs.com/package/nevr-env&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Docs&lt;/strong&gt;: [&lt;a href="https://nevr-ts.github.io/nevr-env/" rel="noopener noreferrer"&gt;https://nevr-ts.github.io/nevr-env/&lt;/a&gt;)&lt;/p&gt;




&lt;p&gt;If you've ever lost production time to a missing env var, I'd love to hear your story. And if nevr-env saves you from that — a star on GitHub would mean the world.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/nevr-ts" rel="noopener noreferrer"&gt;Yalelet Dessalegn&lt;/a&gt; as part of the nevr-ts ecosystem.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>devchallenge</category>
    </item>
  </channel>
</rss>
