You Need To Stop Using Naked Environment Variables Today!

David Peter

July 28, 2023

#guide

#dotenv

#convict

#konfig

You Need To Stop Using Naked Environment Variables Today!

Environment variables are a way to store sensitive information like API keys, database passwords, and other secrets. Naked environment variables are those that are hardcoded directly into the code or configuration files.

Using naked environment variables can lead to security vulnerabilities, as they can be easily accessed by anyone with access to the codebase. dotenv is a popular npm package used to load environment variables from a .env file into process.env. It's important to carefully consider what information is stored in environment variables and who has access to them.

Why Naked Environment Variables Are a Problem 

First, let's discuss why using naked environment variables can lead to serious issues. These variables are often used to store sensitive information such as API keys, passwords, and database credentials. If these details fall into the wrong hands, it can lead to severe security breaches. 

The Misuse of dotenv 

dotenv is undoubtedly a useful tool, but its misuse, particularly in the node.js and deno communities, is alarming. These environment variables, if not handled appropriately, can pose serious security risks. So, it's time to rethink strategy, folks!

Generic security concerns aside. 

Naked Environment Variables Are A Mess

Let's face it, folks. Naked environment variables are like a spilled bag of M&M's – colorful, chaotic, and impossible to manage effectively. These unadorned variables, as unassuming as they may seem, can create a mess faster than a toddler with a paintbrush. 

Why, you ask? Because they lack context. They're just hanging out there in the open, devoid of any meaningful definition or structure. And in the world of programming, that's a recipe for disaster. 

VITE_FIREBASE_APIKEY="----"
VITE_FIREBASE_AUTH_DOMAIN="---"
VITE_FIREBASE_PROJECT_ID="---"
VITE_FIREBASE_STORAGE_BUCKET="---"
VITE_FIREBASE_MESSAGING_SENDER_ID="---"
VITE_FIREBASE_APP_ID="---"
VITE_FIREBASE_MEASUREMENT_ID="---"
VITE_DGRAPH_ENDPOINT="---"

Naked environment variables lack context and are hard to read.

The Dangers of Unstructured Chaos 

Imagine throwing a party and forgetting to assign roles to your helpers. Chaos ensues. It's the same with naked environment variables. When not properly managed, they create confusion, leading to potential bugs, security risks, and maintenance nightmares. 

Remember: In programming, clarity and structure are not just nice-to-haves; they're absolute necessities.

Enter Dotenv: A Double-Edged Sword 

Dotenv seems like the solution, doesn't it? This tool allows you to shove all your environment variables into one .env file. But here's where things get tricky. Without proper consideration for what these variables represent and the requirements they must fulfill, Dotenv can be as dangerous as it is helpful. 

dotenvProCon
Helps manage environment variablesCan create security risks if misused
Simplifies variable storageCan lead to maintenance issues

In the wrong hands, Dotenv can be like an overzealous cleaner who tidies up so well that you can't find anything anymore. And that's not what we want, is it? 

Enter Convict: Structured coniguration management.

Alright, let's talk Convict. It's the knight in shining armor in the world of structured configuration management. You see, when we use Convict, we start to move away from the dangerous territory of naked environment variables. 

Here's the thing. Convict makes the management of environment variables not just safer, but also more straightforward. It lets you define a schema for your configuration, enforcing rules and removing the risk of potential errors. 

But why does this matter? I hear you ask. Well, the beauty of Convict is in its ability to validate and transform environment variables, ensuring they are in the right format and adhering to the specified rules. 

Let's paint a picture. Imagine you're developing an application that requires a port number. Without Convict, you could easily end up with an incorrect port number, and boom, your app crashes. But with Convict? It checks the port number to ensure it's within the appropriate range, preventing an error from bringing your app down. 

And it gets better. With Convict, you can set default values for your environment variables. So, if a particular value isn't set, your application won't crash, instead it'll just use the default. Now that's what we call a safety net! 

Convict: The Breath of Fresh Air 

With Convict, we can finally breathe a sigh of relief. No more worrying about unexpected crashes or errors due to incorrect environment variables. It handles all the heavy-lifting, providing a structured configuration that's easy to manage and maintain. 

So, if you've been clinging onto naked environment variables, it's time to let them go. Embrace Convict, and introduce a safer, more structured approach to your configuration management. Trust me, it's a game-changer

const conf = convict({  
  ip: {  
    doc: 'The IP Address to bind.',  
    format: 'ipaddress',  
    default: '127.0.0.1',  
    env: 'IP\_ADDRESS'  
  },  
  port: {  
    doc: 'The port to bind.',  
    format: 'int',  
    default: 0,  
    env: 'PORT'  
  }  
}).loadFile(path.join(\_\_dirname, 'config.json')).validate()

Enter Konfig: Type-Safe configuration management

Take a minute and visit this URL: https://deno.land/x/konfig. What you'll find is a tool that provides a smarter, safer way to handle environment variables in your Node.js or Deno applications. It's a breath of fresh air, and it's about time we all started using it. 

Functional, type-safe, web standard configuration management with structure and validation built in.

import {
  json,
  number,
  string,
  struct,
} from "https://deno.land/x/fun@v2.0.0-alpha.10/decoder.ts";
import { pipe } from "https://deno.land/x/fun@v2.0.0-alpha.10/fn.ts";
import { bind, env, extract, fallback, flag, schema } from "konfig";

export const config = pipe(
  schema({
    env: [
      env("FOOBAR"),
      fallback("foo"),
    ],
    arg: [
      flag("foo", number),
      fallback(1),
    ],
    composed: [
      env("BAZ"),
      flag("bar"),
      fallback("foobar"),
    ],
    jsonValue: [
      env("JSON\_VAL", json(struct({ foo: string }))),
      fallback({ foo: "bar" }),
    ],
    naked: {
      foo: env("FOO"),
      env: [env("NESTED"), fallback("nested")],
    },
  }),
  bind("bound", ({ env, arg, composed }) => `${env}-${arg}-${composed}`),
  extract,
);

type Config = typeof config;
/*
type Config = {
  env: string;
  arg: number;
  composed: string;
  jsonValue: {
      readonly foo: string;
  };
  naked: {
      foo: string;
      env: string;
      nestedNaked: {
          env: string;
      };
  };
  bound: string;
}
*/

console.log(JSON.stringify(config, null, 4));
/* Outputs
{
    "env": "foo",
    "arg": 1,
    "composed": "foobar",
    "jsonValue": {
        "foo": "bar"
    },
    "naked": {
        "foo": "foo",
        "env": "nested",
        "nestedNaked": {
            "env": "nested-nested"
        }
    },
    "bound": "foo-1-foobar"
}
*/

Embrace the Future with Konfig 

The future of environment variable management lies in tools like Konfig. These tools take environment variables and package them up in a neat, secure manner. It’s like hiring a security guard for your application’s most sensitive data.

So, let's stop using naked environment variables. Today.

Talk with us!

No strings attached 15-min call.

Type Driven unlocks competitive advantage by surgically engineering business success through robust type systems, functional programming, and deep technology expertise.