Repository navigation
Release v0.78.0
🤖 AI-Generated Changelog
Security
- Hardened admin permission checks: Custom admin sync views (import, pull, push) now enforce Django model-level permissions (
add,change,view) in addition to staff status, preventing unauthorized form-definition access - Replaced client-controlled file stashing with server-side session tracking: Uploaded files are now validated and tracked server-side in the user's session rather than via hidden
_stashed_filesPOST fields, eliminating client-supplied metadata injection and path traversal risks - Fixed open access to success page: The custom success page (
submission_success) now requires either an authenticated user with visibility over the submission or a short-lived session receipt issued at submission time, preventing enumeration of arbitrary submission IDs - Hardened SSO account linking: The
link_to_existing_userpipeline function no longer auto-links SSO identities to existing accounts by email or username; linking now requires an explicit administrator-configuredaccount_bindingsmapping inFORMS_WORKFLOWS_SSO, eliminating account-takeover risk - Fixed analytics data scoping: The analytics dashboard and CSV export now filter submissions through
visible_submissions, ensuring users can only see and export data for submissions they are authorized to access - Fixed CSV formula injection: Analytics CSV exports now prefix cells starting with
=,+,-, or@with a single quote to prevent spreadsheet formula injection - Fixed success message XSS: Answer tokens piped into success messages are now HTML-escaped before HTML sanitization via
nh3, preventing stored XSS through malicious form submissions - Escaped filenames in file field help text: Previously-uploaded filenames shown in help text are now HTML-escaped, preventing stored XSS via crafted filenames
- Fixed embedded form authentication bypass: The embedded form view now enforces
requires_loginandone_per_userrestrictions, which were previously not applied to the embed endpoint - Hardened IP-based rate limiting: Client IP extraction now only trusts
X-Forwarded-Forheaders from CIDR ranges listed inFORMS_WORKFLOWS_TRUSTED_PROXIES, preventing rate-limit bypass via spoofed headers - Rate limiting now uses atomic cache increments: Fixed-window rate limiting now uses
cache.add/cache.incrto prevent race conditions that allowed bursting past the configured limit - Restricted
display_textfields: Display-only form fields are now rendered withdisabled=Trueto prevent client-supplied values from being accepted - Hardened PDF generation: WeasyPrint PDF export now uses a restricted
url_fetcherto limit outbound requests made during PDF rendering - File upload validators applied to multi-file fields: File type and size validators are now consistently applied to multi-file upload fields
- Sanitized JSON embedded in HTML: JSON data embedded in analytics dashboard templates now has
<,>, and&escaped to prevent HTML injection - Replaced timestamp-based file paths with UUIDs: Temporary uploaded file storage now uses
uuid4instead of a timestamp, preventing path prediction
Changed
- Django minimum version raised to 5.2.18: Support for Django versions with known security vulnerabilities has been removed; Django 6.0.x and 6.1.x patch releases with outstanding CVEs are explicitly excluded
nh3is now a required dependency: The HTML sanitization librarynh3is now a mandatory dependency rather than optionalFORMS_WORKFLOWS_TRUSTED_PROXIESsetting required for proxy deployments: Deployments behind a reverse proxy must now explicitly configure trusted proxy CIDR ranges to enableX-Forwarded-Forheader trustFORMS_WORKFLOWS_RATE_LIMIT_CACHEsetting recommended: A new setting allows specifying a dedicated Redis or Memcached cache backend for rate limiting; a deployment check (django_forms_workflows.W001) now warns when a non-shared cache is used- SSO
link_to_existing_userandusername_from_emailsettings removed: These settings are replaced by the explicitaccount_bindingsconfiguration; existing pipelines relying on automatic username/email linking must be updated - Draft auto-save now strips file metadata and unknown keys from POST data: The
draft_datahelper ensures only scalar field values owned by the form are persisted to draft records, preventing arbitrary data injection through the auto-save endpoint
Added
- Deployment system check for rate-limit cache: Running
manage.py check --deploynow warns (W001) when the configured rate-limit cache backend does not support atomic operations needed for correct rate limiting
🔗 Full Changelog: v0.77.5...v0.78.0