Conversation
…log filters Roles, permissions, permission groups and categories were deleted from GET parameters on actions that also render their edit pages, so none of them required a CSRF token. The middleware now verifies those actions when the triggering query parameter is present, and the delete links send the token. The manager log echoed the message filter raw into value="", and every filter reached the pagination links unescaped because Paginate urldecodes its extra arguments. Paginate now escapes them itself, and the stored item and user names in the filter dropdowns are escaped too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Octal-obfuscated function calls, a cookie-exfiltration script and an rm -rf string match antivirus signatures. The arithmetic payloads are now built at runtime from harmless function names, and the others use inert markers. Also repairs the stored error report payload, whose unescaped quotes had turned most of it into a PHP comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SystemInfo (a=53) resets OPcache whenever opcache_reset is in the request, and neither the action nor its reset link carried a token. The middleware now verifies a=53 when the parameter is present, and the link sends the token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anges Module dependencies (a=113) are added and removed from $_REQUEST['op'], so a plain GET changed them. The middleware now verifies a=113 when op is present. Logout (a=8) destroyed the manager session on GET without a token. It is now a guarded action, and the logout links in the frame, the welcome page, the lockout placeholder and the keepalive redirect carry the token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- category manager: cast ?id= before it is written into every form action - web user list: escape the reflected search box and the stored username, full name, email and role names - web user editor: escape the username shown in the header - menu index sort and the template/TV delete screens: escape page titles and sanitise summaries while keeping their inline formatting Escaping never double-encodes, so values stored entity-encoded by older installations still render as the same text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CSRF: roles, permissions, permission groups and categories could be deleted cross-site
UserRole(a=35/36/38),Permission(a=135),PermissionsGroups(a=136) and the category manager (a=120/121) delete straight from GET parameters, and none of these actions required a token.MUTATING_GET_ACTIONSwithout demanding a token for plain navigation. A newVerifyCsrfToken::MUTATING_GET_PARAMETERSlist verifies them only when the delete trigger (?action=,module_categories_manager[...]) is in the query string._token.CSRF: OPcache reset (a=53)
SystemInfocallsopcache_reset()wheneveropcache_resetis in the request. Now a=53 needs a token when that parameter is present, and the reset link sends it. Opening the System Info page still needs no token.CSRF: logout (a=8) and module dependencies (a=113)
$_REQUEST['op'], so a plain GET changed them. Now a=113 needs a token whenopis present.[+logouturl+]and the keepalive redirect.XSS: category manager, web users, page titles
?id=was reflected into every formaction. It is now cast to an integer.?search=box and the stored username, full name, email and role names are escaped. Web users can register themselves, so an anonymous visitor could reach an admin's screen through these fields.html_entity_decoded and then printed raw.sanitize_inline_html(), so their inline formatting still renders.XSS: manager log (a=13)
?message=was echoed raw intovalue="". The global sanitizer only rewrites<script, so" autofocus onfocus=...got through.Paginateurldecode()s its extra arguments, soPaginatenow escapes them itself.username,itemnameanditemidvalues in the filter dropdowns were printed raw (stored XSS through document and element names). They are now escaped.Tests: payloads that trigger antivirus scanners
system("id"),phpinfo, backtick andfile_put_contentspayloads inArithmeticExpressionTestare now built at runtime from harmless function names. They still contain no letters, so they still get past the callers' filter.alert(document.cookie)and therm -rf /string are replaced with inert markers.BladeStoredXssTest: unescaped quotes had turned most of the stored-report payload into a PHP comment, so that test never contained the payload it claimed to test.Test plan
_tokenon every delete linklogging.static.php, plus behaviouralPaginatetests (hostile input stays insidehref; filter values survive the round trip)ApacheConfigHardeningTest, comes from running outside a git checkout🤖 Generated with Claude Code