Skip to content

[RFC / Feature Proposal] Relaxing Strict PHP Upper-Bound Enforcement into Configurable Soft Warnings for Emergency Security Mitigations (e.g., php2shell) #65866

Description

@hiro-gj

1. Executive Summary

Currently, Nextcloud Server enforces a strict, hardcoded upper-bound PHP version check in lib/versioncheck.php (for example, if (PHP_VERSION_ID >= 80200) in Nextcloud 25). When a newer PHP minor version is detected, Nextcloud immediately terminates execution with HTTP 500 Internal Server Error and exit(1) across all entry points (index.php, remote.php, public.php, cron.php, and console.php / occ).

While testing boundaries are important for quality assurance, this unconditional hard block creates a severe operational and security dilemma when critical, zero-day Remote Code Execution (RCE) vulnerabilities are discovered in the PHP runtime itself—such as the php2shell vulnerabilities (CVE-2026-109618, CVE-2026-109619).
In many enterprise Linux distributions and managed/shared hosting environments, security patches for such critical vulnerabilities are only released for actively supported PHP branches (e.g., PHP 8.2.35, PHP 8.3.36), while older EOL PHP branches (e.g., PHP 7.4, 8.0, 8.1) receive no patches. Administrators are forced to choose between:

  1. Upgrading PHP immediately to mitigate active RCE exploitation, which causes Nextcloud to completely brick itself via lib/versioncheck.php, or
  2. Keeping an unpatched, vulnerable PHP runtime online while attempting a multi-hop major Nextcloud upgrade (e.g., NC25 → NC26 → NC27 → NC28), which cannot be safely completed within an emergency incident response window.

In our production deployments of Nextcloud 25 (v25.0.13), we relaxed the upper-bound check in lib/versioncheck.php and verified operation under PHP 8.3.36. With E_DEPRECATED display suppression and minor defensive fixes, all core Nextcloud functionalities (Web UI, SAML SSO, WebDAV, file sharing, OCS APIs, and Outlook Sendent integration) ran stably without any fatal errors.

We therefore propose shifting Nextcloud's PHP upper-bound version management from an unconditional hard block (exit(1)) to a configurable soft-warning and emergency compatibility mechanism.


2. Root Cause Analysis & Architectural Inconsistencies in Current Codebase

  1. Discrepancy Between Comment Intent and Implementation in lib/versioncheck.php:

    • Line 36 of lib/versioncheck.php explicitly states:
      // Show warning if >= PHP 8.2 is used as Nextcloud is not compatible with >= PHP 8.2 for now
    • Despite stating "Show warning", the code performs a hard abort (http_response_code(500); exit(1);).
    • By contrast, for outdated/EOL PHP versions (PHP_VERSION_ID < 80000), OCA\Settings\Controller\CheckSetupController::isPhpOutdated() displays a non-blocking warning in the Administration Overview (Security & setup warnings) while allowing the server to operate. Blocking newer, security-patched PHP minor versions while only warning on outdated PHP versions is counterproductive for security.
  2. The occ Bootstrap Paradox (console.php):

    • Because console.php executes require_once __DIR__ . '/lib/versioncheck.php' on line 34 before booting the Symfony Console application, upgrading PHP immediately breaks php occ. Administrators cannot even run php occ maintenance:mode --on, php occ status, or php occ upgrade once the host PHP binary is updated.
  3. Missing $ignoreMax Propagation in OC\App\DependencyAnalyzer:

    • Nextcloud provides 'app_install_overwrite' in config/config.php and occ app:enable --force to bypass maximum version constraints (bool $ignoreMax).
    • However, in lib/private/App/DependencyAnalyzer.php (lines 57–74):
      public function analyze(array $app, bool $ignoreMax = false) {
          ...
          return array_merge(
              $this->analyzeArchitecture($dependencies),
              $this->analyzePhpVersion($dependencies), // <-- BUG: $ignoreMax is NOT passed here!
              ...
              $this->analyzeOC($dependencies, $app, $ignoreMax)
          );
      }
    • Because $ignoreMax is only passed to analyzeOC() and omitted from analyzePhpVersion(), apps declaring <php min-version="7.4" max-version="8.1"/> in appinfo/info.xml (e.g., suspicious_login, limit_login_to_ip) still fail dependency validation during app installation or updates even when listed in app_install_overwrite.

3. Concrete Proposals for Nextcloud Server

Proposal 1: Replace Hard Upper-Bound Exit with Configurable Soft Warning in lib/versioncheck.php

  • Keep the lower-bound hard check (PHP_VERSION_ID < MIN_SUPPORTED_ID): Running on a PHP version older than the minimum required syntax level will cause fatal parse errors, so exiting early remains appropriate.
  • Relax the upper-bound check (PHP_VERSION_ID >= TESTED_MAX_ID):
    • Allow administrators to permit execution on newer PHP minor versions via config/config.php ('allow_unsupported_php' => true, 'php_max_version_id' => 80400) or an environment variable (NEXTCLOUD_ALLOW_UNSUPPORTED_PHP=1), or default to a soft warning for minor version increments within the same major PHP release (e.g., PHP 8.x).
    • Format CLI error/warning messages cleanly to STDERR without HTML <br/> tags.

Proposal 2: Automatic E_DEPRECATED Suppression in Emergency Compatibility Mode

  • Newer PHP minor versions frequently introduce deprecation notices (e.g., dynamic property creation deprecation in PHP 8.2+).
  • When running on a PHP version >= TESTED_MAX_ID under compatibility mode, automatically enforce @ini_set('display_errors', '0') and mask E_DEPRECATED | E_USER_DEPRECATED | E_NOTICE early in lib/versioncheck.php so that deprecation notices do not corrupt HTTP headers, JSON responses, or WebDAV XML streams—even on shared hosts where php.ini cannot be easily customized.

Proposal 3: Surface Unsupported Upper-Bound PHP Versions in Admin Setup Checks

  • Extend OCA\Settings\Controller\CheckSetupController::isPhpSupported() (or add a dedicated SetupCheck class) to display a clear, non-blocking warning banner in the Admin Security & setup warnings panel when PHP_VERSION_ID >= TESTED_MAX_ID:

    "Warning: You are currently running Nextcloud on PHP 8.3.x, which is newer than the officially tested PHP version (8.1) for this release. While emergency operation is permitted for security mitigation, please plan an upgrade to a supported Nextcloud release."

  • This preserves a clear support boundary for the Nextcloud community while empowering sysadmins to patch critical PHP CVEs immediately.

Proposal 4: Propagate $ignoreMax to DependencyAnalyzer::analyzePhpVersion() and Introduce occ maintenance:php-compat

  • Update DependencyAnalyzer::analyzePhpVersion(array $dependencies, bool $ignoreMax = false) so that if (!$ignoreMax && isset($dependencies['php']['@attributes']['max-version'])) respects app_install_overwrite and occ app:enable --force.
  • Provide a built-in OCC command (occ maintenance:php-compat) to inspect PHP compatibility status, toggle emergency compatibility mode (--allow-unsupported / --strict), configure --max-version, and export compatibility patches (--export-patch).

4. Example: Running php-compat-patcher.php on Nextcloud 25 (Upload via SCP/SFTP/FTP, etc. & Open in Web Browser)

php-compat-patcher.php

Note: This patch has not yet been verified on a live production machine, so please use it with caution.

For shared or managed hosting environments without CLI access—or when PHP has already been upgraded to 8.3 and php occ is blocked by lib/versioncheck.php—administrators can apply the emergency relaxation patch simply by uploading php-compat-patcher.php (via SCP/SFTP/FTP, etc.) and opening it in a browser:

  1. Upload (via SCP/SFTP/FTP, etc.):
    • Upload php-compat-patcher.php (via SCP/SFTP/FTP, etc.) to the live Nextcloud 25 root directory (the same folder as index.php and status.php).
    • Note: Because Nextcloud's .htaccess blocks files starting with occ (RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]), use the filename php-compat-patcher.php (you can also restrict access by setting $allowedIps at the top of the script).
  2. Open in Web Browser to Auto-Apply:
    • Navigate to https://<your-domain>/<nextcloud-path>/php-compat-patcher.php in a web browser.
    • Simply loading the page automatically creates .bak backups (lib/versioncheck.php.bak, DependencyAnalyzer.php.bak, etc.), applies the PHP 8.2/8.3 relaxation patch, and displays a status report.
  3. Verify & Self-Delete:
    • Once Nextcloud is verified to work on PHP 8.3, click the "Self-Delete" button (?action=self_delete) on the page (or remove the file via SCP/SFTP/FTP, etc.). If needed, clicking "Rollback" (?action=rollback) immediately restores the original files from .bak.

5. Related / Similar Existing GitHub Issues

