Commit Graph
7 Commits
Author SHA1 Message Date
dualfroz 6a87749efd fix(ical): do not expose user email addresses in calendar feeds
The project and user iCal feeds only need a token and they put the
email address of the task assignee and creator in ATTENDEE and
ORGANIZER. Always use the username@kanboard.local address that was
already the fallback for users without an email.

This also fixes ORGANIZER for creators without an email, which was
rendered as a bare MAILTO: because of operator precedence.
2026-10-03 15:14:00 +02:00
dualfroz 43d1e8b58c fix(api): remove author email addresses from comments and activity
getComment, getAllComments, getProjectActivity, getProjectActivities and
getMyActivityStream returned the email address of the comment or event
author to any project member. Comment events also carry it in their
stored comment data.

The models keep the column since the web UI needs it for avatars, the
procedures drop it before answering.

Fixes #5876
2026-10-03 17:19:19 +02:00
dualfroz cce89ba4a2 fix(http): normalize the host before the private network check
parse_url() keeps the brackets around an IPv6 literal, so "[::1]" or
"[::ffff:127.0.0.1]" never matched an address and isPrivateURL() let the
request through. A host that does not resolve was allowed for the same
reason, while cURL still connects to forms like "0x7f000001" or
"127.0.0.1." on its own.

Strip the brackets and the trailing dot, check IP literals directly, check
every resolved address, and treat a host without any address as private.
IPv4-mapped IPv6 addresses are checked through their IPv4 part, since
FILTER_FLAG_NO_RES_RANGE does not classify them the same way on every PHP
version.

Fixes #5858
Fixes #5871
2026-10-03 17:43:14 +02:00
dualfroz bb891e182e fix(security): escape the project name in the analytic modal title
LayoutHelper::analytic() prefixes the title with the raw project name, and
the AJAX branch of analytic/layout.php printed that title as is, so a
project name containing markup was injected into the analytic modals.

Escape it with $this->text->e() like the other layouts do. It does not
double-encode, so the ">" separator still renders as ">".
2026-10-03 15:58:07 +02:00
dualfroz 23bbaa8c60 fix(ical): only accept known columns as the calendar start date
The calendar_project_tasks and calendar_user_tasks settings were used as a
column name in the iCal query, and escapeIdentifier() leaves values with a
space or a dot untouched. A stored value like "1 OR 1=1 OR 1" made the public
project feed return tasks from every project.

Only date_creation and date_started are accepted now, anything else falls
back to date_started. The currency form also stops saving keys other than
application_currency, which is how the value could be written in the first
place.

Fixes #5904
2026-10-03 16:44:04 +02:00
dualfroz 19540701b6 fix(session): scope the session cookie to the directory without a trailing slash
UrlHelper::dir() always returns a trailing slash, so the session cookie was
scoped to "/kanboard/". That cookie is not sent back for "/kanboard", which
is exactly the url the bundled web.config and .htaccess serve the application
on: both rewrite to index.php whenever the request is not a file, so the
directory url is never redirected to its trailing-slash form.

The first login then stores redirectAfterLogin="/kanboard", redirects there
after a successful check, arrives without the session cookie and bounces back
to the login form with no error message.

Use the directory without the trailing slash, which is what the browser would
have picked as the default cookie path anyway and still matches every url
below it.
2026-10-02 09:50:13 +08:00
dualfroz 16430fd3d2 fix(api): return a full batch response when one request is forbidden
An AccessDeniedException raised by a single request was relayed out of the
batch loop, so the whole call answered with one error object instead of the
array of responses required by the JSON-RPC spec. Authentication failures
still fail the whole call.

Fixes #3879
2026-09-11 13:43:43 -07:00