feat: add CSRF protection to all POST forms

Installs Flask-WTF and enables CSRFProtect globally. Adds csrf_token
hidden fields to all four POST forms (login, delete entry, add user,
delete user, and the public guestbook form). Exempts the API endpoint
which uses header-based key auth instead.
This commit is contained in:
2026-03-28 23:17:26 -06:00
parent 9ad7128619
commit ecdcc044b7
6 changed files with 9 additions and 0 deletions
+1
View File
@@ -47,6 +47,7 @@
{% if current_user.role != 'viewer' %}
<form method="POST" action="{{ url_for('admin_delete', entry_id=g[0]) }}?page={{ page }}"
onsubmit="return confirm('Delete entry for {{ g[1] }} {{ g[2] }}?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
</form>
{% endif %}
+1
View File
@@ -15,6 +15,7 @@
<div class="alert alert-danger py-2">{{ error }}</div>
{% endif %}
<form method="POST" action="{{ url_for('admin_login', next=request.args.get('next', '')) }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" id="username" name="username" class="form-control"
+2
View File
@@ -20,6 +20,7 @@
<div class="card-header">Add User</div>
<div class="card-body">
<form method="POST" action="{{ url_for('admin_users_add') }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<div class="row g-2">
<div class="col-sm-4">
<input type="text" name="username" class="form-control" placeholder="Username" required />
@@ -57,6 +58,7 @@
<td>
<form method="POST" action="{{ url_for('admin_users_delete', user_id=u[0]) }}"
onsubmit="return confirm('Remove user {{ u[1] }}?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<button type="submit" class="btn btn-danger btn-sm">Remove</button>
</form>
</td>
+1
View File
@@ -70,6 +70,7 @@
{% endif %}
<form method="post" action="/" class="mb-4">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<div class="mb-3">
<label for="first_name" class="form-label">First Name(s):</label>
<input type="text" class="form-control" id="first_name" name="first_name" required />