Activity

  1. joshtrichards commented on Oct 26, 2026

    @joshtrichards
    Member

    Hi @hiro-gj!

    Thanks for the detailed write-up. Speaking for myself as one member of the project, rather than on behalf of the project as a whole, I think it’s important to distinguish the broader proposal for a compatibility override from the support situation of the Nextcloud 25 deployment described here.

    While testing boundaries are important for quality assurance, this unconditional hard block creates a severe operational and security dilemma when critical, zero-day Remote Code Execution (RCE) vulnerabilities are discovered in the PHP runtime itself—such as the php2shell vulnerabilities (CVE-2026-109618, CVE-2026-109619).

    For the vulnerabilities cited, PHP released fixes across its supported branches, rather than requiring everyone to move to a newer PHP minor branch. The security update itself therefore does not necessarily require exceeding a Nextcloud release’s PHP upper bound. Whether there is a conflict depends on the specific Nextcloud release and the PHP packages available for the environment.

    The relevant question is whether a supported Nextcloud release has a compatible PHP branch for which security updates are available -- not whether it supports the newest PHP branch.

    In our production deployments of Nextcloud 25 (v25.0.13)

    An important consideration here is that Nextcloud 25 reached community end of life in October 2023, approximately three years ago. If you're an enterprise customer of Nextcloud GmbH, please contact them via https://portal.nextcloud.com/ to discuss options.

    In many enterprise Linux distributions and managed/shared hosting environments, security patches for such critical vulnerabilities are only released for actively supported PHP branches (e.g., PHP 8.2.35, PHP 8.3.36), while older EOL PHP branches (e.g., PHP 7.4, 8.0, 8.1) receive no patches.

    Enterprise distributions have their own package-support lifecycles and may backport security fixes without changing PHP minor branches. For those environments, the relevant sources are the distribution’s security advisories and package-support policies. Upstream PHP EOL does not necessarily mean that security updates are unavailable.

    Nextcloud has also historically retained compatibility with some upstream-EOL PHP branches. The distinction here is between upstream end of life and the security maintenance available through a distribution.

    Managed and shared hosting arrangements vary, so availability there would need to be checked with the hosting provider.

    Administrators are forced to choose between:

    1. Upgrading PHP immediately to mitigate active RCE exploitation, which causes Nextcloud to completely brick itself via lib/versioncheck.php, or
    2. Keeping an unpatched, vulnerable PHP runtime online while attempting a multi-hop major Nextcloud upgrade (e.g., NC25 → NC26 → NC27 → NC28), which cannot be safely completed within an emergency incident response window.

    Those are not necessarily the only options. In addition to distribution support, third-party providers offer security maintenance for PHP branches beyond upstream end of life. Examples include TuxCare, Freexian, and Zend. You would need to confirm coverage for your particular environment and the vulnerabilities in question.

    These options may not be available or practical for every deployment, but they are worth investigating. More generally, when continuing to run software beyond its upstream support period -- whether Nextcloud, PHP, or the underlying Linux distribution -- it's important to have a plan for ongoing security maintenance.

    The occ Bootstrap Paradox (console.php):

    Because console.php executes require_once DIR . '/lib/versioncheck.php' on line 34 before booting the Symfony Console application, upgrading PHP immediately breaks php occ. Administrators cannot even run php occ maintenance:mode --on, php occ status, or php occ upgrade once the host PHP binary is updated.

    I agree that losing access to occ complicates recovery when the host’s PHP version has already been changed. For help recovering a deployment in this situation, please see the community help forum: https://help.nextcloud.com/

    During an upgrade, the PHP runtime must be compatible with the Nextcloud code being executed at each step. That recovery difficulty is worth distinguishing from whether a supported Nextcloud release needs an override to obtain PHP security fixes.

    This preserves a clear support boundary for the Nextcloud community while empowering sysadmins to patch critical PHP CVEs immediately.

    Updating PHP addresses only one part of the security picture; the Nextcloud release also needs ongoing security maintenance. Relaxing the PHP check does not establish compatibility or address vulnerabilities in an unsupported Nextcloud release.

    I understand the operational difficulty of an emergency upgrade. For this deployment, I’d focus on obtaining patched PHP packages and establishing a supported Nextcloud upgrade path. The Nextcloud 25 example illustrates the difficulty of recovering an unsupported deployment; it doesn’t demonstrate a conflict between Nextcloud’s PHP compatibility requirements and obtaining PHP security updates for supported releases.

    The broader question of a compatibility override can be discussed separately, but an override isn’t a substitute for ongoing security maintenance of both Nextcloud and PHP. If extended support is needed for this deployment, I’d suggest exploring that through the providers and enterprise support contacts mentioned above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions