VNX-1427 – Improper Neutralization of Input Used in an Assertion

Overview

Python’s assert statement is a debugging tool, not a security mechanism. When Python is invoked with -O (optimise) or -OO flags, all assert statements are stripped from the bytecode at compile time — they never execute. Using assert for security checks (length validation of passwords, permission checks, input sanitisation) creates invisible security holes in optimised deployments. Severity: Medium | CWE: CWE-1427 – Improper Neutralization of Input Used in an Assertion

Why This Matters

Flask’s production WSGI servers (gunicorn, uWSGI) sometimes run with optimisation. WSGI deployment documentation occasionally recommends -O for performance. Any assert in request-handling code will be silently bypassed. The Python documentation explicitly warns: “assert statements are disabled when the Python interpreter is started in optimised mode”.

What Gets Flagged

# FLAGGED: assert used for password length check
def set_password(password):
    assert len(password) >= 8, "Password too short"  # disabled with -O
    save_password(hash(password))

# FLAGGED: assert for authentication check
def get_user_data(user_id, current_user):
    assert current_user.is_authenticated  # disabled with -O — always passes
    return User.objects.get(id=user_id)

# FLAGGED: assert on request data
def create_item(request):
    assert request.user.is_admin  # disabled with -O
    Item.objects.create(**request.POST)

Remediation

Replace assert with explicit if/raise statements for all security-critical checks:

# SAFE: Explicit validation that cannot be disabled
def set_password(password):
    if len(password) < 8:
        raise ValueError("Password must be at least 8 characters")
    save_password(hash_password(password))

# SAFE: Explicit authentication check
def get_user_data(user_id, current_user):
    if not current_user.is_authenticated:
        raise PermissionDenied("Authentication required")
    return User.objects.get(id=user_id)

# SAFE: Django @login_required decorator (cannot be disabled)
from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('myapp.add_item')
def create_item(request):
    Item.objects.create(**request.POST)

For input validation in Django, use form validation or serializer validation which runs unconditionally.

References