Home Features Docs Blog Security Examples Quick Start

Security-First Development: How djust Protects Your Application by Default

djust Team | | 4 min read
Shield icon representing security protection layers

Security vulnerabilities don't wait for your next sprint planning session. They exploit weaknesses the moment your code ships. That's why djust now includes comprehensive security hardening features that protect your application by default, without requiring you to become a security expert.

With PR #40, we've added a complete security toolkit that covers Python, JavaScript, Rust, and your CI/CD pipeline. Let's explore what's included and how it protects you.

The Security Utilities Module

The new djust.security module provides battle-tested utilities for handling untrusted input safely.

Preventing Prototype Pollution with safe_setattr()

Prototype pollution attacks occur when attackers inject dangerous attribute names like __class__ or __proto__ through user input. These attacks can lead to authentication bypass, code execution, or denial of service.

djust's safe_setattr() blocks over 60 dangerous attributes automatically:

from djust.security import safe_setattr

# Instead of this (DANGEROUS):
for key, value in user_params.items():
    setattr(obj, key, value)  # Attacker could set __class__!

# Use this (SAFE):
for key, value in user_params.items():
    safe_setattr(obj, key, value)  # Blocks __class__, __proto__, etc.

Stopping Log Injection with sanitize_for_log()

Log injection attacks allow attackers to forge log entries, inject ANSI escape codes to manipulate terminals, or flood your logs with massive strings. The sanitize_for_log() function handles all of this:

from djust.security import sanitize_for_log

# Instead of this (DANGEROUS):
logger.info(f"User searched for: {user_query}")

# Use this (SAFE):
logger.info(f"User searched for: {sanitize_for_log(user_query)}")

The function strips ANSI escape sequences, replaces control characters, collapses newlines, and truncates excessively long strings.

DEBUG-Aware Error Handling

Exposing stack traces in production is a security vulnerability. They reveal file paths, code structure, and dependency versions to attackers. The handle_exception() function provides safe error responses that respect your DEBUG setting:

from djust.security import handle_exception

try:
    process_user_request()
except Exception as e:
    # Logs with stack trace in DEBUG, without in production
    # Returns detailed error in DEBUG, generic message in production
    response = handle_exception(
        e,
        error_type="event",
        event_name="submit",
        logger=logger
    )

JavaScript Security Utilities

Client-side security matters too. djust now includes security.js with utilities for safe DOM manipulation:

// Safe innerHTML (prevents XSS via DOMParser sanitization)
djustSecurity.safeSetInnerHTML(element, untrustedHTML);

// Safe object merging (blocks __proto__ pollution)
const merged = djustSecurity.safeObjectAssign({}, untrustedData);

// Safe logging (strips control characters)
console.log(djustSecurity.sanitizeForLog(userInput));

The safeSetInnerHTML() function parses HTML through DOMParser, removes script tags and inline event handlers, and strips dangerous URL schemes like javascript:, data:, and vbscript:.

Automated Security Scanning in CI/CD

Security can't depend on developers remembering to run checks manually. Our CI pipeline now includes a dedicated security-scan job that runs automatically on every pull request:

  • Bandit - Scans Python code for common security issues
  • Safety - Checks Python dependencies for known vulnerabilities
  • cargo-audit - Scans Rust dependencies for security advisories
  • npm audit - Checks JavaScript dependencies for vulnerabilities
  • ESLint security plugin - Catches JavaScript security anti-patterns

Vulnerable code doesn't merge. Period.

Pre-commit Hooks for Early Detection

Why wait for CI when you can catch issues before you commit? Our pre-commit configuration includes:

repos:
  - repo: https://github.com/PyCQA/bandit
    hooks:
      - id: bandit  # Python security linting

  - repo: https://github.com/Yelp/detect-secrets
    hooks:
      - id: detect-secrets  # Credential detection

  - repo: local
    hooks:
      - id: cargo-audit  # Rust dependency vulnerabilities
        stages: [pre-push]

Install them with pre-commit install and security checks run automatically every time you commit.

Security Guidelines for Contributors

We've documented our security requirements in docs/SECURITY_GUIDELINES.md, including:

  • Banned patterns (what NOT to do)
  • Required utilities (what to use instead)
  • Code review checklist for security issues
  • Common vulnerabilities with prevention examples
  • Manual testing procedures for security-sensitive changes

What This Means for You

As a djust developer, you get:

  • Protection by default - Security utilities are ready to import and use
  • Automated enforcement - CI catches security issues before they ship
  • Early feedback - Pre-commit hooks flag problems immediately
  • Clear guidance - Documentation tells you exactly what to do

Security is no longer something you need to remember. It's built into your workflow.

Getting Started

Update to the latest djust version and start using the security utilities:

pip install --upgrade djust
from djust.security import (
    safe_setattr,
    sanitize_for_log,
    handle_exception,
)

Check out the full Security Guidelines for detailed documentation and examples.

Security is a journey, not a destination. These features represent our commitment to making djust applications secure by default. Have suggestions for additional security features? Open an issue or submit a PR - we'd love to hear from you.

Share this post

Related Posts