Fix uploads and scripts under PHP-FPM: php_flag engine off in the .htaccess files of uploads, its backups, expenses, tmp and canned_responses folders, and scripts is wrapped in IfModule mod_php.c, as Apache only knows php_flag under mod_php and with PHP-FPM through mod_proxy_fcgi answered every request in those folders with a 500, so the logo, favicon, avatars and photos of contacts, locations, assets and racks didn't load on hosting panels; PHP still can't run there, as uploads denies php and the like by name and the other five deny everything; 26.11.9 changelog entries

This commit is contained in:
johnnyq
2026-11-13 20:25:50 -05:00
parent 3f8d948fe1
commit 38e5a8ddfc
7 changed files with 24 additions and 6 deletions

View File

@@ -30,6 +30,10 @@ Update from Maintenance > Update — Queue Update hands the job to cron, which u
- RMM Providers: if the RMM provider a line counted is deleted, the line stays at the quantity it last billed, marked RMM provider gone, until another is picked. Deleting a provider says how many lines bill its devices.
- RMM Providers: the RMM Sync job is on Maintenance > Cron, and so is RMM Alerts, every minute. Turning a provider off stops its syncs, and Delete forgets its links - the assets stay as they are either way. API keys are kept like other providers' keys and never shown again. A Tactical RMM key can do whatever its Tactical user can, so make it for a user whose role can see clients and agents and no more.
### Bug Fixes
- Hosting panels: on a server where Apache hands PHP to PHP-FPM - as HestiaCP, cPanel, Plesk and most hosting control panels set it up - your logo, the favicon, avatars and the photos on contacts, locations, assets and racks didn't load, and the server answered them with an error. They load now. The folders kept private, such as backups and receipts, stay private. Installs made with the install script, which runs PHP inside Apache, were not affected.
### Developer Updates
- Database 3.6.7: `rmm_providers` (`rmm_provider_kind` - `tactical` for now - the name it goes by, `api_url`, `web_url`, `api_key`, `api_secret` for an RMM that signs in with an id and a secret, and how the last sync went), `rmm_clients` (each provider's clients, `rmm_client_client_id` 0 until linked, `rmm_client_removed_at` once the RMM stops listing one) and `rmm_devices` (one a device: its asset, what the RMM last said - status, last seen, signed-in user, reboot, patches, checks - and `rmm_device_synced`, JSON of what the sync last wrote to the asset). Re-runnable, like 3.6.0.
@@ -45,6 +49,7 @@ Update from Maintenance > Update — Queue Update hands the job to cron, which u
- `agent/ajax.php`: the seventeen GET answers that printed JSON under PHP's default `text/html` now send `Content-Type: application/json` first - `get_credential_via_id`, `get_totp_token_via_id`, `get_readable_pass`, `get_active_clients`, `get_client_contacts`, `get_client_assets`, `get_client_locations`, `get_client_vendors`, `get_client_projects`, `get_internal_users`, `get_document_content`, `get_canned_response`, `ticket_query_views`, `client_duplicate_check`, `contact_email_check`, `network_ip_check` and `domain_check`. Their callers read the body as text (`itflowGet()`) or with `res.json()`, so nothing changes for them. A new JSON answer sets the header the same way: a value that is not escaped for HTML, as a login's username and password are not, must never go out as `text/html`.
- `getFieldByIdInScope($table, $id, $field, $client_field)` (`functions/app.php`) is `getFieldById()` for a record that belongs to a client. It gives null unless `hasClientAccess()` passes for the record's client, as it does for a record that isn't there; a record with no client (0) is anyone's. Use it wherever a label is made from an id in the query string. The two labels read with their own query, on `agent/trips.php` and `agent/modals/trip/trip_export.php`, take `clientScopeSql()` instead.
- `join.php` puts the login key in its sign-in link only while the invite is `pending` or `accepted` (`userInviteState()`).
- `php_flag engine off` in `uploads/.htaccess`, its `backups`, `expenses`, `tmp` and `canned_responses` folders and `scripts/.htaccess` is wrapped in `<IfModule mod_php.c>`. Apache only knows `php_flag` under mod_php - with PHP-FPM through `mod_proxy_fcgi` it stops on the line and answers every request in the folder with a 500. Under FPM, PHP still can't run there: `uploads/.htaccess` denies `.php`, `.phtml`, `.phar` and the rest by name, and the other five deny everything.
## [26.11.8]

View File

@@ -1,3 +1,5 @@
Require all denied
Options -ExecCGI -Indexes
php_flag engine off
<IfModule mod_php.c>
php_flag engine off
</IfModule>

View File

@@ -1,5 +1,8 @@
Options -ExecCGI -Indexes
php_flag engine off
# php_flag is mod_php's - under PHP-FPM Apache refuses it with a 500, and the rules below keep PHP out
<IfModule mod_php.c>
php_flag engine off
</IfModule>
RemoveHandler .php .phtml .phar .phps
RemoveType .php .phtml .phar .phps
<FilesMatch "\.(php|phtml|phar|phps|cgi|pl|sh)$">

View File

@@ -1,3 +1,5 @@
Require all denied
Options -ExecCGI -Indexes
php_flag engine off
<IfModule mod_php.c>
php_flag engine off
</IfModule>

View File

@@ -1,3 +1,5 @@
Require all denied
Options -ExecCGI -Indexes
php_flag engine off
<IfModule mod_php.c>
php_flag engine off
</IfModule>

View File

@@ -1,3 +1,5 @@
Require all denied
Options -ExecCGI -Indexes
php_flag engine off
<IfModule mod_php.c>
php_flag engine off
</IfModule>

View File

@@ -1,3 +1,5 @@
Require all denied
Options -ExecCGI -Indexes
php_flag engine off
<IfModule mod_php.c>
php_flag engine off
</IfModule>