# PYTHON-FLASK-AUDIT-009: Flask Cookie Without Secure Flags

> **Severity:** MEDIUM | **CWE:** CWE-614 | **OWASP:** A05:2021

- **Language:** Python
- **Category:** Flask
- **URL:** https://codepathfinder.dev/registry/python/flask/PYTHON-FLASK-AUDIT-009
- **Detection:** `pathfinder scan --ruleset python/PYTHON-FLASK-AUDIT-009 --project .`

## Description

This rule detects Flask response.set_cookie() calls where the secure or httponly flags are
explicitly set to False. Cookies that carry session identifiers, authentication tokens, or
any sensitive value must be protected by these flags.

The Secure flag prevents the browser from transmitting the cookie over unencrypted HTTP
connections. Without it, a session cookie can be stolen by a passive network observer on
any unencrypted path between the client and server -- public Wi-Fi, misconfigured proxies,
or HTTP-to-HTTPS redirect chains. The HttpOnly flag prevents JavaScript running on the page
(including injected XSS payloads) from accessing the cookie via document.cookie. Without
it, a successful XSS attack instantly yields the session token.

The detection uses an Or pattern: Or(calls("*.set_cookie", match_name={"secure": False}),
calls("*.set_cookie", match_name={"httponly": False})). This matches any object's set_cookie()
method where either flag is explicitly disabled. The wildcard (*) on the receiver covers both
response objects returned by Flask directly and response objects created via make_response().


## Vulnerable Code

```python
from flask import Flask, make_response

app = Flask(__name__)

@app.route('/setcookie')
def setcookie():
    resp = make_response("cookie set")
    resp.set_cookie('session', 'value', secure=False, httponly=False)
    return resp
```

## Secure Code

```python
from flask import Flask, make_response

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    response = make_response({'status': 'logged in'})

    # SAFE: Set all protective flags on the session cookie
    response.set_cookie(
        'session_id',
        value='abc123',
        secure=True,      # Only send over HTTPS
        httponly=True,    # Prevent JavaScript access
        samesite='Strict' # Prevent cross-site sending
    )
    return response

# Also configure Flask's built-in session cookie flags globally:
# app.config['SESSION_COOKIE_SECURE'] = True
# app.config['SESSION_COOKIE_HTTPONLY'] = True
# app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, Or, QueryType


@python_rule(
    id="PYTHON-FLASK-AUDIT-009",
    name="Flask Cookie Without Secure Flags",
    severity="MEDIUM",
    category="flask",
    cwe="CWE-614",
    tags="python,flask,cookie,secure,httponly,CWE-614",
    message="Cookie set without secure=True or httponly=True. Set both flags for session cookies.",
    owasp="A05:2021",
)
def detect_flask_insecure_cookie():
    """Detects set_cookie() with secure=False or httponly=False."""
    return Or(
        calls("*.set_cookie", match_name={"secure": False}),
        calls("*.set_cookie", match_name={"httponly": False}),
    )
```

## How to Fix

- Set secure=True on all cookies that carry session identifiers, authentication tokens, or any sensitive data so they are never transmitted over plain HTTP.
- Set httponly=True on all session and authentication cookies so JavaScript cannot access them via document.cookie, limiting XSS damage.
- Set samesite='Strict' or samesite='Lax' to reduce CSRF risk. Use 'None' only for third-party contexts, and only in combination with secure=True.
- Configure Flask's global session cookie settings in app.config: SESSION_COOKIE_SECURE=True, SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE='Lax'. These protect the built-in session cookie without requiring per-route set_cookie() calls.
- Review cookie usage during code review as a security-sensitive change and include it in your application's security checklist.

## Security Implications

- **Session Hijacking via Network Eavesdropping:** Without the Secure flag, a session cookie is sent over plain HTTP. On any network path
that includes an unencrypted segment -- public Wi-Fi, HTTP-to-HTTPS redirect, mixed
content -- a passive observer can capture the cookie and replay it to impersonate the
authenticated user.

- **Session Hijacking via XSS:** Without the HttpOnly flag, any JavaScript running on the page can read document.cookie
and exfiltrate session tokens to an attacker-controlled server. A single XSS
vulnerability anywhere on the domain can compromise every logged-in user's session.

- **Cross-Site Request Forgery Amplification:** Cookies without the SameSite attribute (an additional flag not covered by this rule
but worth setting) can be sent with cross-site requests, making CSRF attacks easier.
Explicitly setting secure and httponly is the baseline; SameSite=Strict or Lax should
also be configured.

- **Persistent Cookie Exposure:** If a cookie is set without the Secure flag and the application later migrates to HTTPS,
existing cookies issued to users during the HTTP period remain readable over plain HTTP
until they expire or the user logs out.


## FAQ

**Q: Why does this rule only flag explicit False values, not missing flags?**

Explicitly setting secure=False or httponly=False is a deliberate override that is
almost never correct for sensitive cookies. Missing flags are a separate concern --
Flask's default for set_cookie() is to omit the flags (which browsers treat as not
set). A separate audit rule covering absent flags would complement this one. This rule
focuses on explicit disabling, which is the highest-confidence finding.


**Q: My application serves both HTTP and HTTPS. Can I set secure=True on cookies?**

Yes, and you should. Cookies with the Secure flag are simply not sent over HTTP
connections -- they are only sent over HTTPS. If you have an HTTP endpoint, users
accessing it without HTTPS will not have the secure cookie sent, but they also will
not have it stolen in transit. Migrate fully to HTTPS and set the Secure flag on all
sensitive cookies.


**Q: Does Flask's built-in session cookie respect these flags?**

Flask's built-in session cookie is configured via app.config: SESSION_COOKIE_SECURE,
SESSION_COOKIE_HTTPONLY, and SESSION_COOKIE_SAMESITE. This rule does not cover the
built-in session cookie because it uses a different configuration path. Always configure
those app.config values explicitly for the built-in session.


**Q: What is the SameSite attribute and should I set it?**

The SameSite attribute controls whether cookies are sent with cross-site requests.
SameSite=Strict prevents sending with any cross-site request. SameSite=Lax allows
sending with top-level navigations (links) but not with AJAX requests. SameSite=None
allows cross-site but requires Secure=True. Set Lax or Strict for session cookies to
reduce CSRF risk. This rule does not currently check for missing SameSite, but it is
a recommended addition.


**Q: How do I run this rule in CI/CD?**

Run: pathfinder ci --ruleset python/flask/PYTHON-FLASK-AUDIT-009 --project .
The rule outputs SARIF, JSON, or CSV and can post inline pull request comments on GitHub.


**Q: Does this rule catch Flask-Login or Flask-Session cookie configuration?**

No. Flask-Login and Flask-Session use Flask's built-in session cookie infrastructure,
configured via app.config. This rule matches explicit set_cookie() calls in Python code.
For Flask-Login and Flask-Session, audit the SESSION_COOKIE_SECURE and related
app.config settings directly.


## References

- [CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute](https://cwe.mitre.org/data/definitions/614.html)
- [OWASP Secure Cookie Attributes](https://owasp.org/www-community/controls/SecureCookieAttribute)
- [Flask Cookie Documentation](https://flask.palletsprojects.com/en/stable/api/#flask.Response.set_cookie)
- [MDN HTTP Cookie Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#security)
- [OWASP A05:2021 Security Misconfiguration](https://owasp.org/Top10/A05_2021-Security_Misconfiguration/)
- [OWASP Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html)

---

Source: https://codepathfinder.dev/registry/python/flask/PYTHON-FLASK-AUDIT-009
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
