diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 04d6ccb5..4b6cd09a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,12 +13,11 @@ name: "CodeQL" on: push: - branches: [ "main", "develop" ] + branches: [ "main" ] pull_request: - # The branches below must be a subset of the branches above branches: [ "main" ] schedule: - - cron: '40 16 * * 6' + - cron: '26 17 * * 2' jobs: analyze: @@ -31,9 +30,12 @@ jobs: runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} permissions: + # required for all workflows + security-events: write + + # only required for workflows in private repositories actions: read contents: read - security-events: write strategy: fail-fast: false @@ -46,11 +48,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -64,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -77,6 +79,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index b0dedc42..d19e21b7 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -1,20 +1,39 @@ # Dependency Review Action # -# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable +# packages will be blocked from merging. # # Source repository: https://github.com/actions/dependency-review-action # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement -name: 'Dependency Review' -on: [pull_request] +name: 'Dependency review' +on: + pull_request: + branches: [ "main" ] +# If using a dependency submission action in this workflow this permission will need to be set to: +# +# permissions: +# contents: write +# +# https://docs.github.com/en/enterprise-cloud@latest/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api permissions: contents: read + # Write permissions for pull-requests are required for using the `comment-summary-in-pr` option, comment out if you aren't using this option + pull-requests: write jobs: dependency-review: runs-on: ubuntu-latest steps: - - name: 'Checkout Repository' - uses: actions/checkout@v3 + - name: 'Checkout repository' + uses: actions/checkout@v4 - name: 'Dependency Review' - uses: actions/dependency-review-action@v3 + uses: actions/dependency-review-action@v4 + # Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options. + with: + comment-summary-in-pr: always + # fail-on-severity: moderate + # deny-licenses: GPL-1.0-or-later, LGPL-2.0-or-later + # retry-on-snapshot-warnings: true diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 649c76f3..fdddd7e1 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -7,7 +7,7 @@ name: Docker on: schedule: - - cron: '33 10 * * *' + - cron: '40 1 * * *' push: branches: [ "main" ] # Publish semver tags as releases. diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 4c9361dd..eaa6dc7e 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -17,10 +17,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Python 3.11 + - name: Set up Python 3.12 uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: 3.12 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -32,7 +32,7 @@ jobs: run: bandit -r . -x /tests - name: Check code formatting run: | - black . -t py311 -l 120 --check + black . -t py312 -l 120 --check isort . -c - name: Lint with flake8 run: | diff --git a/.python-version b/.python-version index 2c073331..e4fba218 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.11 +3.12 diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f653a1..f6a46406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/MashSoftware/time-tracker/compare/main...develop) +## [Unreleased](https://github.com/MashSoftware/time-tracker/compare/main...v0.30.0) + +## [0.30.0](https://github.com/MashSoftware/time-tracker/compare/v0.29.0...v0.30.0) - 2024-xx-xx + +### Added + +- Strict HTTP Permissions Policy header. + +### Changed + +- Bump Python version to 3.12.2. ## [0.29.0](https://github.com/MashSoftware/time-tracker/compare/v0.28.3...v0.29.0) - 2023-10-30 diff --git a/Dockerfile b/Dockerfile index ec758642..b2410108 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim +FROM python:3.12-slim RUN useradd containeruser diff --git a/app/__init__.py b/app/__init__.py index d0f72af4..93f3bf48 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -43,6 +43,52 @@ def create_app(config_class=Config): "img-src": ["data:", "'self'"], } + # Set permissions policy + permissions_policy = { + "accelerometer": "()", + "ambient-light-sensor": "()", + "autoplay": "()", + "battery": "()", + "camera": "()", + "cross-origin-isolated": "()", + "display-capture": "()", + "document-domain": "()", + "encrypted-media": "()", + "execution-while-not-rendered": "()", + "execution-while-out-of-viewport": "()", + "fullscreen": "()", + "geolocation": "()", + "gyroscope": "()", + "keyboard-map": "()", + "magnetometer": "()", + "microphone": "()", + "midi": "()", + "navigation-override": "()", + "payment": "()", + "picture-in-picture": "()", + "publickey-credentials-get": "()", + "screen-wake-lock": "()", + "sync-xhr": "()", + "usb": "()", + "web-share": "()", + "xr-spatial-tracking": "()", + "clipboard-read": "()", + "clipboard-write": "()", + "gamepad": "()", + "speaker-selection": "()", + "conversion-measurement": "()", + "focus-without-user-activation": "()", + "hid": "()", + "idle-detection": "()", + "interest-cohort": "()", + "serial": "()", + "sync-script": "()", + "trust-token-redemption": "()", + "unload": "()", + "window-management": "()", + "vertical-scroll": "()", + } + # Initialise app extensions assets.init_app(app) compress.init_app(app) @@ -51,7 +97,12 @@ def create_app(config_class=Config): limiter.init_app(app) login.init_app(app) migrate.init_app(app, db) - talisman.init_app(app, content_security_policy=csp, content_security_policy_nonce_in=["style-src"]) + talisman.init_app( + app, + content_security_policy=csp, + content_security_policy_nonce_in=["style-src"], + permissions_policy=permissions_policy, + ) # Create static asset bundles js = Bundle("src/js/*.js", filters="jsmin", output="dist/js/custom-%(version)s.min.js") diff --git a/app/templates/base.html b/app/templates/base.html index 274cb9d4..74e29238 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -35,7 +35,7 @@ - + Mash Time Tracker{% if title %} | {{ title }}{% endif %} diff --git a/migrations/versions/13384866a8a2_add_schedule.py b/migrations/versions/13384866a8a2_add_schedule.py index 1de2af39..1ce9d818 100644 --- a/migrations/versions/13384866a8a2_add_schedule.py +++ b/migrations/versions/13384866a8a2_add_schedule.py @@ -5,6 +5,7 @@ Create Date: 2019-09-08 21:17:47.324158 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/133b4e91f81b_create_user_table.py b/migrations/versions/133b4e91f81b_create_user_table.py index da5a5b0e..90d51141 100644 --- a/migrations/versions/133b4e91f81b_create_user_table.py +++ b/migrations/versions/133b4e91f81b_create_user_table.py @@ -5,6 +5,7 @@ Create Date: 2019-04-18 00:02:59.183837 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/migrations/versions/302f5d0d3fb7_add_default_tag_id.py b/migrations/versions/302f5d0d3fb7_add_default_tag_id.py index 9af63767..b56e5e96 100644 --- a/migrations/versions/302f5d0d3fb7_add_default_tag_id.py +++ b/migrations/versions/302f5d0d3fb7_add_default_tag_id.py @@ -5,6 +5,7 @@ Create Date: 2021-03-07 08:33:21.726556 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/migrations/versions/55b4d6070aa0_add_event_comment.py b/migrations/versions/55b4d6070aa0_add_event_comment.py index 203f1ed6..c5fa5550 100644 --- a/migrations/versions/55b4d6070aa0_add_event_comment.py +++ b/migrations/versions/55b4d6070aa0_add_event_comment.py @@ -5,6 +5,7 @@ Create Date: 2020-12-03 08:44:09.199511 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/85a27b4f273d_remove_entry_limit.py b/migrations/versions/85a27b4f273d_remove_entry_limit.py index b73e66d0..242ca3aa 100644 --- a/migrations/versions/85a27b4f273d_remove_entry_limit.py +++ b/migrations/versions/85a27b4f273d_remove_entry_limit.py @@ -5,6 +5,7 @@ Create Date: 2021-01-30 23:03:25.102789 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/89fec1d69a9d_create_event_table.py b/migrations/versions/89fec1d69a9d_create_event_table.py index beab3c10..5f5ae910 100644 --- a/migrations/versions/89fec1d69a9d_create_event_table.py +++ b/migrations/versions/89fec1d69a9d_create_event_table.py @@ -5,6 +5,7 @@ Create Date: 2019-04-23 10:18:50.019797 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/migrations/versions/a0f729fa8c10_remove_user_name.py b/migrations/versions/a0f729fa8c10_remove_user_name.py index 87cd7539..bd005fd2 100644 --- a/migrations/versions/a0f729fa8c10_remove_user_name.py +++ b/migrations/versions/a0f729fa8c10_remove_user_name.py @@ -5,6 +5,7 @@ Create Date: 2019-04-23 22:50:41.512508 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/a9da40cf2371_add_entry_limit.py b/migrations/versions/a9da40cf2371_add_entry_limit.py index 909ec4e9..e5dc3510 100644 --- a/migrations/versions/a9da40cf2371_add_entry_limit.py +++ b/migrations/versions/a9da40cf2371_add_entry_limit.py @@ -5,6 +5,7 @@ Create Date: 2019-07-01 23:57:32.993035 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/cf04f2a23d02_create_tag_table.py b/migrations/versions/cf04f2a23d02_create_tag_table.py index faf138ae..8ed76705 100644 --- a/migrations/versions/cf04f2a23d02_create_tag_table.py +++ b/migrations/versions/cf04f2a23d02_create_tag_table.py @@ -5,6 +5,7 @@ Create Date: 2019-07-26 14:12:01.532883 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/migrations/versions/db8ced4ce2b2_add_activated_at.py b/migrations/versions/db8ced4ce2b2_add_activated_at.py index eda8102c..8748107c 100644 --- a/migrations/versions/db8ced4ce2b2_add_activated_at.py +++ b/migrations/versions/db8ced4ce2b2_add_activated_at.py @@ -5,6 +5,7 @@ Create Date: 2019-06-14 14:57:10.824952 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/e354a89547c4_add_entry_history.py b/migrations/versions/e354a89547c4_add_entry_history.py index ed5c172c..222fa91e 100644 --- a/migrations/versions/e354a89547c4_add_entry_history.py +++ b/migrations/versions/e354a89547c4_add_entry_history.py @@ -5,6 +5,7 @@ Create Date: 2021-01-30 23:06:01.790266 """ + import sqlalchemy as sa from alembic import op diff --git a/migrations/versions/fd87ce16f8fd_add_location.py b/migrations/versions/fd87ce16f8fd_add_location.py index f4da67d1..212ca747 100644 --- a/migrations/versions/fd87ce16f8fd_add_location.py +++ b/migrations/versions/fd87ce16f8fd_add_location.py @@ -5,6 +5,7 @@ Create Date: 2022-08-08 22:58:24.951737 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/migrations/versions/ffd26960aa0d_add_timezone.py b/migrations/versions/ffd26960aa0d_add_timezone.py index bda66f6e..fc438346 100644 --- a/migrations/versions/ffd26960aa0d_add_timezone.py +++ b/migrations/versions/ffd26960aa0d_add_timezone.py @@ -5,6 +5,7 @@ Create Date: 2019-05-08 16:12:45.155437 """ + import sqlalchemy as sa from alembic import op diff --git a/requirements.in b/requirements.in index fd477654..7fb45922 100644 --- a/requirements.in +++ b/requirements.in @@ -2,7 +2,7 @@ bcrypt==4.1.2 email_validator==2.1.0.post1 flask-assets==2.1.0 flask-compress==1.14 -flask-limiter[redis]==3.5.0 +flask-limiter[redis]==3.5.1 flask-login==0.6.3 flask-migrate==4.0.5 flask-sqlalchemy==3.1.1 @@ -13,6 +13,6 @@ gunicorn==21.2.0 jsmin==3.0.1 psycopg2==2.9.9 pyjwt==2.8.0 -pytz==2023.3.post1 +pytz==2023.4 requests==2.31.0 werkzeug<3.0.0 diff --git a/requirements.txt b/requirements.txt index 14f20177..6b4a1d99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile requirements.in @@ -12,7 +12,7 @@ blinker==1.7.0 # via flask brotli==1.1.0 # via flask-compress -certifi==2023.11.17 +certifi==2024.2.2 # via requests charset-normalizer==3.3.2 # via requests @@ -20,7 +20,7 @@ click==8.1.7 # via flask deprecated==1.2.14 # via limits -dnspython==2.4.2 +dnspython==2.6.0 # via email-validator email-validator==2.1.0.post1 # via -r requirements.in @@ -38,10 +38,8 @@ flask-assets==2.1.0 # via -r requirements.in flask-compress==1.14 # via -r requirements.in -flask-limiter[redis]==3.5.0 - # via - # -r requirements.in - # flask-limiter +flask-limiter[redis]==3.5.1 + # via -r requirements.in flask-login==0.6.3 # via -r requirements.in flask-migrate==4.0.5 @@ -68,17 +66,17 @@ itsdangerous==2.1.2 # via # flask # flask-wtf -jinja2==3.1.2 +jinja2==3.1.3 # via flask jsmin==3.0.1 # via -r requirements.in -limits[redis]==3.7.0 +limits[redis]==3.9.0 # via flask-limiter -mako==1.3.0 +mako==1.3.2 # via alembic markdown-it-py==3.0.0 # via rich -markupsafe==2.1.3 +markupsafe==2.1.5 # via # jinja2 # mako @@ -98,7 +96,7 @@ pygments==2.17.2 # via rich pyjwt==2.8.0 # via -r requirements.in -pytz==2023.3.post1 +pytz==2023.4 # via -r requirements.in redis==5.0.1 # via limits @@ -106,7 +104,7 @@ requests==2.31.0 # via -r requirements.in rich==13.7.0 # via flask-limiter -sqlalchemy==2.0.24 +sqlalchemy==2.0.27 # via # alembic # flask-sqlalchemy @@ -116,7 +114,7 @@ typing-extensions==4.9.0 # flask-limiter # limits # sqlalchemy -urllib3==2.1.0 +urllib3==2.2.1 # via requests webassets==2.0 # via flask-assets @@ -127,5 +125,5 @@ werkzeug==2.3.8 # flask-login wrapt==1.16.0 # via deprecated -wtforms==3.1.1 +wtforms==3.1.2 # via flask-wtf diff --git a/requirements_dev.txt b/requirements_dev.txt index 0ebee22b..3f366115 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,19 +1,23 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile requirements_dev.in # -attrs==23.1.0 +attrs==23.2.0 # via flake8-bugbear -bandit==1.7.6 +authlib==1.3.0 + # via safety +bandit==1.7.7 # via -r requirements_dev.in -black==23.12.1 +black==24.2.0 # via -r requirements_dev.in build==1.0.3 # via pip-tools -certifi==2023.11.17 +certifi==2024.2.2 # via requests +cffi==1.16.0 + # via cryptography charset-normalizer==3.3.2 # via requests click==8.1.7 @@ -22,30 +26,35 @@ click==8.1.7 # pip-tools # pur # safety -coverage[toml]==7.4.0 + # typer +coverage[toml]==7.4.1 + # via pytest-cov +cryptography==42.0.3 + # via authlib +dparse==0.6.4b0 # via - # coverage - # pytest-cov -dparse==0.6.3 - # via safety -flake8==6.1.0 + # safety + # safety-schemas +flake8==7.0.0 # via # flake8-bugbear # pep8-naming -flake8-bugbear==23.12.2 +flake8-bugbear==24.2.6 # via -r requirements_dev.in -gitdb==4.0.11 - # via gitpython -gitpython==3.1.40 - # via bandit idna==3.6 # via requests iniconfig==2.0.0 # via pytest isort==5.13.2 # via -r requirements_dev.in +jinja2==3.1.3 + # via safety markdown-it-py==3.0.0 # via rich +markupsafe==2.1.5 + # via jinja2 +marshmallow==3.20.2 + # via safety mccabe==0.7.0 # via flake8 mdurl==0.1.2 @@ -57,31 +66,41 @@ packaging==23.2 # black # build # dparse + # marshmallow # pytest # safety + # safety-schemas pathspec==0.12.1 # via black pbr==6.0.0 # via stevedore pep8-naming==0.13.3 # via -r requirements_dev.in -pip-tools==7.3.0 +pip-tools==7.4.0 # via -r requirements_dev.in -platformdirs==4.1.0 +platformdirs==4.2.0 # via black -pluggy==1.3.0 +pluggy==1.4.0 # via pytest pur==7.3.1 # via -r requirements_dev.in pycodestyle==2.11.1 # via flake8 -pyflakes==3.1.0 +pycparser==2.21 + # via cffi +pydantic==1.10.14 + # via + # safety + # safety-schemas +pyflakes==3.2.0 # via flake8 pygments==2.17.2 # via rich pyproject-hooks==1.0.0 - # via build -pytest==7.4.3 + # via + # build + # pip-tools +pytest==8.0.1 # via pytest-cov pytest-cov==4.1.0 # via -r requirements_dev.in @@ -90,19 +109,33 @@ pyyaml==6.0.1 requests==2.31.0 # via safety rich==13.7.0 - # via bandit -ruamel-yaml==0.18.5 - # via safety + # via + # bandit + # safety +ruamel-yaml==0.18.6 + # via + # safety + # safety-schemas ruamel-yaml-clib==0.2.8 # via ruamel-yaml -safety==2.3.4 +safety==3.0.1 # via -r requirements_dev.in -smmap==5.0.1 - # via gitdb +safety-schemas==0.0.2 + # via safety stevedore==5.1.0 # via bandit -urllib3==2.1.0 - # via requests +typer==0.9.0 + # via safety +typing-extensions==4.9.0 + # via + # pydantic + # safety + # safety-schemas + # typer +urllib3==2.2.1 + # via + # requests + # safety wheel==0.42.0 # via pip-tools diff --git a/runtime.txt b/runtime.txt index d45f665d..b884b0fd 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.11.7 \ No newline at end of file +python-3.12.2 \ No newline at end of file