mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-28 17:32:38 +02:00
Implement security best practices using Flask-Talisman
This commit is contained in:
parent
7554842b1f
commit
e626a1cbea
9 changed files with 64 additions and 2 deletions
|
@ -9,6 +9,7 @@ This document describes changes between each past release.
|
|||
Breaking changes
|
||||
----------------
|
||||
|
||||
- Enable session cookie security by default (#845)
|
||||
- Drop support for Python 2 (#483)
|
||||
- Drop support for Python 3.5 (#571)
|
||||
- Drop support for MySQL (#743)
|
||||
|
@ -25,6 +26,7 @@ Security
|
|||
|
||||
- Add CSRF validation on destructive actions (#796)
|
||||
- Ask for private code to delete project or project history (#796)
|
||||
- Add headers to mitigate Clickjacking, XSS, and other attacks: `X-Frame-Options`, `X-XSS-Protection`, `X-Content-Type-Options`, `Content-Security-Policy`, `Referrer-Policy` (#845)
|
||||
|
||||
Added
|
||||
-----
|
||||
|
|
|
@ -21,6 +21,7 @@ ADMIN_PASSWORD = '$ADMIN_PASSWORD'
|
|||
ALLOW_PUBLIC_PROJECT_CREATION = $ALLOW_PUBLIC_PROJECT_CREATION
|
||||
ACTIVATE_ADMIN_DASHBOARD = $ACTIVATE_ADMIN_DASHBOARD
|
||||
BABEL_DEFAULT_TIMEZONE = "$BABEL_DEFAULT_TIMEZONE"
|
||||
SESSION_COOKIE_SECURE = $SESSION_COOKIE_SECURE
|
||||
EOF
|
||||
|
||||
# Start gunicorn without forking
|
||||
|
|
|
@ -64,6 +64,21 @@ of the secret key could easily access any project and bypass the private code ve
|
|||
- **Production value:** `ihatemoney conf-example ihatemoney.cfg` sets it to
|
||||
something random, which is good.
|
||||
|
||||
`SESSION_COOKIE_SECURE`
|
||||
-----------------------
|
||||
|
||||
A boolean that controls whether the session cookie will be marked "secure".
|
||||
If this is the case, browsers will refuse to send the session cookie over plain HTTP.
|
||||
|
||||
- **Default value:** ``True``
|
||||
- **Production value:** ``True`` if you run your service over HTTPS, ``False`` if you run
|
||||
your service over plain HTTP.
|
||||
|
||||
Note: this setting is actually interpreted by Flask, see the
|
||||
`Flask documentation`_ for details.
|
||||
|
||||
.. _Flask documentation: https://flask.palletsprojects.com/en/2.0.x/config/#SESSION_COOKIE_SECURE
|
||||
|
||||
`MAIL_DEFAULT_SENDER`
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -104,12 +104,20 @@ You can create a ``settings.cfg`` file, with the following content::
|
|||
DEBUG = True
|
||||
SQLACHEMY_ECHO = DEBUG
|
||||
|
||||
You can also set the `TESTING` flag to `True` so no mails are sent
|
||||
(and no exception is raised) while you're on development mode.
|
||||
Then before running the application, declare its path with ::
|
||||
|
||||
export IHATEMONEY_SETTINGS_FILE_PATH="$(pwd)/settings.cfg"
|
||||
|
||||
You can also set the ``TESTING`` flag to ``True`` so no mails are sent
|
||||
(and no exception is raised) while you're on development mode.
|
||||
|
||||
In some cases, you may need to disable secure cookies by setting
|
||||
``SESSION_COOKIE_SECURE`` to ``False``. This is needed if you
|
||||
access your dev server over the network: with the default value
|
||||
of ``SESSION_COOKIE_SECURE``, the browser will refuse to send
|
||||
the session cookie over insecure HTTP, so many features of Ihatemoney
|
||||
won't work (project login, language change, etc).
|
||||
|
||||
.. _contributing-developer:
|
||||
|
||||
Contributing as a developer
|
||||
|
|
|
@ -65,6 +65,17 @@ If so, pick the ``pip`` commands to use in the relevant section(s) of
|
|||
|
||||
Then follow :ref:`general-procedure` from step 1. in order to complete the update.
|
||||
|
||||
Disable session cookie security if running over plain HTTP
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. note:: If you are running Ihatemoney over HTTPS, no special action is required.
|
||||
|
||||
Session cookies are now marked "secure" by default to increase security.
|
||||
|
||||
If you run Ihatemoney over plain HTTP, you need to explicitly disable this security
|
||||
feature by setting ``SESSION_COOKIE_SECURE`` to ``False``, see :ref:`configuration`.
|
||||
|
||||
|
||||
Switch to MariaDB >= 10.3.2 instead of MySQL
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
|
|
|
@ -38,3 +38,7 @@ ACTIVATE_ADMIN_DASHBOARD = False
|
|||
# You can change the timezone used to display time. By default it will be
|
||||
#derived from the server OS.
|
||||
#BABEL_DEFAULT_TIMEZONE = "Europe/Paris"
|
||||
|
||||
# Enable secure cookies. Requires HTTPS. Disable if you run your ihatemoney
|
||||
# service over plain HTTP.
|
||||
SESSION_COOKIE_SECURE = True
|
||||
|
|
|
@ -8,6 +8,7 @@ ACTIVATE_DEMO_PROJECT = True
|
|||
ADMIN_PASSWORD = ""
|
||||
ALLOW_PUBLIC_PROJECT_CREATION = True
|
||||
ACTIVATE_ADMIN_DASHBOARD = False
|
||||
SESSION_COOKIE_SECURE = True
|
||||
SUPPORTED_LANGUAGES = [
|
||||
"de",
|
||||
"el",
|
||||
|
|
|
@ -7,6 +7,7 @@ from flask import Flask, g, render_template, request, session
|
|||
from flask_babel import Babel, format_currency
|
||||
from flask_mail import Mail
|
||||
from flask_migrate import Migrate, stamp, upgrade
|
||||
from flask_talisman import Talisman
|
||||
from jinja2 import pass_context
|
||||
from markupsafe import Markup
|
||||
import pytz
|
||||
|
@ -126,6 +127,24 @@ def create_app(
|
|||
instance_relative_config=instance_relative_config,
|
||||
)
|
||||
|
||||
# If we need to load external JS/CSS/image resources, it needs to be added here, see
|
||||
# https://github.com/wntrblm/flask-talisman#content-security-policy
|
||||
csp = {
|
||||
"default-src": ["'self'"],
|
||||
# We have several inline javascript scripts :(
|
||||
"script-src": ["'self'", "'unsafe-inline'"],
|
||||
"object-src": "'none'",
|
||||
}
|
||||
|
||||
Talisman(
|
||||
app,
|
||||
# Forcing HTTPS is the job of a reverse proxy
|
||||
force_https=False,
|
||||
# This is handled separately through the SESSION_COOKIE_SECURE Flask setting
|
||||
session_cookie_secure=False,
|
||||
content_security_policy=csp,
|
||||
)
|
||||
|
||||
# If a configuration object is passed, use it. Otherwise try to find one.
|
||||
load_configuration(app, configuration)
|
||||
app.wsgi_app = PrefixedWSGI(app)
|
||||
|
|
|
@ -33,6 +33,7 @@ install_requires =
|
|||
Flask-Migrate>=2.5.3,<4 # Not following semantic versioning (e.g. https://github.com/miguelgrinberg/flask-migrate/commit/1af28ba273de6c88544623b8dc02dd539340294b)
|
||||
Flask-RESTful>=0.3.9,<1
|
||||
Flask-SQLAlchemy>=2.4,<3
|
||||
Flask-Talisman>=0.8,<1
|
||||
Flask-WTF>=0.14.3,<1
|
||||
WTForms>=2.3.1,<2.4
|
||||
Flask>=2,<3
|
||||
|
|
Loading…
Reference in a new issue