Skip to main content

A secure drop-in replacement for python-decouple with startup validation

Project description

secretsguardian

A secure drop-in replacement for python-decouple with startup validation.


Install

pip install secretsguardian

One-line migration from python-decouple

# Before
from decouple import config

# After — identical behaviour, one line change
from secretsguardian import config

Zero other changes required. Every existing call works identically.


Quick start — Django settings.py

from secretsguardian import config, require

# Block startup immediately if any of these are missing from the environment
require('SECRET_KEY', 'DATABASE_URL', 'STRIPE_KEY', 'EMAIL_HOST_PASSWORD')

# Validate strength at startup — never lazily during a request
SECRET_KEY = config('SECRET_KEY', min_length=50, reject_insecure=True)
DATABASE_URL = config('DATABASE_URL')
STRIPE_KEY = config('STRIPE_KEY', min_length=32)
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')

# All existing decouple usage works without any changes
DEBUG = config('DEBUG', default=False, cast=bool)
PORT  = config('PORT',  default=8000,  cast=int)

Feature 1 — Secret Strength Validation

config() accepts two new optional parameters:

min_length=int

Raises WeakSecretError if the resolved value is shorter than the given number of characters.

SECRET_KEY = config('SECRET_KEY', min_length=50)

Error output:

[secretsguardian] SECRET_KEY failed validation: too short.
Minimum length is 50 characters. Update your .env file.

reject_insecure=True

Raises InsecureSecretError if the value starts with django-insecure-.

SECRET_KEY = config('SECRET_KEY', reject_insecure=True)

Error output:

[secretsguardian] SECRET_KEY failed validation: insecure default value detected.
Django's default 'django-insecure-' key must not be used in production.
Generate a new key and update your .env file.

Both parameters can be combined:

SECRET_KEY = config('SECRET_KEY', min_length=50, reject_insecure=True)

Feature 2 — Startup Secrets Checklist

require() accepts any number of secret name strings. It checks every listed secret at startup, collects all missing names, and raises a single MissingSecretsError listing them together.

require('SECRET_KEY', 'DATABASE_URL', 'STRIPE_KEY', 'EMAIL_HOST_PASSWORD')

Error output when several secrets are missing:

[secretsguardian] Application startup blocked. The following required secrets are missing:

  - DATABASE_URL
  - STRIPE_KEY
  - EMAIL_HOST_PASSWORD

Add these to your .env file before starting the application.

Call require() before any config() calls in settings.py.


Parameter Reference

config(key, *, default=..., cast=None, min_length=None, reject_insecure=False)

Parameter Type Default Description
key str required Environment variable name
default any Fallback value when key is absent (passed to decouple)
cast callable None Type cast function e.g. int, bool (passed to decouple)
min_length int None Minimum character length for the resolved value
reject_insecure bool False Reject values starting with django-insecure-

require(*secret_names)

Parameter Type Description
*secret_names str One or more environment variable names to check

Exceptions

All exceptions inherit from EnvGuardianError, so you can catch them all with a single clause:

from secretsguardian.exceptions import EnvGuardianError

try:
    require('SECRET_KEY')
    SECRET_KEY = config('SECRET_KEY', min_length=50, reject_insecure=True)
except EnvGuardianError as e:
    # Handle all secretsguardian errors in one place
    raise SystemExit(e)
Exception Raised when
EnvGuardianError Base class for all secretsguardian errors
WeakSecretError Value is shorter than min_length
InsecureSecretError Value starts with django-insecure-
MissingSecretsError One or more required secrets are absent

Test mode

When any of the following environment variables are present, all secretsguardian validation is skipped silently. The package behaves identically to plain decouple.

Variable Value that activates test mode
ENV test
DJANGO_ENV test
TESTING true

This means your test suite can use placeholder or missing values without any changes:

ENV=test pytest

or in pytest.ini / conftest.py:

import os
os.environ.setdefault("ENV", "test")

Security guarantees

  • Secret values never appear in any error message, log, or output — only secret names.
  • No network calls anywhere in the package. All validation runs locally.
  • All validation happens at app startup, never lazily during a live request.
  • Errors are human-readable and tell you exactly what is wrong and how to fix it.

License

MIT. secretsguardian is a drop-in replacement for python-decouple with added security validation. It imports python-decouple as a dependency; no source code is copied.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

secretsguardian-0.1.0.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

secretsguardian-0.1.0-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file secretsguardian-0.1.0.tar.gz.

File metadata

  • Download URL: secretsguardian-0.1.0.tar.gz
  • Upload date:
  • Size: 7.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for secretsguardian-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1c3191a99317035daddb3bf95aa3a80d8c56877a5bd1245d70a6455bb1d6cb5b
MD5 6848d075fb3fe871846889f01c13fe09
BLAKE2b-256 fe08a3a903c9ccbb2d220ab90d06ad86eefa9165c1febb3e79f65916327d0c21

See more details on using hashes here.

File details

Details for the file secretsguardian-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for secretsguardian-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f087824e2a12b7c9718c5bd9e43d0c3e66c8225048c9f2248e9dbff65c669ad
MD5 5cf1a632d2343304e4a71ee6692a7d48
BLAKE2b-256 0eaeb4ba9bcb66ce2acdbf02c3ef93c22060b0f1b3fa4f1d5682e1de84693b93

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page