{"library":"pyyaml-env-tag","title":"PyYAML Environment Variable Tag","description":"pyyaml-env-tag (current version 1.1) is a Python library that provides a custom YAML tag (!ENV) for referencing environment variables within YAML files. This allows for dynamic configuration and injecting sensitive data securely. It builds upon the PyYAML library. The project has seen recent releases in 2025, suggesting active maintenance, though official release cadence isn't explicitly stated beyond these updates.","status":"active","version":"1.1","language":"en","source_language":"en","source_url":"https://github.com/waylan/pyyaml-env-tag","tags":["yaml","environment variables","configuration","pyyaml"],"install":[{"cmd":"pip install pyyaml-env-tag","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"This library extends PyYAML functionality, requiring it for YAML parsing and emitting.","package":"pyyaml"}],"imports":[{"note":"The primary helper function to enable the !ENV tag on a PyYAML loader.","symbol":"add_env_tag","correct":"from yaml_env_tag import add_env_tag"},{"note":"Lower-level constructor function for direct integration with PyYAML's add_constructor method.","symbol":"construct_env_tag","correct":"from yaml_env_tag import construct_env_tag"}],"quickstart":{"code":"import yaml\nimport os\nfrom yaml_env_tag import add_env_tag\n\n# Create a YAML string with environment variable tags\nyaml_content = \"\"\"\ndatabase:\n  host: !ENV DB_HOST\n  port: !ENV [DB_PORT, 5432] # Uses 5432 if DB_PORT is not set\n  user: !ENV [DB_USER, default_user] # Uses 'default_user' if DB_USER is not set\napi_key: !ENV [API_KEY_SECRET, FALLBACK_API_KEY, \"no_api_key_set\"]\n\"\"\"\n\n# Set some environment variables for testing\nos.environ['DB_HOST'] = 'localhost'\nos.environ['API_KEY_SECRET'] = 'my_super_secret_key'\n# DB_PORT, DB_USER, and FALLBACK_API_KEY are intentionally not set to demonstrate fallbacks\n\n# Get a PyYAML SafeLoader and add the environment tag constructor to it.\n# It's crucial to use SafeLoader for security with untrusted YAML.\nSafeEnvLoader = add_env_tag(yaml.SafeLoader)\n\n# Load the YAML content\nconfig = yaml.load(yaml_content, Loader=SafeEnvLoader)\n\nprint(\"Loaded Configuration:\")\nprint(config)\n\n# Clean up environment variables (good practice, especially in automated tests)\ndel os.environ['DB_HOST']\ndel os.environ['API_KEY_SECRET']\n\n# Expected output:\n# Loaded Configuration:\n# {\n#   'database': {'host': 'localhost', 'port': 5432, 'user': 'default_user'},\n#   'api_key': 'my_super_secret_key'\n# }","lang":"python","description":"This quickstart demonstrates how to load YAML content containing `!ENV` tags, which resolve to environment variable values or specified defaults. It highlights the use of `add_env_tag` with `yaml.SafeLoader` for secure parsing and showcases both single variable and fallback sequence syntaxes. Set environment variables using `os.environ` before loading the YAML."},"warnings":[{"fix":"Always use `yaml.safe_load()` or explicitly pass `Loader=add_env_tag(yaml.SafeLoader)` to `yaml.load()` when loading YAML from untrusted or unknown sources. The `add_env_tag` function modifies your chosen loader, so always pass `yaml.SafeLoader` for security.","message":"Using `yaml.load()` (without specifying `Loader=`) is inherently unsafe, as it can parse arbitrary Python objects and potentially execute malicious code from untrusted YAML sources. This applies to `pyyaml-env-tag` as it extends PyYAML's loading capabilities.","severity":"gotcha","affected_versions":"<=1.1"},{"fix":"Ensure the last item in a fallback sequence is intended to be a literal default value. If you want `VAR2` to be another environment variable lookup, and have a final literal default, explicitly add it: `!ENV [VAR1, VAR2, 'final_literal_default']`.","message":"When using the sequence syntax for fallbacks (e.g., `!ENV [VAR1, VAR2, default]`), the *last* item in the sequence is always treated as a literal default value and will not itself be resolved as an environment variable name. It will be resolved to a Python object of its implied type (e.g., string, integer, boolean). If you intend `VAR2` to also be an environment variable name to be looked up, this behavior is correct. However, if the sequence only has two items like `!ENV [VAR1, VAR2]`, `VAR2` will be treated as the literal default, not as an environment variable name to resolve.","severity":"gotcha","affected_versions":"<=1.1"}],"env_vars":null,"last_verified":"2026-04-05T00:00:00.000Z","next_check":"2026-07-04T00:00:00.000Z"}