Releases: getkirby/kirby
5.4.0
🚨 Security
Server-Side Template Injection (SSTI) via double template resolution in option rendering
This vulnerability affects all Kirby sites that use option fields (checkboxes, color, multiselect, select, radio, tags or toggles) with options from a query or API whose values may not be fully trusted. It also affects direct uses of the OptionsApi or OptionsQuery classes of Kirby's Options package from plugin or site code. The attack requires either an
attacker in the group of authenticated Panel users or user interaction of another authenticated user.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you are not using any of the mentioned fields or the Options package, if all options are defined statically in the blueprints or if all dynamically gathered options are to be trusted.
- CVE ID: CVE-2026-34587
- Severity: high (CVSS score 7.6)
- Advisory: GHSA-jcjw-58rv-c452
Thanks to @offset for responsibly reporting the identified issue.
Page, file and user creation APIs bypass create permission check via unfiltered blueprint parameter
This vulnerability affects all Kirby sites where users of a particular role have no permission to create pages, files or users (pages.create, files.create or users.create permission is disabled). This can be due to configuration in the user blueprint(s), via options in the model blueprint(s) or via a combination of both settings.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to create pages, files and users. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-41325
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-6gqr-mx34-wh8r
Thanks to @offset for responsibly reporting the identified issue.
pages.access/list and files.access/list permissions are not consistently checked in the Panel and REST API
This vulnerability affects all Kirby sites where users of a particular role have no permission to access or list pages or files (pages.access, pages.list, files.access or files.list permission is disabled). This can be due to configuration in the user blueprint(s), via options in the model blueprint(s) or via a combination of both settings.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to access all pages and files of the site. The vulnerability can only be exploited by authenticated users.
Write actions are not affected by this vulnerability.
- CVE ID: CVE-2026-42137
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-85x2-r8xv-ww8c
Read access to site, user and role information is not gated by permissions
This vulnerability affects all Kirby sites that might have potential attackers in the group of authenticated Panel users.
This vulnerability is of high severity for affected sites.
Your Kirby sites are not affected if you intend all users of your site to be able to list and access the site model and all users and roles, including the content stored within these models.
Write actions are not affected by this vulnerability as they were gated by permissions before.
- CVE ID: CVE-2026-42069
- Severity: high (CVSS score 7.1)
- Advisory: GHSA-2h7v-4372-f6x2
Thanks to @HuajiHD for responsibly reporting the identified issue.
XML Injection in the XML creator toolkit
This vulnerability only affects Kirby sites that use the Xml data handler (e.g. Data::encode($string, 'xml')) or the Xml::create(), Xml::tag() or Xml::value() method(s) in site or plugin code. The Kirby core does not use any of the affected methods.
If you use an affected method and cannot rule out input to these methods controlled by an attacker, we strongly recommend to update to a patch release.
- CVE ID: CVE-2026-32870
- Severity: medium (CVSS score 6.9)
- Advisory: GHSA-9wfj-c55w-j9qr
Thanks to Patrick Falb (@dapatrese) at FORMER 03 for responsibly reporting the identified issue.
User avatar creation, replacement and deletion are not gated by user update permissions
This vulnerability affects all Kirby sites where users of a particular role have no permission to update user information (user.update or users.update permission is disabled). This can be due to configuration in the blueprint(s) of the acting users, via options in the blueprint(s) of the target users or via a combination of both settings.
Your Kirby sites are not affected if you intend all users of your site to be able to upload, replace or delete user avatars. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-42174
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-39cp-6679-8xv2
Page creation API bypasses changeStatus permission check via unfiltered isDraft parameter
This vulnerability affects all Kirby sites where users have the permission to create pages (pages.create permission is enabled) but not the permission to change the status of pages (pages.changeStatus permission is disabled). This can be due to configuration in the user blueprint(s), via options in the page blueprint(s) or via a combination of both settings.
Your Kirby sites are not affected if your use case does not consider the creation of published pages a malicious action. The vulnerability can only be exploited by authenticated users.
- CVE ID: CVE-2026-40099
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-w942-j9r6-hr6r
Thanks to @offset for responsibly reporting the identified issue.
System API endpoint leaks installed version and license data to authenticated users
This vulnerability affects all Kirby sites that might have potential attackers in the group of authenticated Panel users.
- CVE ID: CVE-2026-42051
- Severity: moderate (CVSS score 5.3)
- Advisory: GHSA-x68m-c7jf-2572
Thanks to @HuajiHD and @0x-bala for responsibly reporting the identified issue.
✨ Enhancements
- Site permissions
- New
accesspermission for thesite - New
Kirby\Cms\Site::isAccessible()method checking if the current user hasaccesspermission for the site - New static
Kirby\Cms\Find::site()method returning the site object or throwingKirby\Exception\NotFoundExceptionif the site is not accessible - New i18n string
error.site.notAccessibleadded toi18n/translations/en.json
- New
- User permissions
- New
accessandlistpermissions for users and the current user. - New
Kirby\Cms\User::isAccessible()method checking if the current user hasaccesspermission for a given user - New
Kirby\Cms\User::isListable()method checking if a user is both accessible and haslistpermission. Inaccessible users are implicitly not listable - New static
Kirby\Cms\Find::users()method returning only users filtered byisListable()
- New
- Role permissions
- New
Kirby\Cms\Role::isAccessible()method checking if the current user hasusers.accessoruser.accesspermission. If the role is the same role as the user's, theuser.accesspermissions are checked. Otherwiseusers.access. - New static
Kirby\Cms\Find::role()andKirby\Cms\Find::roles()methods returning only roles filtered byisAccessible() - Added a new
error.role.notFoundtranslation key.
- New
- Avatar permissions
- New avatar hooks
user.createAvatar,user.replaceAvatar,user.deleteAvatar(including:beforeand:after) - New User class methods:
User::createAvatar(),User::replaceAvatar(),User::deleteAvatar() - New User rules:
UserRules::createAvatar(),UserRules::replaceAvatar(),UserRules::deleteAvatar(),UserRules::validAvatar()
- New avatar hooks
🚨 Security fixes
- The
GET /systemAPI route now consistently filters the relevant set of information by current system state Kirby\Cms\Find::parent()now usesKirby\Cms\Find::site()instead of$kirby->site()for the site model lookupKirby\Cms\Api::site()now delegates toKirby\Cms\Find::site()instead of$this->kirby->site()config/api/models/System.phpthetitlefield now reads directly from$this->kirby()->site()to bypass thesite.accesspermission check, ensuring the title is always available- The
page.movedialog now usesKirby\Cms\Find::site()in the submit handler, when a page gets moved to the top-level Kirby\Cms\Find::user()now enforcesisAccessible()on the resolved user, throwingKirby\Exception\NotFoundExceptionif the user exists but is inaccessible- API routes (
config/api/routes/users.php): all `$this->user()...
4.9.0
🚨 Security
This is a backport of our security release for Kirby 5. For all details and vulnerabilities see: https://github.com/getkirby/kirby/releases/tag/5.4.0
We recommend all users upgrade to Kirby 5. If an upgrade is not possible, this security release is the alternative solution.
5.3.3
🐛 Bug fixes
- Pages section table index resets to 1 on each pagination page #8002
- Added missing return types to
Kirby\Cms\Responder#8013 - Disabling PHP's
post_max_sizeno longer causes uploads to fail. #8022 - Fixed the Panel offline warning dialog text in dark mode #8047
- Fixed site view buttons when home preview is false #8046
- Added labels to the blocks field options button and the form controls more button (thanks @FlorianBoe) #8035
🧹 Housekeeping
- Improve test coverage for the Database package #8021
- Updated JS dependencies
5.3.2
🐛 Bug fixes
- Child page content no longer includes parent’s content after using page create dialog #7970
Url::to()strips content representation extension on multilang sites #7965- Prevent duplicate draft when using
page.create:afterhook (Kirby 5.3.x) #7957
🧹 Housekeeping
- Switch to type module #7962
- Upgrade JS and PHP dependencies
5.3.1
✨ Enhancements
- Updated translation (tr)
🐛 Bug fixes
- Using
$users->find()with more than one argument or$field->toUsers()/$field->toUser()no longer results in unfiltered collections. #7943 - Calling
$users->find(false)no longer loads an invalid empty user object. #7952 $lazyCollection->prepend()and$users->prepend()ensure the intended element order even if the collection was not initialized before. #7952$lazyCollection->empty()and$users->empty()no longer result in populated collections if the original collection was not initialized before. #7952- Toggle field: Fixed duplicate display of field icon #7939
- Fixed styling of tags with icons (e.g. link field preview) #7938
- Fixed view button actions on the file view #7954
🧹 Housekeeping
- Add missing code comments on the behavior of
$collection->find(false, false, ...$data)#7952 - Updated CI config for backend tests
5.3.0
Caution
Unfortunately the Kirby 5.3.0 release introduced a regression in the user handling that leads to wrong results when using $users->find(), $field->toUsers() or $field->toUser(). All of these wrongly return the entire set of users without filtering.
Please update to Kirby 5.3.1 or later.
🎉 Features
- Support for option icons in checkboxes, multiselect, radio and tags field #7673



- New
<k-code-token>component and global styles for inline<code>elements withdata-typeattribute. The styles for the colored inline elements have been taken from our lab examples and are now available anywhere. The type can either be a generic type (string, float, bool, etc.) or a color keyword from our design system (green, red, orange, etc.) #7765

- New
<k-stack>component to help with horizontal and vertical layouts. Think of it as a flex layout helper component. It's perfect to create equal gaps between elements in a column or row. E.g. different sections or the gap between the headline and contents of a container. #7766

You can either use the component as a wrapper (which will create a div):… or use the k-stack class on an existing wrapper element to inherit the basic stack styles:<k-stack> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
Use the attributes<ul class="k-stack"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </ul>
gap,direction,alignandjustifyto control the layout.Those are applied as inline styles. If you use the<k-stack gap="var(--spacing-12)" align="center" direction="row" justify="space-between"> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
k-stackclass on a custom element, you need to set the inline styles manually or with the CSS rules for your element. - New
<k-definitions>and<k-definition>components to build definition lists in the style of our tables. This is particularly useful to show any kind of information in a semantic way. We will use this for our new error dialogs. #7767
Definition items can also be created with custom slots:<k-definitions> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> </k-definitions>
<k-definitions> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> </k-definitions>
- New
<k-checklist>component to create appealing lists of items that are marked as checked, to be noticed or errors. We will be using this in our new error dialogs, but the component is also very helpful for all kinds of scenarios in plugins and other parts of the Panel. #7771
Applying a theme:<k-checklist> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
All color themes are supported.<k-checklist theme="negative"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
noticeandnegativewill automatically change the marker (see screenshot) You can easily add your own custom markers as well.<k-checklist style="--checklist-marker: '💛'"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
- New
Kirby\Http\Url::editor($editor, $file, $line)method, to create local editor URLs to open files in a code editor at the given line. #7768<a href="<?= Url::editor('vscode', '/my/local/file.php', 12) ?>">Open in VSCode</a>
- Preview view: Button to sync scrolling in the compare mode #7813
- New
scroll-to-bottomandscroll-to-bottom-fillicons #7813 - New
LazyCollectionclass that initializes and loads its data and elements only when they are first needed #7839
⚡Performance
- Improved performance of UUID enabled check #7094
- User credentials (main data from
index.php) are only loaded once when the user object is first created, improving system performance with many user accounts. - Significantly improved performance when large numbers of user accounts are set up #7841
✨ Enhancements
$visitor->ip()supports new$hashparameter to retrieve a 50 char long hash of the visitor's IP- More readable file paths in JSON error responses for the Panel. Absolute paths to the kirby folder, site folder and index folder will now be replaced with
{kirby},{site}and{index}. This will keep the responses more readable and easier to debug. It will also disguise the filesystem a bit. Although this is not the main intention, since those paths are only visible in debug mode anyway. #7772 - New
layout-top+layout-bottomicons #7814 - Child classes of
Iterator(mostly collections) can now implement a custom iterator and are not pinned toArrayIterator#7838 - New
User::hasPassword()method to provide a solid check for an existing password #7869 - The user dropdown now uses "Set password" instead of "Change password" for users that don't have a password so far. #7869

- Added support for view button separators using (thx @tobimori ) #7873
buttons:
- open
- preview
- '-'
- languages
- '-'
- settings- New
OfflineErrorerror type inkirby/panel/src/errors/OfflineError.js. kirby/panel/src/panel/request.jsnow usessafeFetch()and emits offline on network failures.kirby/panel/src/api/request.jsusessafeFetch()instead of rawfetch().kirby/panel/src/panel/panel.jscatchesOfflineErrorand setsisOffline.- Kirby now can handle HTTP range requests for partial content delivery #1207
- New
Filesystem\F::range($file, $offset, $length)method to only read parts of a file - New
Http\Rangeclass for handling HTTP range requests <k-drawer>has newsizeprop (options:tiny,small,default,large,huge) #7900<k-tag>: support foricon. #7886<k-checkboxes-input>,<k-radio-input>,<k-toggle-input>: support for additionaliconalongside text and info for the label #7886Kirby\Filesystem\F::load()has a newcacheparameter which will return the file content from cache or add the loaded file content to a cache on the first time its loaded #7920
🐛 Bug fixes
- Page move dialog: show spinner while loading https://feedback.getkirby.com/652
- Fixes broken selection state in textarea buttons if not initialized #7831
Iterator::has()and thehas()method of collections correctly treats an existing butnullvalue as a valid collection element #7838- UUID cache gets populated on model actions (e.g. page creation) #7809
- Users can now set their first password (if they had none so far) without providing their current one. This only works for their own account. A user without password cannot change the password of any other user. #7869
- Empty passwords are no longer incorrectly hashed #7869
A::get(): Prefer dotted prefix keys to avoid option collisions of full dotted pr...
6.0.0-alpha.2
TL;DR:
Kirby 6.0.0-alpha.2 is an early developer preview. We plan for a final release in the second half of 2026. Kirby 6 will be a free upgrade for all Kirby 4 & 5 license holders.
Important
Don't use Kirby 6 in production yet
Highlights
✍️ Live editor
📄 Simplified blueprint definition
🥞 New template stacks
🔘 New buttons field
Changelog
We are collecting all changes in our pre-release changelog, if you already want to dive deeper: https://github.com/getkirby/kirby/blob/6.0.0-alpha.2/CHANGELOG.md
5.3.0-rc.1
🎉 Features
- Support for option icons in checkboxes, multiselect, radio and tags field #7673



- New
<k-code-token>component and global styles for inline<code>elements withdata-typeattribute. The styles for the colored inline elements have been taken from our lab examples and are now available anywhere. The type can either be a generic type (string, float, bool, etc.) or a color keyword from our design system (green, red, orange, etc.) #7765

- New
<k-stack>component to help with horizontal and vertical layouts. Think of it as a flex layout helper component. It's perfect to create equal gaps between elements in a column or row. E.g. different sections or the gap between the headline and contents of a container. #7766

You can either use the component as a wrapper (which will create a div):… or use the k-stack class on an existing wrapper element to inherit the basic stack styles:<k-stack> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
Use the attributes<ul class="k-stack"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </ul>
gap,direction,alignandjustifyto control the layout.Those are applied as inline styles. If you use the<k-stack gap="var(--spacing-12)" align="center" direction="row" justify="space-between"> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
k-stackclass on a custom element, you need to set the inline styles manually or with the CSS rules for your element. - New
<k-definitions>and<k-definition>components to build definition lists in the style of our tables. This is particularly useful to show any kind of information in a semantic way. We will use this for our new error dialogs. #7767
Definition items can also be created with custom slots:<k-definitions> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> </k-definitions>
<k-definitions> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> </k-definitions>
- New
<k-checklist>component to create appealing lists of items that are marked as checked, to be noticed or errors. We will be using this in our new error dialogs, but the component is also very helpful for all kinds of scenarios in plugins and other parts of the Panel. #7771
Applying a theme:<k-checklist> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
All color themes are supported.<k-checklist theme="negative"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
noticeandnegativewill automatically change the marker (see screenshot) You can easily add your own custom markers as well.<k-checklist style="--checklist-marker: '💛'"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
- New
Kirby\Http\Url::editor($editor, $file, $line)method, to create local editor URLs to open files in a code editor at the given line. #7768<a href="<?= Url::editor('vscode', '/my/local/file.php', 12) ?>">Open in VSCode</a>
- Preview view: Button to sync scrolling in the compare mode #7813
- New
scroll-to-bottomandscroll-to-bottom-fillicons #7813 - New
LazyCollectionclass that initializes and loads its data and elements only when they are first needed #7839
⚡Performance
- Improved performance of UUID enabled check #7094
- User credentials (main data from
index.php) are only loaded once when the user object is first created, improving system performance with many user accounts. - Significantly improved performance when large numbers of user accounts are set up #7841
✨ Enhancements
$visitor->ip()supports new$hashparameter to retrieve a 50 char long hash of the visitor's IP- More readable file paths in JSON error responses for the Panel. Absolute paths to the kirby folder, site folder and index folder will now be replaced with
{kirby},{site}and{index}. This will keep the responses more readable and easier to debug. It will also disguise the filesystem a bit. Although this is not the main intention, since those paths are only visible in debug mode anyway. #7772 - New
layout-top+layout-bottomicons #7814 - Child classes of
Iterator(mostly collections) can now implement a custom iterator and are not pinned toArrayIterator#7838 - New
User::hasPassword()method to provide a solid check for an existing password #7869 - The user dropdown now uses "Set password" instead of "Change password" for users that don't have a password so far. #7869

- Added support for view button separators using (thx @tobimori ) #7873
buttons:
- open
- preview
- '-'
- languages
- '-'
- settings- New
OfflineErrorerror type inkirby/panel/src/errors/OfflineError.js. kirby/panel/src/panel/request.jsnow usessafeFetch()and emits offline on network failures.kirby/panel/src/api/request.jsusessafeFetch()instead of rawfetch().kirby/panel/src/panel/panel.jscatchesOfflineErrorand setsisOffline.- Kirby now can handle HTTP range requests for partial content delivery #1207
- New
Filesystem\F::range($file, $offset, $length)method to only read parts of a file - New
Http\Rangeclass for handling HTTP range requests <k-drawer>has newsizeprop (options:tiny,small,default,large,huge) #7900<k-tag>: support foricon. #7886<k-checkboxes-input>,<k-radio-input>,<k-toggle-input>: support for additionaliconalongside text and info for the label #7886Kirby\Filesystem\F::load()has a newcacheparameter which will return the file content from cache or add the loaded file content to a cache on the first time its loaded #7920
🐛 Bug fixes
- Page move dialog: show spinner while loading https://feedback.getkirby.com/652
- Fixes broken selection state in textarea buttons if not initialized #7831
Iterator::has()and thehas()method of collections correctly treats an existing butnullvalue as a valid collection element #7838- UUID cache gets populated on model actions (e.g. page creation) #7809
- Users can now set their first password (if they had none so far) without providing their current one. This only works for their own account. A user without password cannot change the password of any other user. #7869
- Empty passwords are no longer incorrectly hashed #7869
A::get(): Prefer dotted prefix keys to avoid option collisions of full dotted prefix vs. nested array, e.g. with plugin options #6242- Radio input: Fixed resetting via clicking the input label #5845
- Options from query: if the query returns an associative array, Kirby now uses the array keys as values by default [#5807](https://github.com/getkirby/kirby/issue...
5.2.3
🐛 Bug fixes
- Using page title in string template of other fields #7834
- Writer Text field cannot handle multi-domain multi-language page links #7786
- The time field does now submit the form when pressing enter. #774
- Fixed console error for skipped page create dialogs #7877
- Fixed "Change Template" options for files: All available file templates are shown when sections don't define available templates #6761
- Fixed opening TOTP disable dialog #7895
- Thumb jobs files do not get regenerate if they already exist #7861
- Blocks field
5.2.2
Caution
🚨 Security
Missing permission checks in the content changes API
CVE ID: CVE-2026-21896
Severity: medium (CVSS score 5.8)
This vulnerability affects all Kirby sites (Kirby 5.0.0-5.2.1) where user permissions are configured to prevent specific role(s) from performing write actions, specifically by disabling the update permission with the intent to prevent modifications to site content.
If you haven't configured any user permissions that deviate from the default of allowing all actions, your site is not affected.
🐛 Bug fixes
- Prevent error when calling
Remote::json()with single-value JSON content (e.g. a single string, single int) #7806 - Fixed
Kirby\Toolkit\Domfor newer libxml versions #7802 - Writer field: fixed inline toolbar position on views without Panel menu #7799
$collection->group(callable)should accept empty string result as key #7830- Fixed filename field bug in upload dialog #7662
♻️ Refactored
- Reset
$_SERVERmanipulation in tests #7807