Introduction

When developers prepare a Django project for production, they usually focus on visible deployment tasks: setting DEBUG = False, configuring the database, collecting static files, setting up Gunicorn, configuring Nginx, enabling HTTPS, and testing the main pages.

These steps are important, but they are not enough.

A modern Django project is not only your own code. It is also a collection of third-party Python packages, system libraries, Docker image layers, JavaScript assets, deployment tools, and configuration files. Every package you install becomes part of your application’s security surface.

A vulnerable package can expose your website even if your own Django views, models, forms, and templates are well written. An old Docker base image, an unpinned requirements.txt file, or a forgotten dependency can create production risks that are difficult to detect after deployment.

This is why dependency security should be part of every Django production checklist.

In this guide, you will learn how to secure Python and Django dependencies before production deployment using practical tools and repeatable steps. We will cover package auditing, pinned versions, pip-tools, SBOM generation, Docker image scanning, CI/CD checks, Dependabot, and a final production checklist that you can reuse before deploying any Django website.

 

Table of Contents

  1. What dependency security means in Django
  2. Why Python dependencies can become a production risk
  3. Common dependency mistakes in Django projects
  4. How to audit packages with pip-audit
  5. How to pin and lock dependencies correctly
  6. How to separate development and production requirements
  7. How to generate an SBOM for a Python project
  8. How to scan Docker images before deployment
  9. How to add dependency security checks to CI/CD
  10. How to use Dependabot for long-term maintenance
  11. Production dependency security checklist
  12. Common mistakes
  13. Best practices
  14. Troubleshooting
  15. FAQ
  16. Conclusion

 

What Dependency Security Means in a Django Project

Dependency security means identifying, controlling, updating, and monitoring the external packages and software components used by your application.

In a Django project, this usually includes:

  • Python packages installed with pip
  • Django itself
  • Django extensions such as django-csp, django-ckeditor, djangorestframework, or django-allauth
  • Database drivers such as psycopg, psycopg2, or mysqlclient
  • Authentication and security libraries
  • Background task tools such as Celery and Redis clients
  • Docker base images
  • Operating system packages installed inside Docker images
  • Frontend dependencies if your project uses npm, Tailwind, Bootstrap build tools, or JavaScript packages

For a small local project, dependencies may feel simple. You install a package, test the feature, and continue coding. In production, however, each dependency must be treated as part of the application.

If the package has a known vulnerability, an unsafe default configuration, or an abandoned maintenance status, it can become a real risk.

 

Why Dependency Security Matters Before Production Deployment

A Django website in production is exposed to real users, bots, crawlers, scanners, and attackers.

Even if your website is small, automated scanners can find public applications and test them for known weaknesses. Attackers do not need to understand your whole business. They only need one vulnerable package, one exposed admin endpoint, one weak configuration, or one outdated image.

Dependency security matters because Django applications are built on many layers:

  • Your Django code
  • Your installed Python packages
  • Your Python runtime
  • Your WSGI or ASGI server
  • Your Docker image
  • Your Linux packages
  • Your database and cache services
  • Your Nginx or reverse proxy configuration

If one of these layers is outdated or vulnerable, the whole deployment can be affected.

That is why dependency scanning should happen before production deployment, not only after a problem appears.

 

Common Dependency Risks in Django Projects

1. Using an Old Django Version

Django is actively maintained, but security fixes are released only for supported versions. If your project uses an old unsupported version, you may not receive important security fixes.

Before deployment, always check your Django version:

 

python -m django --version

 

You can also check the installed package metadata:

 

python -m pip show django

 

If your Django version is old, do not upgrade directly in production. Upgrade in a development branch, run tests, check breaking changes, then deploy to staging first.

 

2. Installing Packages Without Pinning Versions

A common mistake is writing requirements like this:

Django
djangorestframework
psycopg
gunicorn
redis

 

This is dangerous for production because the installed versions can change between environments.

Your local machine, staging server, and production server may not install the same versions. A future deployment may install a newer package version that breaks your application or introduces behavior you did not test.

