User tests: Successful: Unsuccessful:
This PR addresses a potential XSS vulnerability by standardizing and securing the generation of HTML attributes within Joomla. Previously, the ArrayHelper::toString() method was extensively used to convert arrays of attributes into HTML strings. While core code often used this carefully, the lack of automatic HTML escaping within ArrayHelper::toString() presented a "footgun" API, making it easy for developers to accidentally introduce XSS vulnerabilities if user-supplied data was passed un-sanitized.
This PR introduces a dedicated, secure method for building HTML attributes, significantly enhancing the platform's security posture.
Introduced HTMLHelper::buildAttributes()
A new public static method buildAttributes() has been added to libraries/src/HTML/HTMLHelper.php. This method responsibly converts an array of attributes into a properly escaped HTML attribute string using htmlspecialchars(value, ENT_QUOTES, 'UTF-8').
Migrated HTMLHelper::link() and HTMLHelper::iframe()
The core HTMLHelper::link() and HTMLHelper::iframe() methods were updated to utilize HTMLHelper::buildAttributes() for their attribute generation, replacing their direct use of ArrayHelper::toString().
Comprehensive Migration Across the Codebase
All other identified instances of ArrayHelper::toString() that were responsible for generating HTML attributes have been replaced with HTMLHelper::buildAttributes().
Unit tests are provided.
All should work fine.
All should work fine.
Please select:
Documentation link for guide.joomla.org:
No documentation changes for guide.joomla.org needed
Pull Request link for manual.joomla.org:
No documentation changes for manual.joomla.org needed
| Status | New | ⇒ | Pending |
| Category | ⇒ | Front End com_users Layout Libraries Templates (site) Unit Tests |
| Labels |
Added:
Unit/System Tests
PR-6.2-dev
|
||
| Labels |
Added:
Feature
|
||
| Labels |
Added:
Conflicting Files
|
||
I would suggest to place the new code in to separated Helper under HTML/Helpers or inside one of existing.
Also it shoud be invoced like HTMLHelper::_('foobar') instead of direct call.
I would suggest to place the new code in to separated Helper under HTML/Helpers or inside one of existing.
Also it shoud be invoked like HTMLHelper::_('foobar') instead of direct call.
| Labels |
Removed:
Conflicting Files
|
||
After careful consideration, I've renamed the Attribute helper to HTML. The new HTML helper will handle methods related to HTML, such as tag generation and attribute rendering. I've also renamed buildAttributes to attributes, so the new usage is:
HTMLHelper::_('html.attributes', [...])Edit an article.
Click Versions button.
Select a version and click Preview button.
Before PR:
<button class="button-preview btn btn-primary" data-url="/Joomla_6.2.0-alpha4-dev-Development-Full_Package/administrator/index.php?option=com_contenthistory&view=preview&layout=preview&tmpl=component&32b99b8a9aa11a1a3f3f34603c376f67=1" type="button">
<span class="icon-search" aria-hidden="true"></span>
Preview</button>
After PR:
<button class="button-preview btn btn-primary" data-url="/Joomla_6.2.0-alpha4-dev+pr.47754-Development-Full_Package/administrator/index.php?option=com_contenthistory&amp;view=preview&amp;layout=preview&amp;tmpl=component&amp;6d97440605421c5b4567d4a117f90a48=1" type="button">
<span class="icon-search" aria-hidden="true"></span>
Preview</button>
An error has occurred.
404 View not found [name, type, prefix]: joomla\component\contenthistory\administrator\controller\display, html, Administrator
Call Stack
# Function Location
1 () JROOT\libraries\src\MVC\Controller\BaseController.php:884
2 Joomla\CMS\MVC\Controller\BaseController->getView() JROOT\libraries\src\MVC\Controller\BaseController.php:662
3 Joomla\CMS\MVC\Controller\BaseController->display() JROOT\libraries\src\MVC\Controller\BaseController.php:738
4 Joomla\CMS\MVC\Controller\BaseController->execute() JROOT\libraries\src\Dispatcher\ComponentDispatcher.php:143
5 Joomla\CMS\Dispatcher\ComponentDispatcher->dispatch() JROOT\libraries\src\Component\ComponentHelper.php:361
6 Joomla\CMS\Component\ComponentHelper::renderComponent() JROOT\libraries\src\Application\AdministratorApplication.php:150
7 Joomla\CMS\Application\AdministratorApplication->dispatch() JROOT\libraries\src\Application\AdministratorApplication.php:206
8 Joomla\CMS\Application\AdministratorApplication->doExecute() JROOT\libraries\src\Application\CMSApplication.php:320
9 Joomla\CMS\Application\CMSApplication->execute() JROOT\administrator\includes\app.php:58
10 require_once() JROOT\administrator\index.php:32
Edit an article.
Click Versions button.
Select a version.
Click Preview button.
Before PR:
<button class="button-preview btn btn-primary" data-url="/Joomla_6.2.0-alpha4-dev-Development-Full_Package/administrator/index.php?option=com_contenthistory&view=preview&layout=preview&tmpl=component&32b99b8a9aa11a1a3f3f34603c376f67=1" type="button">
<span class="icon-search" aria-hidden="true"></span>
Preview</button>
After PR:
<button class="button-preview btn btn-primary" data-url="/Joomla_6.2.0-alpha4-dev+pr.47754-Development-Full_Package/administrator/index.php?option=com_contenthistory&amp;view=preview&amp;layout=preview&amp;tmpl=component&amp;6d97440605421c5b4567d4a117f90a48=1" type="button">
<span class="icon-search" aria-hidden="true"></span>
Preview</button>
An error has occurred.
404 View not found [name, type, prefix]: joomla\component\contenthistory\administrator\controller\display, html, Administrator
Call Stack
# Function Location
1 () JROOT\libraries\src\MVC\Controller\BaseController.php:884
2 Joomla\CMS\MVC\Controller\BaseController->getView() JROOT\libraries\src\MVC\Controller\BaseController.php:662
3 Joomla\CMS\MVC\Controller\BaseController->display() JROOT\libraries\src\MVC\Controller\BaseController.php:738
4 Joomla\CMS\MVC\Controller\BaseController->execute() JROOT\libraries\src\Dispatcher\ComponentDispatcher.php:143
5 Joomla\CMS\Dispatcher\ComponentDispatcher->dispatch() JROOT\libraries\src\Component\ComponentHelper.php:361
6 Joomla\CMS\Component\ComponentHelper::renderComponent() JROOT\libraries\src\Application\AdministratorApplication.php:150
7 Joomla\CMS\Application\AdministratorApplication->dispatch() JROOT\libraries\src\Application\AdministratorApplication.php:206
8 Joomla\CMS\Application\AdministratorApplication->doExecute() JROOT\libraries\src\Application\CMSApplication.php:320
9 Joomla\CMS\Application\CMSApplication->execute() JROOT\administrator\includes\app.php:58
10 require_once() JROOT\administrator\index.php:32
This pull request has conflicts, please resolve those before we can evaluate the pull request.