Skip to content

Chore/update elfinder#14

Merged
abdul-kaioum merged 13 commits intomainfrom
chore/update-elfinder
Feb 20, 2026
Merged

Chore/update elfinder#14
abdul-kaioum merged 13 commits intomainfrom
chore/update-elfinder

Conversation

@abdul-kaioum
Copy link
Member

@abdul-kaioum abdul-kaioum commented Feb 20, 2026

Pull Request

Description

Plugin check gh action added

Type of Change

  • [x ] 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📚 Documentation update
  • [ x] ⚡ Improvement
  • [x ] 🔄 Code refactor

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Tests added/updated
  • Documentation updated if needed
  • README updated if needed

Changelog

Copilot AI review requested due to automatic review settings February 20, 2026 03:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the elFinder library to version 2.1.66 and adds a GitHub Actions workflow for plugin checking. The update includes security improvements, bug fixes, and enhancements to the file manager functionality, along with code quality improvements across the backend and frontend.

Changes:

  • Updated elFinder from version 2.1.65 to 2.1.66
  • Added GitHub Actions workflow for WordPress plugin checks
  • Improved code formatting and consistency across backend PHP files
  • Enhanced security with better file validation and syntax checking

Reviewed changes

Copilot reviewed 86 out of 105 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tools/build_elfinder.sh Updated build script to use pnpm and improved path handling
submodule/sources/elFinder Updated elFinder submodule to version 2.1.66
libs/elFinder/php/*.php Updated elFinder PHP classes with compatibility fixes and improvements
libs/elFinder/js/*.js Updated elFinder JavaScript files and CDN resources
libs/elFinder/css/elfinder.full.css Updated version information in CSS file
frontend/src/**/*.css Improved CSS formatting and consistency
frontend/src/components/utilities/Tabs/Tabs.tsx Improved code formatting
file-manager.php Added ABSPATH security check
composer.json Updated dependencies to newer versions
backend/hooks/*.php Reorganized imports for better code structure
backend/functions/*.php Added ABSPATH security checks
backend/app/**/*.php Multiple improvements: code formatting, import ordering, and logic refinements
.github/workflows/plugin-check.yml Added new GitHub Actions workflow for plugin checks
.distignore Added additional files to ignore in distribution
Comments suppressed due to low confidence (1)

libs/elFinder/php/elFinderVolumeSFTPphpseclib.class.php:1

  • Corrected spelling of 'substitue' to 'substitute'.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gemini-code-assist
Copy link

Summary of Changes

Hello @abdul-kaioum, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on a significant update to the elFinder file manager submodule and its associated Composer dependencies. It also includes extensive backend PHP code refactoring to enhance code quality, improve error handling, and ensure better consistency across the codebase. Frontend changes are minimal, primarily addressing styling and a minor component structure adjustment.

Highlights

  • elFinder Submodule Update: The elFinder submodule has been updated to its latest version (2.1.66), bringing various fixes and new features, including updated translations and CDN libraries.
  • Dependency Updates: Composer dependencies, including bitapps/wp-kit, bitapps/wp-database, friendsofphp/php-cs-fixer, and several symfony packages, have been upgraded to newer versions.
  • PHP Code Refactoring and Consistency: Numerous backend PHP files have undergone refactoring to improve code consistency, readability, and adherence to modern PHP standards, including explicit global namespace usage for functions like intval and sprintf.
  • Improved PHP Syntax Checking: The FileEditValidator now uses token_get_all for PHP syntax checking, replacing the less reliable exec function, which enhances security and compatibility.
  • Frontend Styling and Component Adjustments: Minor CSS formatting adjustments have been applied across several frontend style sheets, and a React Tabs component has received a structural change for clarity.
