# PYTHON-PYRAMID-SEC-001: Pyramid CSRF Check Disabled Globally

> **Severity:** HIGH | **CWE:** CWE-352 | **OWASP:** A05:2021

- **Language:** Python
- **Category:** Pyramid
- **URL:** https://codepathfinder.dev/registry/python/pyramid/PYTHON-PYRAMID-SEC-001
- **Detection:** `pathfinder scan --ruleset python/PYTHON-PYRAMID-SEC-001 --project .`

## Description

This rule detects calls to Configurator.set_default_csrf_options() in Pyramid
applications. This method controls CSRF protection globally. When called with
require_csrf=False, it disables CSRF token validation across every view in the
application, leaving all state-changing endpoints vulnerable to cross-site request
forgery attacks.

Pyramid's CSRF protection works by requiring a valid token on POST, PUT, DELETE,
and PATCH requests. Disabling it means any website can craft a form that submits
to your application using the victim's browser cookies, performing actions on
their behalf without their knowledge.


## Vulnerable Code

```python
from pyramid.config import Configurator
from pyramid.response import Response

# SEC-001: CSRF disabled
config = Configurator()
config.set_default_csrf_options(require_csrf=False)
```

## Secure Code

```python
from pyramid.config import Configurator

config = Configurator()

# SECURE: Enable CSRF protection globally (default behavior)
config.set_default_csrf_options(require_csrf=True)

# Per-view exemption if needed (rare, document why)
# @view_config(route_name='webhook', require_csrf=False)

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, flows, QueryType
from codepathfinder.presets import PropagationPresets

_PYRAMID_SOURCES = [
    calls("request.params.get"),
    calls("request.params"),
    calls("request.GET.get"),
    calls("request.POST.get"),
    calls("request.matchdict.get"),
    calls("request.json_body.get"),
    calls("*.params.get"),
    calls("*.params"),
]


@python_rule(
    id="PYTHON-PYRAMID-SEC-001",
    name="Pyramid CSRF Check Disabled Globally",
    severity="HIGH",
    category="pyramid",
    cwe="CWE-352",
    tags="python,pyramid,csrf,security,OWASP-A05,CWE-352",
    message="CSRF protection disabled globally via set_default_csrf_options(require_csrf=False).",
    owasp="A05:2021",
)
def detect_pyramid_csrf_disabled():
    """Detects Configurator.set_default_csrf_options() calls."""
    return calls("*.set_default_csrf_options")
```

## How to Fix

- Never call set_default_csrf_options(require_csrf=False) in production. Pyramid enables CSRF protection by default.
- If specific views need CSRF exemption (webhooks, API endpoints with token auth), exempt them individually with require_csrf=False in the @view_config decorator
- Use Pyramid's built-in CSRF token mechanism with session.get_csrf_token() in templates
- For API endpoints using Bearer token authentication, exempt per-view rather than disabling globally
- Review all calls to set_default_csrf_options() in code review to confirm the configuration is intentional

## Security Implications

- **Cross-Site Request Forgery on All Endpoints:** With CSRF protection disabled, an attacker can create a malicious page that
submits forms to your Pyramid application. When an authenticated user visits
the attacker's page, their browser sends cookies automatically, and the
forged request executes with the victim's session.

- **Account Takeover via Password Change:** A common CSRF attack target is the password change form. The attacker's page
submits a hidden form to /change-password with a new password. Without CSRF
protection, the request succeeds and the attacker owns the account.

- **Compliance Violations:** PCI DSS, SOC 2, and OWASP all require CSRF protection for web applications
handling sensitive data. Globally disabling it will fail any security audit.


## FAQ

**Q: Does Pyramid have CSRF protection enabled by default?**

Yes. Starting in Pyramid 1.7, CSRF checks are enabled by default for POST,
PUT, DELETE, and PATCH. You have to explicitly disable it. This rule catches
that explicit disabling.


**Q: How do I exempt a webhook endpoint from CSRF without disabling it globally?**

Use require_csrf=False in the @view_config decorator for that specific view.
This keeps CSRF protection active for all other views.


**Q: Our API uses Bearer token auth. Do we need CSRF?**

No. CSRF exploits cookie-based auth. If your API uses Bearer tokens in
the Authorization header, CSRF is not a threat. Exempt API views individually.


**Q: Does this rule fire even if require_csrf=True is passed?**

Yes. Any call to set_default_csrf_options() is flagged for review to confirm
the configuration is intentional.


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

Run: pathfinder ci --ruleset python/pyramid --project .


## References

- [CWE-352: Cross-Site Request Forgery](https://cwe.mitre.org/data/definitions/352.html)
- [Pyramid CSRF Protection Documentation](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html)
- [OWASP CSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)
- [OWASP A05:2021 Security Misconfiguration](https://owasp.org/Top10/A05_2021-Security_Misconfiguration/)

---

Source: https://codepathfinder.dev/registry/python/pyramid/PYTHON-PYRAMID-SEC-001
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
