Conversation
…extension - Saving an existing page (isNew unset) skipped isValidPageName(), so pages could be created in hidden folders or in the statically served uploads folder. The name is now checked for every save. - Uploads only checked that the detected content type and the extension were each allowed, so e.g. a PDF could be stored as x.png and then be handed to ImageMagick as PDF. The content type must now match the extension, the format is passed to ImageMagick explicitly, and images above the new MAX_IMAGE_PIXELS setting are refused before being decoded. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYvivwGowMczvsbn1ciBmR
- index.php and api.php now send a Content-Security-Policy (own scripts and styles only, nonce for the upload page script, hashes for the wiki's two inline handlers, no framing/plugins/base, forms to self), nosniff, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP and, over HTTPS, Strict-Transport-Security. - Apache: only index.php and api.php are reachable among the PHP scripts; composer/phpunit files, markdown docs and the license are denied; the tests, locales and Michelf folders get their own .htaccess denying access. - nginx: equivalent rules in INSTALL.md and the tested template; static files get nosniff. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYvivwGowMczvsbn1ciBmR
The control file was placed in Michelf/, which now denies all access, so the scripts in it could no longer run and the test could not notice them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HYvivwGowMczvsbn1ciBmR
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
This change implements comprehensive security hardening by adding security headers to all responses and restricting direct access to non-public files through web server configuration and
.htaccessrules.Key Changes
Security Headers
securityHeaders()function inauth_functions.phpthat sends security headers with every response:Content-Security-Policy: Restricts scripts/styles to same-origin only, with nonce-based inline script support and hash-based inline event handler supportX-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: same-originPermissions-Policy: Disables camera, microphone, geolocation, payment, and USBCross-Origin-Opener-Policy: same-originStrict-Transport-Security(HTTPS only)cspNonce()function to generate a unique nonce for each request's inline scriptsHANDLER_TOGGLE_DRAWER,HANDLER_GO_BACK) to allow them via CSP hash validationindex.phpto use nonce for the upload form's inline script and constants for event handlersFile Access Restrictions
.htaccessrules to deny direct access to:index.phpandapi.phpare public)composer.json,phpunit.xml, documentation, license).htaccessfiles intests/,locales/, andMichelf/directories to deny direct accessINSTALL.mdwith equivalent location rulesX-Content-Type-Options: nosniffheader to static assets (JS, CSS, SVG, PNG)Upload Security
uploadTypesForExt()anduploadTypeMatchesExt()functions to validate that uploaded file content matches the declared extension (prevents storing PDFs as PNGs, etc.)imageMagickFormatPrefix()to explicitly specify format to ImageMagick instead of guessing from contentMAX_IMAGE_PIXELSconfiguration constant to refuse images exceeding pixel limitsBug Fixes
isNewflag is false (client-controlled)Testing
SecurityHeadersTestintegration test to verify all security headers are present on various endpointsImageTooLargeTestto verify pixel limit enforcementImageProcessingTest::testContentOfAnotherAcceptedTypeIsNotStoredUnderAnImageExtension()to verify type/extension validationPageNameTesttests for invalid names on non-new pages and editing existing pagesServerConfigTesttests to verify unneeded files are not served and entry points work correctlyIpAllowlistDeniedTest::testRefusedResponsesHaveSecurityHeaders()to verify headers on denied requestssecurityHeaders()andcontentSecurityPolicy()functionshttps://claude.ai/code/session_01HYvivwGowMczvsbn1ciBmR