fix: address 7 findings from security review#30
Merged
olivierlambert merged 1 commit intomainfrom Apr 4, 2026
Merged
Conversation
Fixes XSS, IDOR, SSRF, and CSRF vulnerabilities identified during a full codebase security review. - Stored XSS: replace innerHTML with textContent/createElement for user-controlled data in team and event type search results - IDOR: add ownership checks on invite delete, create, quick-link, and invite management page for private event types - SSRF: validate CalDAV source URLs against private IP ranges and non-HTTP schemes before making requests - CSRF: change booking approval from GET to GET(form)+POST(action) to prevent auto-approval by email security scanners Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes 7 vulnerabilities (4 High, 2 Medium, 1 template-level) identified during a full codebase security review.
High severity
Stored XSS via innerHTML — User-controlled data (
name,email,username) was rendered viainnerHTMLin team/event-type search dropdowns. Minijinja's auto-escaping produces HTML entities (<) whichinnerHTMLdecodes back to live HTML. Replaced all instances with safe DOM APIs (textContent,createElement). Affected:team_settings.html,team_form.html,event_type_form.html.IDOR: invite deletion —
POST /dashboard/invites/{id}/deletehad no ownership check. Any authenticated user could delete any invite. Added ownership verification viaaccounts.user_idorteam_membersmembership.IDOR: invite creation for private event types —
POST /dashboard/invites/{id}/sendandPOST /dashboard/invites/{id}/quick-linkdid not enforce the documented rule that private event types restrict invite creation to the owner. Added ownership check forprivatevisibility;internalremains open to all authenticated users by design.SSRF via CalDAV source URLs — No validation on user-supplied CalDAV URLs allowed probing internal networks (cloud metadata, localhost services). Added
validate_caldav_url()that rejects non-HTTP(S) schemes, private/reserved IP ranges (RFC 1918, loopback, link-local, CGNAT, IPv6 ULA), and resolves hostnames to check all IPs before connecting.Medium severity
IDOR: invite management page —
GET /dashboard/invites/{id}leaked private event type details (title, guest PII, active invite tokens) to any authenticated user. Added ownership check forprivatevisibility.Booking approval via GET —
GET /booking/approve/{token}performed irreversible side effects (confirm booking, CalDAV write-back, send emails). Email security scanners (Safe Links, Proofpoint) auto-follow links, causing unintended approvals. Changed to two-step flow matching existing decline/cancel pattern: GET renders confirmation form, POST performs mutation.Files changed
src/caldav/mod.rsvalidate_caldav_url(),is_private_ip()src/web/mod.rstemplates/event_type_form.htmltemplates/team_form.htmltemplates/team_settings.htmltemplates/booking_approve_form.htmlTest plan
<img src=x onerror=alert(1)>as name, verify no XSS in team searchhttp://127.0.0.1orhttp://169.254.169.254is rejected🤖 Generated with Claude Code