A safer production requirements file uses exact versions:

Django==5.2.1
djangorestframework==3.16.0
psycopg==3.2.9
gunicorn==23.0.0
redis==5.2.1

 

Pinned versions make your deployments more predictable.

 

3. Ignoring Transitive Dependencies

You may install only ten packages directly, but those packages can install many other dependencies.

These indirect packages are called transitive dependencies.

For example, your project may install package A. Package A may install package B and package C. You did not manually install B or C, but they are still part of your production environment.

A vulnerability can exist in a package that you never manually added to your requirements.txt, but it still exists inside your environment because another package requires it.

That is why dependency scanning tools are important.

 

4. Installing Packages Directly on the Server

Production servers should be reproducible.

If you connect to the server and manually run:

 

pip install some-package

 

you create an environment that may not match your Git repository.

This makes debugging, rollback, and disaster recovery more difficult.

A production server should install dependencies only from committed dependency files, such as:

 

pip install -r requirements/prod.txt

 

or through a Docker image that was built and tested before deployment.

 

5. Forgetting Docker Image Vulnerabilities

Even if your Python packages are safe, your Docker image may contain vulnerable operating system packages.

Docker images are made of layers. Those layers can include system libraries, package managers, build tools, and runtime dependencies.

For example, a Django Docker image may contain:

  • Python runtime
  • Debian or Alpine packages
  • PostgreSQL client libraries
  • Build tools
  • OpenSSL libraries
  • CA certificates
  • System utilities

These components must also be scanned before production deployment.

 

Step 1: Create a Clean Virtual Environment

Before auditing dependencies, start with a clean and reproducible environment.

This helps you avoid confusing old packages, unused libraries, or global Python packages with your actual project dependencies.

 

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel

 

On Windows PowerShell:

 

.venv\Scripts\Activate.ps1

 

Then install your project dependencies:

 

python -m pip install -r requirements.txt

 

If your project uses separate production requirements:

 

python -m pip install -r requirements/prod.txt

 

A clean environment gives you more reliable audit results.

 

Step 2: Audit Python Packages with pip-audit

pip-audit is a tool for scanning Python environments and requirements files for packages with known vulnerabilities.

Install it:

 

python -m pip install pip-audit

 

Scan the current environment:

 

pip-audit

 

Scan a requirements file:

 

pip-audit -r requirements.txt

 

If you have a production requirements file:

 

pip-audit -r requirements/prod.txt

 

Generate JSON output:

 

pip-audit -r requirements/prod.txt -f json -o pip-audit-report.json

 

JSON output is useful if you want to store reports, integrate results into CI/CD, or later build a MofidTech tool that analyzes dependency risk.

 

How to Understand pip-audit Results

When pip-audit finds a vulnerability, it usually shows:

  • The affected package
  • The installed version
  • The vulnerability ID
  • A short vulnerability description
  • Fixed versions when available

A typical result may look like this:

Name     Version  ID                  Fix Versions
package  1.0.0    PYSEC-XXXX-XXXX     1.0.3

 

Do not panic when you see results. Instead, follow a safe process:

  1. Read the vulnerability details.
  2. Check the affected package.
  3. Check whether your project uses the vulnerable feature.
  4. Check the fixed version.
  5. Upgrade in a development branch.
  6. Run tests.
  7. Deploy to staging.
  8. Monitor behavior.
  9. Deploy to production only after validation.

Upgrade a package carefully:

 

python -m pip install --upgrade package-name

 

Then regenerate your requirements file or update your locked dependencies.

 

Step 3: Pin and Lock Dependencies with pip-tools

For professional Django projects, pip freeze is not always the best long-term dependency workflow.

pip freeze captures everything installed in the current environment. That can include packages you installed temporarily, testing libraries, or old experiments.

A better approach is to use pip-tools.

Install it:

 

python -m pip install pip-tools

 

Create a requirements.in file with your direct dependencies:

Django
djangorestframework
psycopg
gunicorn
redis
django-csp
python-decouple

 

Then compile it:

 

pip-compile requirements.in

 

This generates a pinned requirements.txt file with exact versions for both direct and transitive dependencies.

Install from the generated file:

 

python -m pip install -r requirements.txt

 

When you want to upgrade dependencies intentionally:

 

pip-compile --upgrade requirements.in

 

To upgrade only Django:

 

pip-compile --upgrade-package Django requirements.in

 

This workflow is safer because dependency changes become visible in Git.

You can review them with:

 

git diff requirements.txt

 

Step 4: Separate Development and Production Dependencies

Development packages should not always be installed in production.

For example, these packages may be useful locally but unnecessary in production:

  • django-debug-toolbar
  • pytest
  • coverage
  • ipython
  • profiling tools
  • local testing utilities

A clean requirements structure can look like this:

requirements/
    base.in
    dev.in
    prod.in
    base.txt
    dev.txt
    prod.txt

 

Example base.in:

Django
djangorestframework
psycopg
redis
python-decouple
django-csp

 

Example dev.in:

-r base.in
django-debug-toolbar
pytest
pytest-django
coverage

 

Example prod.in:

-r base.in
gunicorn
whitenoise

 

Compile the files:

 

pip-compile requirements/base.in -o requirements/base.txt
pip-compile requirements/dev.in -o requirements/dev.txt
pip-compile requirements/prod.in -o requirements/prod.txt

 

Install production dependencies only:

 

python -m pip install -r requirements/prod.txt

 

This makes production smaller, cleaner, easier to audit, and easier to reproduce.

 

Step 5: Check Django Production Settings

Dependency security is not separate from Django configuration.

A vulnerable package is one risk, but a secure package used with unsafe settings can also create problems.

Before deployment, run:

 

python manage.py check

 

Then run the deployment checks:

 

python manage.py check --deploy

 

This command does not replace a full security audit, but it helps detect common production configuration issues.

Important production settings include:

 

DEBUG = False

ALLOWED_HOSTS = [
    "mofidtech.fr",
    "www.mofidtech.fr",
]

CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

SECURE_SSL_REDIRECT = True

SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

SECURE_CONTENT_TYPE_NOSNIFF = True

X_FRAME_OPTIONS = "DENY"

 

Be careful with HSTS. Enable it only when HTTPS is correctly configured and stable for your domain and subdomains.

 

Step 6: Generate an SBOM for Your Django Project

An SBOM, or Software Bill of Materials, is a structured list of software components included in an application.

It helps you answer questions like:

  • Which packages are installed?
  • Which versions are used?
  • Which packages are direct dependencies?
  • Which packages are transitive dependencies?
  • What components exist in this release?
  • Are we affected by a newly announced vulnerability?

Install CycloneDX for Python:

 

python -m pip install cyclonedx-bom

 

Generate an SBOM from a requirements file:

 

cyclonedx-py requirements requirements.txt -o sbom.json

 

For a production requirements file:

 

cyclonedx-py requirements requirements/prod.txt -o sbom.json

 

Generate an SBOM from the current environment:

 

cyclonedx-py environment -o sbom.json

 

An SBOM is useful for professional projects because it gives you a clear inventory of your software components.

For small projects, it may feel advanced. But for client projects, institutional projects, production applications, and security-sensitive systems, it is very useful.

 

Step 7: Scan Docker Images Before Deployment

If your Django project uses Docker, you must scan the container image, not only the Python requirements file.

A Docker image can include:

  • Python
  • Linux packages
  • system libraries
  • PostgreSQL drivers
  • build tools
  • OpenSSL
  • CA certificates
  • shell utilities
  • application code
  • Python dependencies

Example Dockerfile:

 

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

RUN apt-get update \
    && apt-get install -y --no-install-recommends build-essential libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY requirements/prod.txt /app/requirements/prod.txt

RUN python -m pip install --upgrade pip \
    && python -m pip install --no-cache-dir -r requirements/prod.txt

COPY . /app

