Execution After Redirect ('EAR')

ID

python.execution_after_redirect

Severity

low

Resource

Other

Language

Python

Tags

CWE:698, NIST.SP.800-53

Description

Detects code that continues to execute after issuing an HTTP redirect, potentially leading to unintended information disclosure or behavior.

Rationale

Execution-after-redirect vulnerabilities occur when a web application continues processing code after issuing a redirect (e.g., via redirect() or setting HTTP status 302). In Python web frameworks like Flask or Django, this can cause sensitive logic to run unintentionally, resulting in issues like information leakage, authorization bypass, or unintended side effects.

Consider the following Flask example:

from flask import Flask, redirect, request

app = Flask(__name__)

@app.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect('/login')
    do_cleanup()  # This will still execute!

Here, do_cleanup() is executed even after the redirect is issued, which can lead to undefined behavior or security problems.

Another example showing the vulnerability more clearly:

from flask import Flask, redirect

app = Flask(__name__)

@app.route('/transfer')
def transfer():
    if not user_is_authenticated():
        return redirect('/login')
    perform_transfer()  # This still runs even if the user is unauthenticated!

The call to perform_transfer() should not execute after the redirect(), but in this structure, it will unless explicitly returned early.

Remediation

To prevent execution after redirection in Python applications, ensure that no additional code executes after a redirection call. Always use return statements directly with redirect functions or after setting redirect responses to terminate execution flow clearly.

Correct usage:

from flask import Flask, redirect, session

app = Flask(__name__)

@app.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect('/login')  # Execution stops here

For more complex logic:

@app.route('/transfer')
def transfer():
    if not user_is_authenticated():
        return redirect('/login')  # Prevents perform_transfer() from running
    return perform_transfer()  # Safe to call now

Best Practices:

  • Always pair redirect() with a return keyword.

  • Avoid side-effect-prone logic after redirection unless absolutely required and well-audited.

  • Document all intentional post-redirect logic to make exceptions explicit and justifiable.

References

  • CWE-698: Execution After Redirect (EAR)

  • Owasp: Execution After Redirect (EAR)