- Description:
The cookiecutter‑django template (by default) commits local environment files containing sensitive values (such as the Django SECRET_KEY, database credentials, and API keys). An external attacker who probes a public repository may locate these files (for example,
.env
and files under the.envs/
directories) and harvest sensitive information.- An attacker could search for filenames like
.env
,.envs/.production/.django
, or.envs/.production/.postgres
and retrieve their contents. - The presence of a merge script (
merge_production_dotenvs_in_dotenv.py
) indicates that production environment files are merged together. If these files are not excluded from version control, they are at risk of exposure.
- An attacker could search for filenames like
- Impact:
- Disclosure of critical secrets might allow attackers to hijack sessions, bypass authentication, tamper with data, or compromise external services (such as email, databases, and cloud storage) that depend on these credentials.
- Vulnerability Rank: High
- Currently Implemented Mitigations:
- The documentation and interactive prompts ask developers whether to track local environment files (defaulting to “y”).
- Settings files—both production and local—load sensitive values from environment variables.
- Environment files are organized under subdirectories (e.g.
.envs/.production/
) to compartmentalize configurations.
- Missing Mitigations:
- The secure‑by‑default approach is not enforced; the default “y” option means many projects will inadvertently expose these files.
- No automated post‑generation hook exists to remove or ignore local environment files from version control.
- No in‑template validation warns if committed environment files contain critical secrets.
- Preconditions:
- The project is generated with the default option (keep_local_envs_in_vcs = “y”).
- The repository is publicly accessible or its access controls are misconfigured.
- Source Code Analysis:
- Template files and README documents reveal that developers are asked about tracking env files but the default remains insecure.
- The file
merge_production_dotenvs_in_dotenv.py
indicates that multiple environment files are meant to be merged into one.env
, increasing the risk if they are tracked. - Production settings (e.g. in
config/settings/production.py
) load secrets from environment variables, thereby nullifying the security benefit if those secrets are committed.
- Security Test Case:
- Generate a new project using the cookiecutter‑django template with the default setting (keep_local_envs_in_vcs = “y”).
- Inspect the generated repository to verify that files such as
.env
and directories like.envs/
(e.g..envs/.production/.django
) exist. - Push the repository to a public GitHub instance.
- From an external machine (or by using file search tools), locate these environment files.
- Confirm that the file contents include sensitive keys and credentials.
- Description:
The template pins key dependency versions (as observed in
pyproject.toml
and various requirements files) so that, unless manually updated, projects may continue to use libraries that later are found to have vulnerabilities.- Although automated workflows (e.g. Dependabot and a pre‑commit auto‑update workflow) run daily to update dependency versions for non‑breaking changes, these tools are intentionally configured to ignore major (and sometimes minor) updates.
- An attacker may exploit known vulnerabilities in libraries such as Django, Celery, django‑allauth, etc. that remain unpatched due to the automated rules skipping major updates.
- Impact:
- Exploitation of known issues in outdated library versions might allow attackers to execute remote code, bypass authentication, inject SQL, or leak data.
- Continuously relying on outdated dependencies expands the attack surface by leaving unpatched security flaws available.
- Vulnerability Rank: High
- Currently Implemented Mitigations:
- A
.github/dependabot.yml
file schedules daily updates for pip packages, npm packages, GitHub Actions, and Docker images. - A
pre-commit-autoupdate.yml
workflow updates pre‑commit hooks daily. - Additional workflows (such as
update-changelog.yml
andalign-versions.yml
) help track dependency changes.
- A
- Missing Mitigations:
- Automated tools are configured to ignore major (and in some cases minor) version updates, leaving a window during which critical vulnerabilities from major release updates persist.
- There is no enforced manual review or upgrade mechanism when a dependency issue with a major release is discovered.
- Preconditions:
- The project is generated from an older commit or the developer chooses not to manually upgrade to new major versions.
- Outdated dependency versions containing known security issues remain installed.
- Source Code Analysis:
- The
pyproject.toml
file pins specific versions for dependencies (e.g. Django, djlint, pytest, etc.); while these versions are secure at the time of generation, they may become vulnerable if not updated. - The
.github/dependabot.yml
file schedules daily updates but includes ignore rules that skip major/minor updates for some ecosystems (such as Docker images). - Automation workflows (for pre‑commit, dependency locking, and changelogs) update only non‑breaking changes.
- The
- Security Test Case:
- Generate a new project using the cookiecutter‑django template.
- Examine dependency version pins in files such as
pyproject.toml
,requirements/local.txt
, and Dockerfiles. - Run an automated dependency scanner (e.g. Safety or Snyk) against the project to identify version-based vulnerabilities.
- For a dependency documented to have a security issue in a new major version, craft an HTTP request (or similar attack vector) that exploits that vulnerability in the running application.
- Confirm the exploitability of the vulnerability, demonstrating that outdated dependencies can endanger the system.
- Description:
When a project is generated with the
debug
option set to"y"
, the post‑generation hook (inhooks/post_gen_project.py
) uses a constant value ("debug"
) for critical secret keys instead of generating cryptographically secure random values. This misconfiguration results in weak (predictable) secret keys and may leave the Django application running in debug mode.- An attacker may deliberately trigger errors in the deployed application (which is running in debug mode) to reveal detailed error pages, stack traces, and configuration details.
- The use of the weak, constant
"debug"
string in place of unique, random secret keys (e.g. Django’sSECRET_KEY
, database passwords, and Celery passwords) makes it trivial for an attacker to guess these values.
- Impact:
- Exposing the Django debug error pages can reveal sensitive internal configuration details, code paths, and stack traces.
- With predictable secret keys, session hijacking, forgery of cookies, or even remote code execution become easier to achieve.
- In a production environment, leaving debug mode enabled represents a critical security oversight.
- Vulnerability Rank: Critical
- Currently Implemented Mitigations:
- The post‑generation script in
hooks/post_gen_project.py
sets secret keys in files by calling the functionset_flags_in_envs()
. When debug mode is off, a secure random value is generated viagenerate_random_user()
.
- The post‑generation script in
- Missing Mitigations:
- There is no enforcement or check that ensures debug mode is turned off in production deployments.
- The template does not prevent a project from being generated with
debug = "y"
, nor does it validate that secret keys are replaced with cryptographically secure random values in all cases. - No warning is emitted to developers if the generated production environment uses the constant
"debug"
value.
- Preconditions:
- The project is generated with the
debug
option set to"y"
. - The generated project is deployed to a production environment without altering the insecure default secret values.
- The project is generated with the
- Source Code Analysis:
- In
hooks/post_gen_project.py
, the variableDEBUG_VALUE
is defined as"debug"
. - In the
main()
function, the expressiondebug = "{{ cookiecutter.debug }}".lower() == "y"
determines whether debug mode is enabled. - When debug mode is active, the call
set_flags_in_envs(DEBUG_VALUE if debug else generate_random_user(), DEBUG_VALUE if debug else generate_random_user(), debug=debug)
passesDEBUG_VALUE
for key settings instead of generating random values. - Consequently, the production Django environment file (e.g.
.envs/.production/.django
) ends up with predictable values.
- In
- Security Test Case:
- Use the cookiecutter‑django template to generate a new project with the prompt set to
debug = "y"
. - Inspect the generated environment files (for example,
.envs/.production/.django
) and verify that critical secrets—such as the DjangoSECRET_KEY
—are set to the constant value"debug"
. - Deploy the project with this configuration.
- Intentionally trigger an unhandled error (for example, by navigating to a non‑existent URL) to prompt Django’s debug error page.
- Observe that the detailed error page is displayed and confirm that sensitive information (including the weak secret keys) is revealed.
- Demonstrate that the use of predictable secret values can lead to session forgery or other attack scenarios.
- Use the cookiecutter‑django template to generate a new project with the prompt set to