RUN python manage.py collectstatic --noinput

CMD ["gunicorn", "mofidtech.wsgi:application", "--bind", "0.0.0.0:8000"]

 

Build the image:

 

docker build -t mofidtech-web:latest .

 

Scan the image with Trivy:

 

trivy image mofidtech-web:latest

 

Scan only high and critical vulnerabilities:

 

trivy image --severity HIGH,CRITICAL mofidtech-web:latest

 

Fail the build on critical vulnerabilities:

 

trivy image --severity CRITICAL --exit-code 1 mofidtech-web:latest

 

If your scan shows many vulnerabilities, do not automatically ignore them. Check:

  • Which package is affected
  • Whether a fixed version exists
  • Whether the vulnerability affects your runtime
  • Whether the vulnerable package exists only in build tools
  • Whether you can update the base image
  • Whether you can use a multi-stage Docker build

 

Step 8: Reduce Docker Image Risk

A secure Docker image should be as small and intentional as possible.

Use a slim base image when appropriate:

 

FROM python:3.12-slim

 

Avoid installing unnecessary tools:

 

RUN apt-get update \
    && apt-get install -y --no-install-recommends libpq-dev \
    && rm -rf /var/lib/apt/lists/*

 

Avoid keeping package manager cache:

 

rm -rf /var/lib/apt/lists/*

 

Use --no-cache-dir with pip:

 

python -m pip install --no-cache-dir -r requirements/prod.txt

 

Avoid copying unnecessary files into the image by using .dockerignore.

Example .dockerignore:

.git
.venv
__pycache__
*.pyc
.env
.env.*
node_modules
coverage
htmlcov
.pytest_cache
.DS_Store

 

Never copy secret files into Docker images.

 

Step 9: Add Dependency Security to CI/CD

Manual checks are useful, but they are easy to forget.

A better approach is to run dependency checks automatically in CI/CD.

For example, you can run pip-audit on every pull request and block deployment if critical vulnerabilities are found.

Example GitHub Actions workflow:

 

name: Django Dependency Security

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  dependency-security:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install audit tools
        run: |
          python -m pip install --upgrade pip
          python -m pip install pip-audit

      - name: Audit Python dependencies
        run: |
          pip-audit -r requirements/prod.txt

 

Add Django checks:

 

      - name: Install project dependencies
        run: |
          python -m pip install -r requirements/prod.txt

      - name: Run Django deployment checks
        env:
          DJANGO_SETTINGS_MODULE: mofidtech.settings
          SECRET_KEY: dummy-secret-key-for-ci
          DEBUG: "False"
        run: |
          python manage.py check --deploy

 

Add Docker image scanning:

 

      - name: Build Docker image
        run: |
          docker build -t mofidtech-web:ci .

      - name: Scan Docker image with Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "mofidtech-web:ci"
          severity: "HIGH,CRITICAL"
          exit-code: "1"

 

The goal is not to make deployment impossible. The goal is to catch dangerous dependency problems before they reach production.

 

Step 10: Use Dependabot for Long-Term Maintenance

Dependency security is not a one-time task.

A project that is safe today can become vulnerable later when new vulnerabilities are discovered.

Dependabot can create automated pull requests to update dependencies.

Example .github/dependabot.yml:

 

version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5

  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5

 

Do not merge dependency update pull requests blindly.

Before merging:

  1. Read the changelog.
  2. Check whether the update is major, minor, or patch.
  3. Run tests.
  4. Run pip-audit.
  5. Build and scan the Docker image.
  6. Test staging.
  7. Deploy production only after validation.

 

Step 11: Build a Safe Update Workflow

A professional update workflow should be predictable.

Recommended workflow:

  1. Create a new Git branch.
  2. Update dependencies intentionally.
  3. Run dependency scanning.
  4. Run Django checks.
  5. Run automated tests.
  6. Review the Git diff.
  7. Build the Docker image.
  8. Scan the image.
  9. Deploy to staging.
  10. Monitor logs.
  11. Deploy to production.

Example Git workflow:

 

git checkout -b security/update-dependencies

pip-compile --upgrade requirements/prod.in -o requirements/prod.txt

pip-audit -r requirements/prod.txt

python manage.py check
python manage.py check --deploy
python manage.py test

git diff requirements/prod.txt

git add requirements/
git commit -m "Update production dependencies"

git push origin security/update-dependencies

 

This gives you a clean reviewable process.

 

Production Dependency Security Checklist

Before Committing Changes

Check the following:

  • Review changed files with git diff
  • Confirm that no unnecessary dependency was added
  • Confirm that production dependencies are pinned
  • Confirm that development packages are not in production requirements
  • Run pip-audit
  • Run Django checks
  • Run tests locally
  • Check for unexpected major version upgrades

Useful commands:

 

git status
git diff
pip-audit -r requirements/prod.txt
python manage.py check
python manage.py test

 

Before Deploying to Staging

Check the following:

  • Install dependencies from locked files
  • Run python manage.py check
  • Run python manage.py check --deploy
  • Build the Docker image
  • Scan the Docker image
  • Generate or update the SBOM
  • Test authentication
  • Test admin access
  • Test forms
  • Test file uploads
  • Test important user flows

Useful commands:

 

python -m pip install -r requirements/prod.txt
python manage.py check --deploy
docker build -t mofidtech-web:staging .
trivy image --severity HIGH,CRITICAL mofidtech-web:staging

 

<hr>

Before Deploying to Production

Check the following:

  • Backup the database
  • Confirm migrations are reviewed
  • Confirm DEBUG = False
  • Confirm ALLOWED_HOSTS is correct
  • Confirm HTTPS is configured
  • Confirm secure cookies are enabled
  • Confirm the Docker image was scanned
  • Confirm there are no unresolved critical vulnerabilities
  • Prepare rollback commands
  • Monitor logs after deployment

Example production commands:

 

python manage.py check --deploy
python manage.py migrate --plan
python manage.py collectstatic --noinput

 

If using Docker Compose:

 

docker compose -f docker-compose.yml -f docker-compose.prod.yml config
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
docker compose logs -f web

 

Security Considerations

Do Not Trust a Package Only Because It Installs Successfully

A package can install successfully and still be risky.

It may be:

  • outdated
  • abandoned
  • vulnerable
  • unnecessary
  • poorly maintained
  • too powerful for your use case

Before adding a package, check whether you really need it.

 

Avoid Adding Dependencies for Simple Problems

Every dependency has a cost.

If you can solve a small problem with a few lines of safe code, you may not need a new package.

This is especially true for:

  • simple template filters
  • formatting helpers
  • small utility functions
  • one-time scripts
  • basic validation logic

A smaller dependency tree is usually easier to maintain and audit.

 

Review Authentication Packages Carefully

Packages that affect authentication and authorization should receive extra review.

This includes packages related to:

  • login
  • logout
  • password reset
  • OAuth
  • sessions
  • tokens
  • permissions
  • admin access
  • user roles

A small mistake in these areas can create serious production risk.

 

Be Careful with AI-Generated Code

AI-generated code can be useful, but it may suggest:

  • outdated packages
  • insecure configuration
  • unnecessary dependencies
  • old syntax
  • vulnerable examples
  • missing validation
  • weak deployment practices

Before adding AI-suggested dependencies, verify the package, read the documentation, audit it, and test it.

 

Performance Considerations

Fewer Dependencies Can Mean Faster Builds

A smaller dependency tree usually means:

  • faster Docker builds
  • faster CI checks
  • smaller images
  • fewer conflicts
  • easier audits
  • simpler debugging

This is especially useful for Django projects deployed with Docker Compose, GitHub Actions, or cloud build systems.

 

Smaller Docker Images Are Easier to Scan

Large Docker images often contain more packages and more potential vulnerabilities.

To reduce image size:

  • use slim base images
  • remove package manager cache
  • avoid unnecessary system tools
  • use .dockerignore
  • install only production dependencies
  • avoid copying local development files into the image

 

Avoid Installing Build Tools in the Final Runtime Image

Build tools are often unnecessary in the final production image.

If possible, use multi-stage Docker builds.

Example idea:

 

FROM python:3.12-slim AS builder

WORKDIR /app

RUN apt-get update \
    && apt-get install -y --no-install-recommends build-essential libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY requirements/prod.txt .
RUN python -m pip wheel --wheel-dir /wheels -r prod.txt

FROM python:3.12-slim

WORKDIR /app

COPY --from=builder /wheels /wheels
COPY requirements/prod.txt .

RUN python -m pip install --no-cache-dir --no-index --find-links=/wheels -r prod.txt

COPY . .

CMD ["gunicorn", "mofidtech.wsgi:application", "--bind", "0.0.0.0:8000"]

 

This keeps build dependencies out of the final runtime image.

 

Common Mistakes

Mistake 1: Using pip freeze Without Review

pip freeze captures everything installed in the environment.

If your local environment contains old experiments, debug tools, or temporary libraries, they can accidentally enter production.

A better approach is to define direct dependencies in .in files and compile locked .txt files.

 

Mistake 2: Updating All Packages Directly Before Deployment

Updating all packages immediately before deployment is risky.

You may introduce breaking changes at the worst possible moment.

Instead:

  1. Update in a branch.
  2. Run tests.
  3. Scan dependencies.
  4. Test staging.
  5. Deploy production carefully.

 

Mistake 3: Ignoring Warnings Because the Website Still Works

A vulnerable package may not break your website visually.

The homepage can load correctly while a security issue exists in the background.

Security checks must not depend only on manual browsing.

 

Mistake 4: Scanning Only Python Packages and Forgetting Docker

If your project runs in Docker, you need both Python dependency scanning and container image scanning.

These are related but not identical.

pip-audit checks Python dependencies.

trivy image checks container images and system packages.

Use both.

 

Mistake 5: Not Keeping a Rollback Plan

Dependency updates can break behavior.

Before production deployment, know how to return to the previous version quickly.

Example rollback with Git:

 

git log --oneline
git revert commit_hash

 

Example rollback with Docker image tags:

 

docker compose pull
docker compose up -d

 

A rollback plan is part of professional deployment.

 

Troubleshooting

pip-audit Reports a Vulnerability but No Fix Is Available

If no fixed version is available:

  • Check whether your project actually uses the vulnerable feature
  • Look for official mitigation advice
  • Consider replacing the package
  • Limit exposure through configuration
  • Monitor the package for a fix
  • Document the risk temporarily

Do not ignore the vulnerability silently.

 

pip-compile Produces a Very Large requirements.txt File

This is normal.

The compiled file includes direct and transitive dependencies.

Do not delete transitive dependencies manually unless you understand the dependency graph.

 

Docker Scan Shows Vulnerabilities in the Base Image

Try updating the base image:

 

docker pull python:3.12-slim
docker build --no-cache -t mofidtech-web:latest .
trivy image mofidtech-web:latest

 

If vulnerabilities remain, check whether patched versions are available.

Sometimes a vulnerability is reported before the base image maintainers have released a fix.

 

Django check --deploy Shows Many Warnings

Read each warning carefully.

Some settings are environment-specific.

For example, HTTPS and HSTS settings should be configured correctly in production but may not be appropriate for local development.

Do not blindly copy production settings into local development.

 

Real-World Use Case: Securing a Django Blog Before Deployment

Imagine you are preparing a Django blog or tutorial website for production.

The project uses:

  • Django
  • PostgreSQL
  • Gunicorn
  • Redis
  • CKEditor
  • Docker Compose
  • Nginx
  • A security headers package

Before deployment, you can follow this process:

 

git checkout -b security/pre-production-check

python -m venv .venv
source .venv/bin/activate

python -m pip install --upgrade pip pip-tools pip-audit

pip-compile requirements/prod.in -o requirements/prod.txt

python -m pip install -r requirements/prod.txt

pip-audit -r requirements/prod.txt

python manage.py check
python manage.py check --deploy
python manage.py test

docker build -t mofidtech-web:preprod .

trivy image --severity HIGH,CRITICAL mofidtech-web:preprod

 

If all checks pass, deploy to staging first.

After testing staging, merge the branch and deploy to production.

 

Best Practices for Long-Term Dependency Security

Follow these best practices:

  • Use locked dependency files for production
  • Do not install packages manually on the production server
  • Run pip-audit regularly
  • Scan Docker images before deployment
  • Use Dependabot or another automated update system
  • Review dependency pull requests before merging
  • Separate development and production dependencies
  • Remove unused packages
  • Document major upgrades
  • Keep Django on a supported version
  • Test authentication, admin access, forms, uploads, and user-data features after dependency updates
  • Keep a rollback plan
  • Generate an SBOM for important releases
  • Monitor production logs after deployment

 

FAQ

1. Is pip-audit enough to secure a Django project?

No. pip-audit is useful for finding known vulnerabilities in Python packages, but it does not review your Django settings, business logic, Docker image, Nginx configuration, database permissions, or custom code.

Use it as one part of a larger security process.

 

2. Should I always upgrade a vulnerable package immediately?

You should respond quickly, but not blindly.

Check:

  • the severity
  • whether your project is affected
  • the fixed version
  • possible breaking changes
  • test results

Upgrade in development first, then staging, then production.

 

3. What is the difference between requirements.in and requirements.txt?

requirements.in usually contains your direct dependencies.

requirements.txt is generated from it and contains exact versions for both direct and transitive dependencies.

This makes production installations more reproducible.

 

4. Is pip freeze bad?

pip freeze is not bad, but it can capture everything in your current environment, including packages that are not really needed by the project.

For production, pip-tools often gives you a cleaner workflow.

 

5. Do I need an SBOM for a small Django website?

For a small personal project, an SBOM may not be mandatory.

However, it is still useful because it gives you a clear inventory of your dependencies.

For professional, institutional, or client projects, SBOMs are increasingly valuable.

 

6. Should I scan Docker images even if I use python:slim?

Yes.

Slim images are smaller, but they can still contain vulnerable system packages.

Always scan the final image that you deploy.

 

7. Can Dependabot break my Django project?

Dependabot itself does not break your project, but a dependency update can introduce breaking changes.

Treat Dependabot pull requests like normal code changes:

  • review them
  • test them
  • scan dependencies
  • deploy to staging first

 

8. Should I commit requirements.txt to Git?

Yes.

For most Django applications, you should commit the locked requirements file used for production.

This helps ensure that production installs the same versions that were tested.

 

9. How often should I audit dependencies?

For active projects, run dependency checks:

  • on every pull request
  • before every production deployment
  • at least weekly in CI
  • after major security announcements

 

10. What should I do if a package is abandoned?

If a package is abandoned and still important to your project, look for a maintained alternative.

If replacement is not immediately possible, document the risk and plan a migration.

 

Conclusion

Securing a Django project before production is not only about Django settings.

It is also about controlling the dependencies that your application depends on.

A professional production workflow should include:

  • package auditing
  • pinned versions
  • dependency locks
  • SBOM generation
  • Docker image scanning
  • CI/CD checks
  • regular dependency updates
  • staging validation
  • rollback planning

The most important idea is simple: never deploy dependencies that you do not understand, cannot reproduce, or have not checked.

Your requirements files, Docker images, and dependency update process should be treated with the same seriousness as your Django views, models, forms, and templates.

By using tools like pip-audit, pip-tools, CycloneDX, Trivy, Docker Scout, and Dependabot, you can reduce production risk and create a repeatable security workflow for every Django project.

For MofidTech readers, this topic is especially valuable because it connects Django, Python, DevOps, cybersecurity, Docker, and developer productivity in one practical workflow.

It is also a strong foundation for a future MofidTech tool that helps developers review dependency security before deploying their applications.