Monero Integration, CSRF: enforce coverage test + CI gate; Monero docs/hardening updates
Summary
- Completes CSRF protection audit.
- Adds a focused CSRF coverage test and integrates it into CI as a gate.
- Updates docs (Testing, Security, README) with CSRF policy and Monero hardening guidance.
- No runtime breaking changes or DB migrations.
Changes
-
Makefile
- Added
test-csrf
target to run only tests/test_csrf_coverage.py withPYTEST_DISABLE_PLUGIN_AUTOLOAD=1
for stable output.
- Added
-
CI
-
.gitlab-ci.yml: New
csrf-audit
job to runmake test-csrf
on each commit/MR.
-
.gitlab-ci.yml: New
-
Tests
-
tests/test_csrf_coverage.py:
- Ensures all POST views declare
require_csrf=True
. - Ensures all local POST forms include
{% include "snippets/csrf.j2" %}
. - Skips external POSTs:
- absolute URLs (
http/https
) - signed upload forms (
action="{{ signed_post["url"] }}"
)
- absolute URLs (
- Ensures all POST views declare
-
tests/test_csrf_coverage.py:
-
Templates
- make_post_sell/templates/update-card.j2
-
make_post_sell/templates/snippets/stripe.j2
- Standardized CSRF includes to double quotes so the test recognizes them.
-
Documentation
-
docs/testing.md: Added “CSRF Coverage Test Only” section (
make test-csrf
). - docs/security.md: Finalized CSRF coverage status, template policy (skip CSRF for external POSTs), and CI verification. Expanded Monero hardening guidance.
- README.rst: Added CSRF coverage test snippet in “Running Tests”.
-
docs/testing.md: Added “CSRF Coverage Test Only” section (
CSRF Audit Details
- All state-changing POST routes use
require_csrf=True
. - All local POST forms include
{% include "snippets/csrf.j2" %}
. - External POSTs (e.g., signed S3/Spaces uploads) are excluded from CSRF and test coverage.
Examples (selected):
-
Views:
-
make_post_sell/views/authentication.py:
- Split GET/POST for
join-or-log-in
,verification-challenge
, addedrequire_csrf=True
on POST.
- Split GET/POST for
-
make_post_sell/views/coupon.py:
- Split coupon_new into GET/POST, added
require_csrf=True
on POST.
- Split coupon_new into GET/POST, added
- Verified comment.py, cart.py POST routes have
require_csrf=True
.
-
make_post_sell/views/authentication.py:
-
Templates (selected):
-
cart.j2, coupon_new.j2, join-or-log-in.j2, markup_editor.j2, user_settings.j2, user_addresses.j2, shop_settings.j2, shop_users.j2, shop_new.j2, shop_location_form.j2, product_new.j2, product_edit.j2,
comments/*
, verification-challenge.j2. - Signed external upload forms (e.g., in product_edit.j2, shop_settings.j2) are intentionally excluded from CSRF and test coverage.
-
cart.j2, coupon_new.j2, join-or-log-in.j2, markup_editor.j2, user_settings.j2, user_addresses.j2, shop_settings.j2, shop_users.j2, shop_new.j2, shop_location_form.j2, product_new.j2, product_edit.j2,
Monero: Documentation & Hardening Notes
-
- Monero hardening checklist:
- RPC bound to localhost, strong auth, no public exposure.
- Disable mock mode in production; keep mock JSON non-public.
- Price oracle: HTTPS, enforce timeouts/retries and sanity bounds.
- Minimal PII in logs; avoid leaking addresses/PII.
- Watcher idempotence and confirmation thresholds.
- Notes on watcher behavior and inventory finalization parity with Stripe.
- Monero hardening checklist:
-
- Monero test targets remain (
make test-monero
), with CSRF test added.
- Monero test targets remain (
Testing
-
Local CSRF coverage test:
-
make test-csrf
→ 2 passed (CSRF views + template coverage).
-
-
Full test suite:
-
make test
(set Stripe test keys per README if needed).
-
CI
- Adds
csrf-audit
job to thetest
stage that runsmake test-csrf
to prevent regressions. - Pip-audit job retained as before.
Backwards Compatibility
- No runtime behavior changes except added CSRF enforcement on POST (expected security hardening).
- No config changes or DB migrations.
Risks & Mitigations
- Risk: Missing CSRF in a new POST endpoint or template could regress.
- Mitigation: CI gate (
csrf-audit
) fails if coverage is incomplete.
- Mitigation: CI gate (
- Risk: False positive for external POSTs.
- Mitigation: Test explicitly skips actions to absolute URLs and
signed_post["url"]
.
- Mitigation: Test explicitly skips actions to absolute URLs and
Follow-ups (Optional)
- Add a CI badge or README note for CSRF coverage gate.
- Extend tests to assert specific critical routes/forms if desired.
- Consider adding price oracle timeouts/retries and bounds in
views/crypto.py
.
How To Verify
- Locally:
-
make test-csrf
should pass.
-
- In CI:
- Ensure
csrf-audit
job passes in the MR pipeline.
- Ensure