Changelog
  • .distignore
    • Added new entries for .htaccess, .gitignore, and .github directories within libs/elFinder to be ignored during distribution.
  • backend/app/Http/Controllers/FileManagerController.php
    • Removed unused Error import.
    • Adjusted line break for formatting consistency.
  • backend/app/Http/Controllers/LogController.php
    • Updated intval call to use the global namespace for explicit function reference.
  • backend/app/Http/Controllers/SettingsController.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Requests/Permissions/PermissionsUpdateRequest.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Requests/Permissions/SearchUserRequest.php
    • Removed an extra newline for formatting consistency.
  • backend/app/Http/Requests/Settings/LangUpdateRequest.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Requests/Settings/ThemeUpdateRequest.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Rules/ValidateCommandsRule.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Rules/ValidateLangRule.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Rules/ValidateRolesRule.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Rules/ValidateThemeRule.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Http/Rules/ValidateUsersRule.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Model/Log.php
    • Reordered class properties for better organization.
    • Adjusted method declaration for user() for consistency.
  • backend/app/Model/User.php
    • Removed unused Config import.
    • Added a log() relationship method.
  • backend/app/Providers/AccessControlProvider.php
    • Added Exception import.
    • Removed isFileAllowedToOpen method from its original position and moved it to a new location.
    • Adjusted conditional logic and string formatting in scanFile method using global namespace functions.
  • backend/app/Providers/FileEditValidator.php
    • Added ParseError import.
    • Refactored checkSyntax method to use token_get_all for PHP syntax validation, replacing the exec function.
  • backend/app/Providers/FileManager/FileManagerProvider.php
    • Removed unused elFinderConnector import.
  • backend/app/Providers/FileManager/FinderConnector.php
    • Updated PHPDoc for the output method.
    • Adjusted while loop syntax for consistency.
    • Added global namespace prefix to intval and function_exists calls for explicit function reference.
  • backend/app/Providers/InstallerProvider.php
    • Removed unused Connection import.
  • backend/app/Providers/Logger.php
    • Adjusted formatting and conditional logic in logUpload and processFileHashForUpload methods for consistency.
  • backend/app/Providers/MediaSynchronizer.php
    • Adjusted formatting in onFileUpload method.
  • backend/app/Providers/PreferenceProvider.php
    • Reordered use statements for alphabetical consistency.
    • Adjusted formatting and added global namespace prefix to is_string and bool cast for explicit function reference.
  • backend/app/Providers/VersionMigrationProvider.php
    • Reordered use statements for alphabetical consistency.
  • backend/app/Views/Shortcode.php
    • Reordered use statements for alphabetical consistency.
    • Added global namespace prefix to count call for explicit function reference.
  • backend/db/Migrations/BFMLogsTableMigration.php
    • Reordered use statements for alphabetical consistency.
  • backend/functions/common.php
    • Added ABSPATH check for WordPress environment compatibility.
  • backend/functions/global.php
    • Replaced \defined('ABSPATH') || exit(); with if ( ! defined( 'ABSPATH' ) ) exit; for WordPress environment compatibility.
  • backend/hooks/ajax.php
    • Moved use statements after ABSPATH check for proper loading order.
  • backend/hooks/api.php
    • Moved ABSPATH check before use statements for proper loading order.
  • composer.json
    • Updated bitapps/wp-kit dependency to ^2.2.
    • Updated bitapps/wp-database dependency to ^1.11.
  • composer.lock
    • Updated content hash.
    • Updated bitapps/wp-kit to version 2.2.
    • Updated bitapps/wp-validator to version 1.2.2.
    • Updated friendsofphp/php-cs-fixer to version v3.94.1.
    • Updated react/child-process to v0.6.7.
    • Updated react/dns to v1.14.0.
    • Updated react/event-loop to v1.6.0.
    • Updated react/socket to v1.17.0.
    • Updated sebastian/diff to 8.0.0.
    • Updated squizlabs/php_codesniffer to 3.13.5.
    • Updated various symfony packages to newer versions (e.g., symfony/console to v8.0.4, symfony/event-dispatcher to v8.0.4, symfony/filesystem to v8.0.1, symfony/finder to v8.0.5, symfony/options-resolver to v8.0.0, symfony/process to v8.0.5, symfony/service-contracts to v3.6.1, symfony/stopwatch to v8.0.0, symfony/string to v8.0.4).
    • Updated plugin-api-version to 2.9.0.
  • file-manager.php
    • Added ABSPATH check for WordPress environment compatibility.
  • frontend/src/components/utilities/Tabs/Tabs.tsx
    • Reformated cloneElement call for ActiveTabPanel for better readability.
  • frontend/src/components/utilities/TelemetryPopup/TelemetryPopup.module.css
    • Applied minor CSS formatting adjustments for consistency.
  • frontend/src/pages/Layout/ui/Navigation/TopNavigation/TopNavigation.module.css
    • Applied minor CSS formatting adjustment for consistency.
  • frontend/src/resource/styles/global.css
    • Removed trailing newline for file cleanliness.
  • frontend/src/resource/styles/plugin.css
    • Applied minor CSS formatting adjustments for consistency.
  • libs/elFinder/css/elfinder.full.css
    • Updated elFinder version to 2.1.66 and copyright year to 2026.
  • libs/elFinder/css/elfinder.min.css
    • Updated elFinder version to 2.1.66 and copyright year to 2026.
  • libs/elFinder/js/cdn/bzip2.js
    • Applied minor formatting adjustments.
  • libs/elFinder/js/cdn/gunzip.min.js
    • Applied minor formatting adjustments.
  • libs/elFinder/js/cdn/marked.min.js
    • Updated marked.js to a newer version.
  • libs/elFinder/js/cdn/run_prettify.js
    • Applied minor formatting adjustments.
  • libs/elFinder/js/cdn/sha.js
    • Updated sha.js to a newer version.
  • libs/elFinder/js/cdn/sha.min.js
    • Updated sha.min.js to a newer version.
  • libs/elFinder/js/cdn/unzip.min.js
    • Applied minor formatting adjustments.
  • libs/elFinder/js/i18n/elfinder.LANG.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT, EOT, WOFF, WOFF2).
  • libs/elFinder/js/i18n/elfinder.ar.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (خط, خط SFNT, خط Embedded Open Type, خط Web Open Font Format, خط Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.bg.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (шрифт, SFNT шрифт, Embedded Open Type шрифт, Web Open Font Format шрифт, Web Open Font Format 2 шрифт).
  • libs/elFinder/js/i18n/elfinder.ca.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Tipus de lletra, Tipus de lletra SFNT, Tipus de lletra Embedded Open Type, Tipus de lletra Web Open Font Format, Tipus de lletra Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.cs.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.da.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Skrift, SFNT skrift, Embedded Open Type skrift, Web Open Font Format skrift, Web Open Font Format 2 skrift).
  • libs/elFinder/js/i18n/elfinder.de.js
    • Added 'btnDiscard' translation ('Änderungen verwerfen').
    • Fixed typo in 'confirmNotSave' message.
    • Added new font kinds (Schriftart, SFNT-Schrift, Embedded-Open-Type-Schrift, Web-Open-Font-Format-Schrift, Web-Open-Font-Format-2-Schrift).
  • libs/elFinder/js/i18n/elfinder.el.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Γραμματοσειρά, Γραμματοσειρά SFNT, Γραμματοσειρά Embedded Open Type, Γραμματοσειρά Web Open Font Format, Γραμματοσειρά Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.en.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.es.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Fuente, Fuente SFNT, Fuente Embedded Open Type, Fuente Web Open Font Format, Fuente Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.fa.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (فونت, فونت SFNT, فونت Embedded Open Type, فونت Web Open Font Format, فونت Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.fo.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.fr.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Police, Police font, Police Embedded Open Type, Police Web Open Font Format, Police Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.fr_CA.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Police, Police SFNT, Police Embedded Open Type, Police Web Open Font Format, Police Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.he.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (גופן, גופן SFNT, גופן Embedded Open Type, גופן Web Open Font Format, גופן Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.hr.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.hu.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.id.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Huruf, Huruf SFNT, Huruf Embedded Open Type, Huruf Web Open Font Format, Huruf Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.it.js
    • Added 'btnDiscard' translation ('Scartare le modifiche').
    • Added new font kinds (File font, Font SFNT, Font Embedded Open Type, Font Web Open Font Format, Font Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.ja.js
    • Added 'btnDiscard' translation ('変更を破棄').
    • Added new font kinds (フォント, SFNT フォント, Embedded Open Type フォント, Web Open Font Format フォント, Web Open Font Format 2 フォント).
  • libs/elFinder/js/i18n/elfinder.ko.js
    • Updated version to 2024-03-19 and date formats.
    • Added 'errMaxMkdirs' translation.
    • Added 'btnDiscard' translation.
    • Added new font kinds (글꼴, SFNT 글꼴, Embedded Open Type 글꼴, Web Open Font Format 글꼴, Web Open Font Format 2 글꼴).
  • libs/elFinder/js/i18n/elfinder.nl.js
    • Added 'btnDiscard' translation ('Wijzigingen weggooien').
    • Added new font kinds (Lettertype bestand, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.no.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.pl.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Czcionka, Czcionka SFNT, Czcionka Embedded Open Type, Czcionka Web Open Font Format, Czcionka Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.pt_BR.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Fonte, SFNT fonte, Embedded Open Type fonte, Web Open Font Format fonte, Web Open Font Format 2 fonte).
  • libs/elFinder/js/i18n/elfinder.ro.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, Font SFNT, Font Embedded Open Type, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.ru.js
    • Updated version to 2024-11-05 and translator information.
    • Updated date formats.
    • Changed 'cmdpreference' to 'Настройки'.
    • Added 'btnDiscard' translation.
    • Updated several error messages and labels for clarity and consistency.
    • Added new font kinds (Шрифт, Шрифт SFNT, Шрифт Embedded Open Type, Шрифт Web Open Font Format, Шрифт Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.si.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.sk.js
    • Updated version to 2025-11-09 and date formats.
    • Added 'btnDiscard' translation ('Zahodiť zmeny').
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.sl.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.sr.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.sv.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT, Embedded Open Type, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.tr.js
    • Updated version to 2025-06-26 and translator information.
    • Updated date formats.
    • Added 'btnDiscard' translation.
    • Updated several error messages and labels for clarity and consistency.
    • Added new font kinds (Fontu, SFNT fontu, Embedded Open Type fontu, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.ug_CN.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (فونت, SFNT فونت, Embedded Open Type فونت, Web Open Font Format فونت, Web Open Font Format 2 فونت).
  • libs/elFinder/js/i18n/elfinder.uk.js
    • Added 'btnDiscard' translation ('Скасувати зміни').
    • Added new font kinds (Шрифт, Шрифт SFNT, Шрифт Embedded Open Type, Шрифт Web Open Font Format, Шрифт Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.vi.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (Font, SFNT font, Embedded Open Type font, Web Open Font Format, Web Open Font Format 2).
  • libs/elFinder/js/i18n/elfinder.zh_CN.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (字体, SFNT 字体, Embedded Open Type 字体, Web Open Font Format 字体, Web Open Font Format 2 字体).
  • libs/elFinder/js/i18n/elfinder.zh_TW.js
    • Added 'btnDiscard' translation.
    • Added new font kinds (字型, SFNT 字型, Embedded Open Type 字型, Web Open Font Format 字型, Web Open Font Format 2 字型).
  • libs/elFinder/php/elFinder.class.php
    • Removed unused elFinder class property.
    • Updated $ApiRevision to 66.
    • Adjusted PHPDoc comments for clarity.
    • Added E_STRICT to error reporting level.
    • Added elFinderAbortFiles to global variables for tracking abort-related temporary files.
    • Fixed conditional logic in trigger, exec, zipdl, file, fsock_get_contents, parse_data_scheme, getTempDir, upload, get, put, phpErrorHandler, itemLock, itemUnlock, getIniBytes, procExec, and onShutdown methods for improved robustness.
  • libs/elFinder/php/elFinderVolumeDriver.class.php
    • Adjusted getContentUrl path calculation for consistency.
    • Removed tmbPath fallback in getTempPath.
    • Refined encode and decode methods for better handling of empty paths.
    • Modified move method to attempt copy/delete if direct move fails.
  • libs/elFinder/php/elFinderVolumeDropbox2.class.php
    • Replaced filter_var($state, FILTER_SANITIZE_STRING) with htmlspecialchars($state) for improved security and consistency.
  • libs/elFinder/php/elFinderVolumeLocalFileSystem.class.php
    • Simplified conditional check in _relpath method.
  • libs/elFinder/php/elFinderVolumeOneDrive.class.php
    • Modified getContentUrl to directly use webUrl for download links.
  • libs/elFinder/php/elFinderVolumeSFTPphpseclib.class.php
    • Added NET_SFTP_LOCAL_FILE constant for compatibility.
    • Adjusted conditional logic in init and connect methods.
    • Added compatibility for phpseclib versions in parseRaw method.
    • Updated _mkfile and _copy methods to use self::NET_SFTP_LOCAL_FILE.
  • submodule/sources/elFinder
    • Updated submodule commit hash to 61000a8349d319027ab22d81498fcc69833869b3.
  • tools/build_elfinder.sh
    • Updated build script to use pnpm instead of npm.
    • Added rm -rf build command to clean previous build artifacts.
    • Modified the script to copy build/* contents to libs/elFinder/.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/plugin-check.yml
Activity
  • The pull request was opened by abdul-kaioum.
  • The author categorized the changes as bug fixes, improvements, and code refactoring.
  • The description mentions the addition of a 'Plugin check gh action', suggesting new CI/CD integration or checks.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

🔍 WordPress Plugin Check Report

❌ Status: Failed

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
35 3 32

❌ Errors (3)

📁 backend/app/Providers/FileEditValidator.php (1 error)
📍 Line 🔖 Check 💬 Message
44 WordPress.Security.EscapeOutput.ExceptionNotEscaped All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found 'wp_strip_all_tags'.
📁 backend/app/Providers/AccessControlProvider.php (1 error)
📍 Line 🔖 Check 💬 Message
221 WordPress.Security.EscapeOutput.ExceptionNotEscaped All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found 'wp_strip_all_tags'.
📁 backend/app/Providers/PhpSyntaxChecker.php (1 error)
📍 Line 🔖 Check 💬 Message
30 WordPress.WP.AlternativeFunctions.file_system_operations_is_writable File operations should use WP_Filesystem methods instead of direct PHP filesystem calls. Found: is_writable().

⚠️ Warnings (32)

📁 backend/app/Providers/AccessControlProvider.php (4 warnings)
📍 Line 🔖 Check 💬 Message
216 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
217 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
217 WordPress.Security.ValidatedSanitizedInput.MissingUnslash $_REQUEST['content'] not unslashed before sanitization. Use wp_unslash() or similar
217 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_REQUEST['content']
📁 backend/app/Providers/PhpSyntaxChecker.php (3 warnings)
📍 Line 🔖 Check 💬 Message
94 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_SERVER['PHP_AUTH_USER']
94 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_SERVER['PHP_AUTH_PW']
100 Squiz.PHP.DiscouragedFunctions.Discouraged The use of function set_time_limit() is discouraged
📁 composer.json (1 warning)
📍 Line 🔖 Check 💬 Message
0 missing_composer_json_file The "/vendor" directory using composer exists, but "composer.json" file is missing.
📁 backend/app/Http/Controllers/FileManagerController.php (2 warnings)
📍 Line 🔖 Check 💬 Message
28 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
28 WordPress.Security.ValidatedSanitizedInput.InputNotValidated Detected usage of a possibly undefined superglobal array index: $_REQUEST['cmd']. Check that the array index exists before using it.
📁 backend/app/Views/Admin.php (3 warnings)
📍 Line 🔖 Check 💬 Message
258 WordPress.Security.ValidatedSanitizedInput.InputNotValidated Detected usage of a possibly undefined superglobal array index: $_SERVER['HTTP_USER_AGENT']. Check that the array index exists before using it.
258 WordPress.Security.ValidatedSanitizedInput.MissingUnslash $_SERVER['HTTP_USER_AGENT'] not unslashed before sanitization. Use wp_unslash() or similar
258 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_SERVER['HTTP_USER_AGENT']
📁 backend/app/Providers/FileManager/FinderConnector.php (2 warnings)
📍 Line 🔖 Check 💬 Message
58 WordPress.Security.ValidatedSanitizedInput.MissingUnslash $_SERVER['HTTP_RANGE'] not unslashed before sanitization. Use wp_unslash() or similar
58 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_SERVER['HTTP_RANGE']
📁 backend/app/Providers/PermissionsProvider.php (4 warnings)
📍 Line 🔖 Check 💬 Message
500 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
501 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
511 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
512 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
📁 backend/app/Plugin.php (5 warnings)
📍 Line 🔖 Check 💬 Message
416 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
416 WordPress.Security.NonceVerification.Recommended Processing form data without nonce verification.
416 WordPress.Security.ValidatedSanitizedInput.MissingUnslash $_REQUEST['action'] not unslashed before sanitization. Use wp_unslash() or similar
417 Squiz.PHP.DiscouragedFunctions.Discouraged The use of function ini_set() is discouraged
418 Squiz.PHP.DiscouragedFunctions.Discouraged The use of function ini_set() is discouraged
📁 backend/functions/global.php (1 warning)
📍 Line 🔖 Check 💬 Message
63 WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log() found. Debug code should not normally be used in production.
📁 backend/functions/common.php (4 warnings)
📍 Line 🔖 Check 💬 Message
33 WordPress.PHP.DevelopmentFunctions.error_log_print_r print_r() found. Debug code should not normally be used in production.
68 WordPress.Security.ValidatedSanitizedInput.InputNotValidated Detected usage of a possibly undefined superglobal array index: $_SERVER['REQUEST_URI']. Check that the array index exists before using it.
68 WordPress.Security.ValidatedSanitizedInput.MissingUnslash $_SERVER['REQUEST_URI'] not unslashed before sanitization. Use wp_unslash() or similar
68 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized Detected usage of a non-sanitized input variable: $_SERVER['REQUEST_URI']
📁 backend/app/Http/Controllers/PermissionsController.php (1 warning)
📍 Line 🔖 Check 💬 Message
56 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude Using exclusionary parameters, like exclude, in calls to get_posts() should be done with caution, see https://wpvip.com/documentation/performance-improvements-by-removing-usage-of-post__not_in/ for more information.
📁 readme.txt (2 warnings)
📍 Line 🔖 Check 💬 Message
0 mismatched_plugin_name Plugin name "File Manager" is different from the name declared in plugin header "Bit File Manager".
0 readme_parser_warnings_no_short_description_present The "Short Description" section is missing. An excerpt was generated from your main plugin description.

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Abdul Kaioum <58425930+abdul-kaioum@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 20, 2026 03:15
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request primarily focuses on updating dependencies, including elfinder, and applying various code style fixes and refactorings. The changes introduce significant improvements, such as enhancing the PHP syntax check for better security and performance, and fixing potential security vulnerabilities related to path traversal and arbitrary file deletion. The file move operation has also been made more robust. While the overall changes are positive, I've identified a few areas for further improvement, including a potential bug in path calculation and opportunities for code simplification. My specific comments are detailed below.

}
if (empty($file['url']) && $this->URL) {
$path = str_replace($this->separator, '/', substr($this->decode($hash), strlen(rtrim($this->root, '/' . $this->separator)) + 1));
$path = str_replace($this->separator, '/', substr($this->decode($hash), strlen(trim($this->root, '/' . $this->separator))));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The change from rtrim to trim and the removal of + 1 might introduce a bug. trim will remove leading slashes from $this->root, which could lead to an incorrect path calculation in substr. For example, if $this->root is /var/www/files/, trim would make it var/www/files, and strlen would be incorrect, leading to a malformed relative path. The previous implementation with rtrim and + 1 seemed more robust for handling root paths with or without a trailing slash. I suggest reverting to a logic similar to the original to ensure correct path handling.

            $path = str_replace($this->separator, '/', substr($this->decode($hash), strlen(rtrim($this->root, '/' . $this->separator)) + 1));

Comment on lines +35 to +37
$validatedIds = array_map(function ($id) {
return \intval($id);
}, $request->ids);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While the current implementation is correct, it can be simplified. Instead of using an anonymous function with array_map, you can directly pass 'intval' as a callable string. This is more concise and generally more readable.

        $validatedIds = array_map('intval', $request->ids);

return '';
} else {
if ($path && strpos($path, $this->root) === 0) {
if (strpos($path, $this->root) === 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Removing the $path && check could potentially lead to warnings or errors if _relpath() is ever called with a null or empty string value for $path. While the current call sites might prevent this, it's safer to keep the guard as a defensive programming measure, especially for a protected method that could be used by subclasses in unexpected ways.

            if ($path && strpos($path, $this->root) === 0) {

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 86 out of 105 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

tools/build_elfinder.sh:1

  • Duplicate echo statement "Building elFinder from submodule." appears on both lines 3 and 6. Remove the duplicate on line 6 as it's redundant after the cd command.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 45 to 53
try {
token_get_all($content);
} catch (ParseError $e) {
$error = sprintf(
/* translators: 1: file name, 2: PHP parse error message */
__('Syntax error in file: %1$s. Error: %2$s', 'file-manager'),
$fileName,
$e->getMessage()
);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using token_get_all() for PHP syntax validation is less robust than exec('php -l') as it only performs tokenization, not full parsing. This could miss syntax errors that would be caught by the PHP interpreter. Consider documenting this limitation or providing an option to use the more thorough validation method when available.

Suggested change
try {
token_get_all($content);
} catch (ParseError $e) {
$error = sprintf(
/* translators: 1: file name, 2: PHP parse error message */
__('Syntax error in file: %1$s. Error: %2$s', 'file-manager'),
$fileName,
$e->getMessage()
);
if (\function_exists('exec')) {
$phpBinary = \defined('PHP_BINARY') ? PHP_BINARY : 'php';
$tmpFile = @\tempnam(\sys_get_temp_dir(), 'bfm_php_lint_');
if ($tmpFile !== false) {
@\file_put_contents($tmpFile, $content);
$cmd = \escapeshellarg($phpBinary) . ' -l ' . \escapeshellarg($tmpFile) . ' 2>&1';
$output = [];
$returnVar = 0;
@\exec($cmd, $output, $returnVar);
@\unlink($tmpFile);
if ($returnVar !== 0) {
$error = sprintf(
/* translators: 1: file name, 2: PHP parse error message */
__('Syntax error in file: %1$s. Error: %2$s', 'file-manager'),
$fileName,
\implode("\n", $output)
);
}
}
} else {
try {
token_get_all($content);
} catch (ParseError $e) {
$error = sprintf(
/* translators: 1: file name, 2: PHP parse error message */
__('Syntax error in file: %1$s. Error: %2$s', 'file-manager'),
$fileName,
$e->getMessage()
);
}

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +26
public function log()
{
return $this->hasMany(Log::class, 'user_id', 'ID');
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name 'log' is ambiguous and could conflict with logging functionality. Consider renaming to 'logs' (plural) to better indicate it returns a collection of log records.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 20, 2026 04:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 92 out of 111 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 3908 to 3933
protected function encode($path)
{
if (!is_null($path) && $path !== '') {
if ($path !== '') {

// cut ROOT from $path for security reason, even if hacker decodes the path he will not know the root
$p = $this->relpathCE($path);
// if reqesting root dir $path will be empty, then assign '/' as we cannot leave it blank for crypt
if ($p === '') {
$p = $this->separator;
}
// change separator
if ($this->separatorForHash) {
$p = str_replace($this->separator, $this->separatorForHash, $p);
}
// TODO crypt path and return hash
$hash = $this->crypt($p);
// hash is used as id in HTML that means it must contain vaild chars
// make base64 html safe and append prefix in begining
$hash = strtr(base64_encode($hash), '+/=', '-_.');
// remove dots '.' at the end, before it was '=' in base64
$hash = rtrim($hash, '.');
// append volume id to make hash unique
return $this->id . $hash;
}
//TODO: Add return statement here
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encode() no longer guards against null ($path !== '' is true for null) and also has no return statement when $path is empty, which can lead to null being returned where a string hash is expected. Restore the null/empty handling and ensure the function always returns a string.

Copilot uses AI. Check for mistakes.
Comment on lines 3944 to 3950
protected function decode($hash)
{
if ($hash && strpos($hash, $this->id) === 0) {
if (strpos($hash, $this->id) === 0) {
// cut volume id after it was prepended in encode
$h = substr($hash, strlen($this->id));
// replace HTML safe base64 to normal
$h = base64_decode(strtr($h, '-_.', '+/='));
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decode() now calls strpos($hash, $this->id) without checking that $hash is a non-empty string. If $hash can be null/false, PHP 8+ will throw a TypeError. Restore the previous guard (e.g. $hash && ...) or cast/validate $hash before using string functions.

Copilot uses AI. Check for mistakes.
Comment on lines +5400 to 5416
//Delete temp file paths
if (!empty($GLOBALS['elFinderTempFiles'])) {
foreach (array_keys($GLOBALS['elFinderTempFiles']) as $f) {
is_file($f) && is_writable($f) && unlink($f);
//Make sure paths are safe before deleting them
$tf = elFinder::$commonTempPath . DIRECTORY_SEPARATOR . basename($f);
is_file($tf) && is_writable($tf) && unlink($tf);
}
unset($f);
}

//Delete abort file paths
if (!empty($GLOBALS['elFinderAbortFiles'])) {
foreach (array_keys($GLOBALS['elFinderAbortFiles']) as $f) {
//Make sure paths are safe before deleting them
$tf = elFinder::$connectionFlagsPath . DIRECTORY_SEPARATOR . basename($f);
is_file($tf) && is_writable($tf) && unlink($tf);
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onShutdown() derives deletion targets with elFinder::$commonTempPath . DIRECTORY_SEPARATOR . basename($f) / connectionFlagsPath .... If either base path is empty, this can resolve to an absolute path like /somefile and risks deleting unintended files. Add a guard to only delete when the base directory is non-empty and the resolved realpath stays within that directory.

Copilot uses AI. Check for mistakes.
Comment on lines 4485 to 4515
@@ -4492,7 +4510,7 @@ protected function itemUnlock($hash)
return true;
}
$lock = elFinder::$commonTempPath . DIRECTORY_SEPARATOR . $hash . '.lock';
$cnt = (int)file_get_contents($lock);
$cnt = file_get_contents($lock);
if (--$cnt < 1) {
unlink($lock);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

itemLock()/itemUnlock() now use file_get_contents($lock) + 1 / --$cnt without casting/handling false. If the lock file is empty/unreadable, arithmetic on false/strings can yield incorrect counters and prevent proper unlocking. Cast to (int) (and handle false explicitly) before increment/decrement.

Copilot uses AI. Check for mistakes.
Comment on lines 2004 to 2014
if ($onetime) {
$volume = null;
$tmpdir = elFinder::$commonTempPath;
if (!$tmpdir || !is_file($tmpf = $tmpdir . DIRECTORY_SEPARATOR . 'ELF' . $target)) {
if (!$tmpdir || !is_file($tmpf = $tmpdir . DIRECTORY_SEPARATOR . 'ELF' . basename($target))) {
return $a404;
}
$GLOBALS['elFinderTempFiles'][$tmpf] = true;
if ($file = json_decode(file_get_contents($tmpf), true)) {
$src = base64_decode($file['file']);
$src = $tmpdir . DIRECTORY_SEPARATOR . basename(base64_decode($file['file']));
if (!is_file($src) || !($fp = fopen($src, 'rb'))) {
return $a404;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The one-time download flow now reconstructs $src as $tmpdir . DIRECTORY_SEPARATOR . basename(base64_decode($file['file'])), but the stored value appears to be an absolute path (set when creating the one-time link). This will likely 404 because the file won’t exist in $tmpdir. Either always copy the source into $tmpdir when generating the token (and store only the basename), or store a validated relative path and verify it stays inside $tmpdir when resolving.

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +171
server.httpServer.close(() => {
server.watcher.close()
removeStoredPort()
})
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configureServer is calling server.httpServer.close() during startup. That will immediately shut down the dev server (and will also close the watcher), which likely makes vite dev unusable. Instead of invoking close(), register a listener (e.g. server.httpServer.once('close', ...)) or use process.on('exit'/'SIGINT') to run cleanup when the server is actually stopping.

Copilot uses AI. Check for mistakes.
Comment on lines 3333 to 3335
if (empty($file['url']) && $this->URL) {
$path = str_replace($this->separator, '/', substr($this->decode($hash), strlen(rtrim($this->root, '/' . $this->separator)) + 1));
$path = str_replace($this->separator, '/', substr($this->decode($hash), strlen(trim($this->root, '/' . $this->separator))));
if ($this->encoding) {
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getContentUrl() now builds $path using trim($this->root, ...) and a different substr() offset. trim() removes characters from both ends (not just trailing separators), so the computed offset can be wrong and produce broken URLs. Consider reverting to the previous rtrim(...)+1 style (or otherwise compute the relative path safely) so URLs don’t include missing/extra path segments.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 20, 2026 05:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 93 out of 112 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

$volume = null;
$tmpdir = elFinder::$commonTempPath;
if (!$tmpdir || !is_file($tmpf = $tmpdir . DIRECTORY_SEPARATOR . 'ELF' . $target)) {
if (!$tmpdir || !is_file($tmpf = $tmpdir . DIRECTORY_SEPARATOR . 'ELF' . basename($target))) {
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file path construction uses string concatenation which could be vulnerable to path traversal attacks. While basename() is used later in the file cleanup, it would be safer to validate or sanitize $target earlier to ensure it doesn't contain directory traversal sequences before constructing the file path.

Copilot uses AI. Check for mistakes.
Comment on lines +5403 to +5405
//Make sure paths are safe before deleting them
$tf = elFinder::$commonTempPath . DIRECTORY_SEPARATOR . basename($f);
is_file($tf) && is_writable($tf) && unlink($tf);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The temporary file cleanup logic on lines 5403-5405 only deletes files in the common temp path by reconstructing the path with basename($f). However, files may have been stored with full paths in the elFinderTempFiles array. If a file was registered with a path outside the common temp directory, it won't be properly deleted. Consider checking whether the original path is within the expected temp directory before deletion.

Copilot uses AI. Check for mistakes.
Comment on lines 39 to 40
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PHP file syntax validation has been changed from using exec('php -l') to a loopback HTTP request approach. While this is more secure (avoiding shell execution), the new PhpSyntaxChecker class performs actual file writes and HTTP requests which could impact performance significantly, especially for large files or high-traffic scenarios. Consider adding configuration options to control this behavior or implement caching for recently validated files.

Suggested change
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);
// Allow disabling of the syntax check cache via constant if needed.
$cacheEnabled = !(\defined('BFM_DISABLE_SYNTAX_CACHE') && BFM_DISABLE_SYNTAX_CACHE);
$wpError = null;
if ($cacheEnabled) {
// Simple per-request cache keyed by file path and content hash.
static $cache = [];
$cacheKey = $realFile . ':' . md5($content);
if (array_key_exists($cacheKey, $cache)) {
$wpError = $cache[$cacheKey];
} else {
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);
$cache[$cacheKey] = $wpError;
}
} else {
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);
}

Copilot uses AI. Check for mistakes.
Comment on lines 25 to 46
public function check($content, $realFile)
{
$previousContent = file_get_contents($realFile);

if (!is_writable($realFile)) {
return new WP_Error('file_not_writable');
}

$f = fopen($realFile, 'w+');

if (false === $f) {
return new WP_Error('file_not_writable');
}

$written = fwrite($f, $content);
fclose($f);

if (false === $written) {
return new WP_Error('unable_to_write', __('Unable to write to file.'));
}

wp_opcache_invalidate($realFile, true);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PhpSyntaxChecker writes the content to the actual file on line 39 before validation, which means invalid PHP code will temporarily exist in the production file. If a fatal error occurs between writing the file and completing the loopback validation, the file could be left in a broken state. While there's a rollback mechanism, consider additional safeguards like atomic file operations or temporary staging.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 20, 2026 06:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 93 out of 112 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 25 to 64
public function check($content, $realFile)
{
$previousContent = file_get_contents($realFile);

if (!is_writable($realFile)) {
return new WP_Error('file_not_writable');
}

// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fwrite, WordPress.WP.AlternativeFunctions.file_system_operations_fclose
$f = fopen($realFile, 'w+');

if (false === $f) {
return new WP_Error('file_not_writable');
}

$written = fwrite($f, $content);
fclose($f);

if (false === $written) {
return new WP_Error('unable_to_write', __('Unable to write to file.', 'file-manager'));
}

wp_opcache_invalidate($realFile, true);

$result = $this->loopbackRequest();

if (true !== $result) {
file_put_contents($realFile, $previousContent);
wp_opcache_invalidate($realFile, true);

$message = isset($result['message'])
? $result['message']
: __('An error occurred. Please try again later.', 'file-manager');

$data = $result;
unset($data['message']);

return new WP_Error('php_error', $message, $data);
}
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PHP syntax checker writes user-provided content directly to the real file on the filesystem before validation. If the loopback request fails or times out, the rollback mechanism (line 52) attempts to restore the previous content. However, there's a potential window of vulnerability: if the process terminates unexpectedly between writing the new content (line 40) and the rollback (line 52), the malicious/invalid code could remain on the filesystem.

Additionally, using file_get_contents/file_put_contents with phpcs:disable comments suggests awareness of WordPress coding standards but bypasses them, which may pose security concerns in a file manager context where user-provided content is written to executable PHP files.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 20, 2026 07:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 94 out of 113 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const VAR_PREFIX = 'bit_fm_';

const VERSION = '6.8.6';
const VERSION = '6.8.9';
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Config::VERSION is set to '6.8.9' but the readme.txt shows version 6.8.7 and the file-manager.php header shows 6.8.7. All version numbers across the plugin should be consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +93
function fileSystemAdapter()
{
global $wp_filesystem;

if (empty($wp_filesystem)) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}

return $wp_filesystem;
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fileSystemAdapter function returns the global $wp_filesystem but does not handle the case where WP_Filesystem() fails to initialize. If WP_Filesystem() returns false or $wp_filesystem remains empty, this function will return an invalid value. Add error handling to check if initialization was successful.

Copilot uses AI. Check for mistakes.
$result = $this->loopbackRequest();

if (true !== $result) {
file_put_contents($realFile, $previousContent);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code uses file_put_contents() which is flagged by the phpcs:disable comment, but then calls fileSystemAdapter()->delete() for cleanup. For consistency and to respect WordPress filesystem abstraction, the initial write operation should also use the WP_Filesystem API (e.g., $wp_filesystem->put_contents()) instead of file_put_contents().

Suggested change
file_put_contents($realFile, $previousContent);
global $wp_filesystem;
if (!\function_exists('\WP_Filesystem')) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if (!$wp_filesystem instanceof \WP_Filesystem_Base) {
\WP_Filesystem();
}
if ($wp_filesystem instanceof \WP_Filesystem_Base) {
$wp_filesystem->put_contents($realFile, $previousContent, FS_CHMOD_FILE);
} else {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
\file_put_contents($realFile, $previousContent);
}

Copilot uses AI. Check for mistakes.
Comment on lines 39 to 42
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);

if ($wpError instanceof WP_Error) {
throw new PreCommandException($wpError->get_error_message());
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of the exec()-based syntax checking without providing an alternative check means PHP syntax errors may not be caught before writing files. The PhpSyntaxChecker::check() method writes content to the file first, then performs a loopback HTTP request. If that request fails or times out for reasons unrelated to syntax errors (network issues, server configuration), valid code could be rejected. Consider adding fallback validation or better error messaging to distinguish between syntax errors and connectivity issues.

Suggested change
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);
if ($wpError instanceof WP_Error) {
throw new PreCommandException($wpError->get_error_message());
$syntaxOk = null;
// Primary, local syntax check using "php -l" on a temporary file, if exec() is available.
if (\function_exists('exec')) {
$tmpFile = @tempnam(\sys_get_temp_dir(), 'bfm_php_syntax_');
if ($tmpFile !== false) {
// Write the in-memory content to the temporary file without touching the real file.
if (@file_put_contents($tmpFile, $content) !== false) {
$phpBinary = \defined('PHP_BINARY') && PHP_BINARY ? PHP_BINARY : 'php';
$command = escapeshellarg($phpBinary) . ' -l ' . escapeshellarg($tmpFile) . ' 2>&1';
$output = [];
$exitCode = 0;
@exec($command, $output, $exitCode);
// Ensure the temporary file is always removed.
@unlink($tmpFile);
if ($exitCode !== 0) {
// A non-zero exit code from "php -l" indicates a syntax error.
$message = trim(implode("\n", $output));
if ($message === '') {
$message = __('PHP syntax check failed with an unknown error.', 'file-manager');
}
throw new PreCommandException($message);
}
$syntaxOk = true;
} else {
// Clean up if the file could not be written.
@unlink($tmpFile);
}
}
}
$wpError = (new PhpSyntaxChecker())->check($content, $realFile);
if ($wpError instanceof WP_Error) {
$originalMessage = $wpError->get_error_message();
if ($syntaxOk === true) {
// Local "php -l" check passed, but the HTTP-based checker failed.
// Provide clearer context so users can distinguish syntax errors from connectivity issues.
$wrappedMessage = sprintf(
/* translators: 1: original error message from HTTP-based syntax checker */
__('PHP syntax appears valid, but an additional syntax check failed: %1$s This may be caused by a connectivity or server configuration issue rather than a syntax error in the file.', 'file-manager'),
$originalMessage
);
throw new PreCommandException($wrappedMessage);
}
throw new PreCommandException($originalMessage);

Copilot uses AI. Check for mistakes.
@@ -1,11 +1,11 @@
<?php

if ( ! defined( 'ABSPATH' ) ) exit;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ABSPATH check should come before any code execution, including comments. The opening PHP tag and any subsequent code should immediately be followed by the security check. Move the ABSPATH check to line 2, right after the opening PHP tag.

Copilot uses AI. Check for mistakes.
@abdul-kaioum abdul-kaioum merged commit 6a7cf67 into main Feb 20, 2026
1 check failed
@abdul-kaioum abdul-kaioum deleted the chore/update-elfinder branch February 20, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants