* Fix stored XSS vulnerability in Attribute Definitions
GHSA-rvfg-ww4r-rwqf: Stored XSS via Attribute Definition Name
Security Impact:
- Authenticated users with attribute management permission can inject XSS payloads
- Payloads execute when viewing/editing attributes in admin panel
- Can steal session cookies, perform CSRF attacks, or compromise admin operations
Root Cause:
1. Input: Attributes.php postSaveDefinition() accepts definition_name without sanitization
2. Output: Views echo definition_name without proper escaping
Fix Applied:
- Input sanitization: Added FILTER_SANITIZE_FULL_SPECIAL_CHARS to definition_name and definition_unit
- Output escaping: Added esc() wrapper when displaying definition_name in views
- Defense-in-depth: htmlspecialchars on attribute values saved to database
Files Changed:
- app/Controllers/Attributes.php - Sanitize inputs on save
- app/Views/attributes/form.php - Escape output on display
- app/Views/attributes/item.php - Escape output on display
* Remove input sanitization, keep output escaping only
Use escaping on output (esc() in views) as the sole XSS prevention
measure instead of sanitizing on input. This preserves the original
data in the database while still protecting against XSS attacks.
* Add validation for definition_fk foreign key in attribute definitions
Validate definition_group input before saving:
- Must be a positive integer (> 0)
- Must exist in attribute_definitions table
- Must be of type GROUP to ensure data integrity
Also add translation for definition_invalid_group error message
in all 45 language files (English placeholder for translations).
* Refactor definition_fk validation into single conditional statement
* Add esc() to attribute value outputs for XSS protection
- Add esc() to TEXT input value in item.php
- Add esc() to definition_unit in form.php
These fields display user-provided content and need output escaping
to prevent stored XSS attacks.
* Refactor definition_group validation into separate method
Extract validation logic for definition_fk into validateDefinitionGroup()
private method to improve code readability and reduce method complexity.
Returns:
- null if input is empty (no group selected)
- false if validation fails (invalid group)
- integer ID if valid
* Add translations for definition_invalid_group in all languages
- Added proper translations for 28 languages (de, es, fr, it, nl, pl, pt-BR, ru, tr, uk, th, zh-Hans, zh-Hant, ro, sv, vi, id, el, he, fa, hu, da, sw-KE, sw-TZ, ar-LB, ar-EG)
- Set empty string for 14 languages to fallback to English (cs, hr-HR, bg, bs, ckb, hy, km, lo, ml, nb, ta, tl, ur, az)
---------
Co-authored-by: Ollama <ollama@steganos.dev>
Modified definition_values() function in app/Views/attributes/item.php to properly handle checkbox attributes.
The issue was that checkbox attributes have two input elements (hidden and checkbox) with the same name pattern. When collecting attribute values during the refresh operation, both inputs were being processed, with the hidden input potentially overwriting the checkbox state.
Changes:
- Skip hidden inputs that have a corresponding checkbox input
- For checkbox inputs, explicitly capture the checked state using prop('checked')
- Convert checked state to '1' or '0' for consistency
This ensures that when adding another attribute to an item, existing checkbox states are preserved correctly.
* Improve code style and PSR-12 compliance
- refactored code formatting to adhere to PSR-12 guidelines
- standardized coding conventions across the codebase
- added missing framework files and reverted markup changes
- reformatted arrays for enhanced readability
- updated language files for consistent styling and clarity
- minor miscellaneous improvements
- Updated formatting to reflect standard
- Wrapped Decimal type in to_decimals() function for localization
Signed-off-by: objecttothis <objecttothis@gmail.com>
- Made view CI form helper function call format uniform.
- replaced calls to array() with []
- Placed { on its own line
- Removed empty lines where there shouldn't be any.
- Replaced text/javascript with application/javascript as the former is deprecated
- Replaced TRUE/FALSE constants with true/false keywords
- Replaced NULL constant with null keyword
- Replaced `<?php echo` in views with shortened `<?=`
- Added missing variable declaration
- Added missing function return type in declaration
- replaced `== true`, `== false`, `=== true` and `=== false` in if statements with simplified forms
- Added `@noinspection PhpUnused` tags to PHPdocs for functions which are called via AJAX.
- removed conversion to array in getResult in favor of returning an array to begin with.
- Refactored variable for clarity.
- declared variable in view coming from controller
- Added PHPdocs
- Refactored nested if/else statements into ternary notation.
- Corrected tab type
- added missing model declaration in view
- Modified query builder to extrapolate out the set() command for clarity