* fix: validate redirects in favicon fetching to prevent SSRF
The previous SSRF fix (GHSA-jcc6-f9v6-f7jw) only validated redirects for
the main page URL but not for the favicon fetch path. An attacker could
craft an HTML page with a favicon link that redirects to a private IP,
bypassing the IP validation and leaking internal network data as base64.
Extract a reusable `safe_get()` function that validates every redirect hop
against private/internal IPs and use it for both page and favicon fetches.
Resolves: GHSA-9fr2-pprw-pp9j
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback for SSRF favicon fix
- Fix off-by-one in redirect limit: only raise RuntimeError when the
response is still a redirect after MAX_REDIRECTS hops, not when the
final response is a successful 200
- Return final URL from safe_get() so favicon href resolution uses the
correct origin after redirects instead of the original URL
- Add unit tests for validate_url_ip and safe_get covering private IP
blocking, redirect-following, and redirect limit enforcement
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restrict role modification in ProjectMemberViewSet.partial_update to
Admins only and enforce that requesters cannot modify or assign roles
equal to or higher than their own. Previously, Guests could demote
Admins by exploiting a missing lower-bound check on role changes.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bulk update date endpoint fetched issues by ID without filtering
by workspace or project, allowing any authenticated project member to
modify start_date and target_date of issues in any workspace/project
across the entire instance (IDOR - CWE-639).
Scoped the query to include workspace__slug and project_id filters,
consistent with other issue endpoints in the codebase.
Ref: GHSA-4q54-h4x9-m329
* chore(deps): replace dotenvx with dotenv and update dependency overrides
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: sort devDependencies in package.json files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes#6746
API-driven issue updates (PUT update, PUT create-via-upsert, PATCH) were
missing `model_activity.delay()` calls, so webhooks were never dispatched
for changes made through the API. The web UI paths already include these
calls (e.g. in `post()` at L475), but the `put()` and `partial_update()`
methods only called `issue_activity.delay()`.
This adds `model_activity.delay()` immediately after each existing
`issue_activity.delay()` in these three code paths, using the same
signature as the existing call in `post()`.
Tested on Plane CE v1.2.1 self-hosted: API PATCH triggers
`webhook_send_task` in the Celery worker, confirming webhook delivery.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: replace Discord references with Forum links
* chore: migrate help and community CTAs from Discord to Forum
* refactor: replace Discord icons with lucide MessageSquare
* chore: rename Discord labels and keys to Forum
* chore: remove obsolete Discord icon component
* chore: update Discord references to Forum in templates
* chore: code refactoring
* feat: enhance authentication logging with detailed error and info messages
- Added logging for various authentication events in the Adapter and its subclasses, including email validation, user existence checks, and password strength validation.
- Implemented error handling for GitHub OAuth email retrieval, ensuring proper logging of unexpected responses and missing primary emails.
- Updated logging configuration in local and production settings to include a dedicated logger for authentication events.
* chore: address copilot comments
* chore: addressed some additional comments
* chore: update log
* fix: lint
* chore: updated the logic for page version task
* chore: updated the html variable
* chore: handled the exception
* chore: changed the function name
* chore: added a custom variable