grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026[11.0.1]: https://github.com/owncloud/core/compare/v11.0.0...v11.0.1
## Summary
* Security - Reject SVG/script content before it reaches ImageMagick bitmap previews: [#41827](https://github.com/owncloud/core/pull/41827)
* Security - Pin the Imagick coder for each preview provider: [#41834](https://github.com/owncloud/core/pull/41834)
* Security - Prevent path traversal via appconfig public_/remote_ keys: [#41856](https://github.com/owncloud/core/pull/41856)
* Bugfix - Reduce priority of checkPropFind event: [#41676](https://github.com/owncloud/core/pull/41676)
* Bugfix - Do not echo secrets when setting config values via occ: [#41779](https://github.com/owncloud/core/issues/41779)
* Bugfix - Restore index usage for filecache writes on Oracle: [#41782](https://github.com/owncloud/core/issues/41782)
* Bugfix - Show federated users in the share dialog when local users also match: [#41807](https://github.com/owncloud/core/pull/41807)
* Bugfix - Avoid a deprecation notice when hashing the file cache path on Oracle: [#41808](https://github.com/owncloud/core/pull/41808)
* Bugfix - Ship only the app payload in the release tarballs: [#41824](https://github.com/owncloud/core/issues/41824)
* Bugfix - Release the file handle when a bitmap preview cannot be decoded: [#41835](https://github.com/owncloud/core/pull/41835)
* Bugfix - Show a media type icon when a preview file cannot be opened: [#41855](https://github.com/owncloud/core/pull/41855)
* Bugfix - Restrict federated address book sync to the trusted server: [#41869](https://github.com/owncloud/core/pull/41869)
* Change - Update PHP dependencies: [#41775](https://github.com/owncloud/core/pull/41775)
* Change - Require rhukster/dom-sanitizer as a tagged release: [#41785](https://github.com/owncloud/core/pull/41785)
* Change - Restore Oracle database support in the command line installer: [#41808](https://github.com/owncloud/core/pull/41808)
## Details
* Security - Reject SVG/script content before it reaches ImageMagick bitmap previews: [#41827](https://github.com/owncloud/core/pull/41827)
Bitmap previews (PDF, Font, ...) sanitized SVG content before decoding it, but
fell back to the original, unsanitized bytes whenever the sanitizer could not
parse the input - which happened for any malformed SVG or non-XML payload, not
only for genuinely broken SVG files. A crafted malformed SVG or a raw MVG script
could therefore reach ImageMagick unsanitized and trigger an MSL script that
reads or writes arbitrary files as the web server user.
Bitmap previews no longer attempt to sanitize and fall back; they now reject any
content that is detected as text, XML, SVG, or MVG before ImageMagick ever sees
it, and decode through the same hardened Imagick options already used by the
dedicated SVG preview provider.
Media type detection from file content now always reports a media type. It
previously passed an unusable value on to its caller when the magic database
behind it could not be loaded, which made a bitmap preview fail the request with
a server error rather than fall back to a media type icon, and left the new
check above with nothing to test the content against.
Previews that read a file also no longer pass it to ImageMagick before the
hardened Imagick options are applied.
https://github.com/owncloud/core/pull/41827
* Security - Pin the Imagick coder for each preview provider: [#41834](https://github.com/owncloud/core/pull/41834)
Bitmap and SVG previews decoded content with no format hint, so ImageMagick's
own content-sniffing - independent of the mime-type check that decides whether a
preview is attempted at all - could pick a different coder than the one a
provider actually serves. PostScript-looking content, which the mime check must
allow through for the PDF and Postscript providers, could therefore still reach
the Ghostscript delegate through any other bitmap provider (SGI, Font,
Illustrator, Photoshop, TIFF, Heic).
Each provider now pins the exact Imagick coder it expects instead of letting
ImageMagick guess from the file's content. The pin is applied in memory and
introduces no temporary file of its own.
Because media types are derived from the file name extension, a file whose
extension does not match its actual content no longer gets a preview: a JPEG
saved as photo.tif is routed to the TIFF provider, pinned to the TIFF coder, and
falls back to a media type icon where content sniffing previously rendered it.
This is the intended trade-off - content sniffing is what allowed a preview
provider to be steered to an unrelated coder in the first place.
The affected extensions are ai, bw, eps, heic, heif, int, inta, pdf, ps, psd,
rgb, rgba, sgi, tif and tiff. Of those providers only SGI and Heic are
registered by default, so on a stock install this is visible for bw, int, inta,
rgb, rgba, sgi, heic and heif; the rest need their provider enabled in
enabledPreviewProviders.
The font extensions otf, pfb and ttf change differently: the font coder accepts
any bytes, so a mismatched file still produces a thumbnail, just one drawn by
the font coder rather than reflecting the file's real content. Real .otf files
gain previews they did not have before, because an unpinned read had no decode
delegate for them at all.
Office documents and SVG are pinned too but are not affected. For Office the pin
covers the PDF LibreOffice has just produced rather than anything the user
uploaded, and for SVG content that is not parseable XML never reached a coder
before this change either.
One route is deliberately left open, and is worth stating so the expectation is
set: which provider handles a preview can be steered by the request, so asking
for a file to be previewed as a PDF hands that file's bytes to the PDF coder
whatever they are. This is not a change - content sniffing reached the same
coder before - and the PDF, PostScript and EPS coders are the ones a
distribution's ImageMagick policy denies by default. Deployments that enable
those coders should keep that policy as the control, because it applies
process-wide rather than per provider.
https://github.com/owncloud/core/pull/41834
* Security - Prevent path traversal via appconfig public_/remote_ keys: [#41856](https://github.com/owncloud/core/pull/41856)
We've fixed a path traversal in the appconfig `public_`/`remote_` service
handlers. An authenticated admin could set such a key on the `core` app to a
traversal value which was later included by `public.php`, leading to remote code
execution. An included handler must now resolve to a PHP file inside the app's
own directory, and the app-id guard can no longer be bypassed by mangled
spellings such as a trailing space.
Note for integrators: the appconfig endpoints now refuse to *read* a `core`
`public_`/`remote_` key as well as to write one. `getValue`/`hasKey` on the
legacy `core/ajax/appconfig` endpoint had no such guard at all and returned the
stored handler path; `GET /settings/appconfig/core/...` refused the exact
lowercase prefix already, and now refuses a mangled spelling of it too
(`PUBLIC_webdav`, app id `CORE` or `core `), as well as any key on `core`
outside `[a-zA-Z0-9_.-]{1,64}`. Scripts which need a handler path should read it
with `occ config:app:get`.
Requesting a service which is not registered now answers 404 on both
`public.php` and `remote.php`. `public.php` previously reported a logged 500,
and `remote.php` sent a malformed status line; its refusals now answer 503,
which is the status a WebDAV client already saw for them.
https://github.com/owncloud/core/pull/41856
* Bugfix - Reduce priority of checkPropFind event: [#41676](https://github.com/owncloud/core/pull/41676)
The checkPropFind event that triggers during an HTTP PROPFIND request must
happen before the Sabre DAV httpPropFind event. That has been happening because
it sorts alphabetically first. This change reduces the priority number of
checkPropFind, increasing its priority, so that it always executes first,
regardless of any other sort order.
https://github.com/owncloud/core/pull/41676
* Bugfix - Do not echo secrets when setting config values via occ: [#41779](https://github.com/owncloud/core/issues/41779)
Config:system:set and config:app:set printed the value that had just been
written back to stdout, so every secret configured through occ ended up in the
terminal scrollback, the container log or the CI log of whoever ran the command.
WOPI signing keys and the JWT secrets of apps leaked out of Docker deployments
that configure them from a startup hook this way.
Both commands now print a placeholder instead of the value when the config key
holds a secret. Recognition reuses the existing list of sensitive keys in
OC\SystemConfig, which gained an accessor telling whether a key path is
sensitive, and falls back to matching the key name against the patterns
credential, key, passwd, password, pwd, salt, secret and token. That fallback
covers the keys of apps, which core does not know, such as wopi.token.key or
jwt_secret. Boolean values keep being shown, as they cannot hold a secret. Only
the confirmation output changed, the stored value is written as before.
https://github.com/owncloud/core/issues/41779
https://github.com/owncloud/core/pull/41780
* Bugfix - Restore index usage for filecache writes on Oracle: [#41782](https://github.com/owncloud/core/issues/41782)
On Oracle every compare column of an upsert was wrapped in to_char(). That cast
is only needed for text and binary columns, which Oracle cannot compare
directly, but it was applied to all of them - and to_char(column) cannot use an
index on that column. Writes to the file cache compare storage and path_hash, so
uploads, renames and file scans could no longer use the unique index
fs_storage_path_hash and became very slow on large installations.
Only text and binary compare columns are cast now, so every other comparison
uses its index again.
https://github.com/owncloud/core/issues/41782
https://github.com/owncloud/core/pull/41818
* Bugfix - Show federated users in the share dialog when local users also match: [#41807](https://github.com/owncloud/core/pull/41807)
The share dialog only offered federated users when the search returned no local
users and no local groups, so a single local match hid every federated result -
including exact federated cloud id matches. Searching for a surname stem shared
by local accounts therefore made federated users unreachable unless the full
cloud id was typed.
The suggestion that made this filtering necessary is generated by the server: a
search term containing an "@" was always offered as a federated cloud id, even
when it was the email address of an existing local account. That guess is now
skipped whenever the search matched a local user or group exactly, so the share
dialog no longer needs to discard genuine federated results.
https://github.com/owncloud/enterprise/issues/4392
https://github.com/owncloud/core/pull/41807
* Bugfix - Avoid a deprecation notice when hashing the file cache path on Oracle: [#41808](https://github.com/owncloud/core/pull/41808)
Oracle cannot store empty strings, so the file cache converts them to null
before writing a row. For the storage root, whose path is the empty string, that
left md5() being called with null. PHP 8 reports that as a deprecated implicit
null to string conversion: noise in the log whenever a storage root is inserted,
and an error under PHPUnit's strict error handling. The stored path_hash itself
was never wrong, because md5(null) coerces to md5('').
The value is now cast to a string before hashing.
https://github.com/owncloud/core/pull/41808
* Bugfix - Ship only the app payload in the release tarballs: [#41824](https://github.com/owncloud/core/issues/41824)
The release bundles contained 13 bundled apps as the working tree they had been
built in, rather than as the app's release artifact. Each of those app
directories carried `.git/` (a shallow clone including its pack file),
`.github/`, `tests/`, `vendor-bin/` and `build/artifacts/`, the last holding a
second copy of the app's own tarball. That was 101.94 MB of the 441.8 MB
uncompressed complete tarball, in 16 shipped git repositories.
Three things made it more than dead weight. `files_antivirus` shipped its
anti-virus acceptance data, so a ClamAV scan of the tarball, or of any image
built from it, reported `Eicar-Test-Signature FOUND` and could be rejected by an
anti-virus gate. The development files were covered by the app's
`appinfo/signature.json`, so an administrator could not delete them without
breaking `occ integrity:check-app`. And the shipped `.git/` carried the release
engineer's clone metadata, including their name and e-mail address.
The affected app releases have been repackaged, and the release tooling now
refuses to build a bundle that contains a build working tree, so this cannot
recur unnoticed. The standard tarball was affected as well, through
`notifications`.
https://github.com/owncloud/core/issues/41824
* Bugfix - Release the file handle when a bitmap preview cannot be decoded: [#41835](https://github.com/owncloud/core/pull/41835)
Bitmap previews closed the file they had opened only when decoding succeeded, so
every file that could not be decoded leaked a file handle for the lifetime of
the process. Generating previews for a directory of files that ImageMagick has
no decoder for could therefore exhaust the available file handles.
Bitmap previews for a file that cannot be opened at all now report no preview
instead of failing the whole request.
https://github.com/owncloud/core/pull/41835
* Bugfix - Show a media type icon when a preview file cannot be opened: [#41855](https://github.com/owncloud/core/pull/41855)
Generating an SVG preview read the file without checking that it had been
opened. A file the storage could not open, or one whose name the filesystem
rejects, made the request fail with a server error instead of falling back to a
media type icon. The bitmap providers shared that gap for one of the two values
an unsuccessful open can return.
Generating an SVG preview for a file that opened but then failed to be read - an
encrypted file with a missing or damaged key, for instance - already fell back
to the icon, but held the file handle and its lock until the request ended. The
bitmap providers were not affected by this one.
Both providers now check the handle before reading, so such a file gets the
media type icon, and the SVG provider releases the handle whether or not the
read succeeds.
https://github.com/owncloud/core/pull/41855
* Bugfix - Restrict federated address book sync to the trusted server: [#41869](https://github.com/owncloud/core/pull/41869)
The federated system address book sync could request resources that do not
belong to the trusted server it was syncing with, and could follow redirects
away from that server.
Requests which would leave the trusted server are now refused, and resource
references which do not belong to it are skipped and logged.
https://github.com/owncloud/core/pull/41869
* Change - Update PHP dependencies: [#41775](https://github.com/owncloud/core/pull/41775)
The following have been updated:
* composer/semver (3.4.4 to 3.5.0)
* doctrine/lexer (3.0.1 to 3.0.2)
* firebase/php-jwt (v7.1.0 to v7.2.0)
* google/apiclient (v2.19.4 to v2.20.0)
* google/apiclient-services (v0.452.0 to v0.460.0)
* google/auth (v1.53.0 to v1.55.0)
* guzzlehttp/guzzle (7.15.2 to 7.15.5)
* guzzlehttp/promises (2.5.1 to 2.5.3)
* guzzlehttp/psr7 (2.13.0 to 2.13.1)
* laravel/serializable-closure (2.0.15 to 2.1.0)
* monolog/monolog (3.10.0 to 3.12.0)
* nikic/php-parser (v5.8.0 to v5.9.0)
* pear/archive_tar (1.6.0 to 1.6.1)
* phpseclib/phpseclib (3.0.55 to 3.0.57)
* punic/punic (3.8.1 to 3.8.2)
* rhukster/dom-sanitizer (1.0.14 to 1.0.17)
* sabre/event (5.1.8 to 5.1.9)
* symfony/console (v7.4.14 to v7.4.19)
* symfony/event-dispatcher (v7.4.14 to v7.4.17)
* symfony/mailer (v7.4.14 to v7.4.19)
* symfony/mime (v7.4.13 to v7.4.19)
* symfony/process (v7.4.13 to v7.4.19)
* symfony/routing (v7.4.13 to v7.4.18)
* symfony/service-contracts (v3.7.1 to v3.7.3)
* symfony/string (v7.4.13 to v7.4.19)
* symfony/translation (v7.4.14 to v7.4.17)
https://github.com/owncloud/core/pull/41775
https://github.com/owncloud/core/pull/41791
https://github.com/owncloud/core/pull/41797
https://github.com/owncloud/core/pull/41809
https://github.com/owncloud/core/pull/41829
https://github.com/owncloud/core/pull/41839
https://github.com/owncloud/core/pull/41842
https://github.com/owncloud/core/pull/41864
* Change - Require rhukster/dom-sanitizer as a tagged release: [#41785](https://github.com/owncloud/core/pull/41785)
Rhukster/dom-sanitizer was required as "dev-main", a branch pin. A branch pin
resolves to whatever commit the branch happened to point at when the lock file
was written, and it carries no version number. Vulnerability scanners match
installed versions against advisory version ranges, so an unversioned dependency
can never match any range: scanners silently reported nothing at all for this
package, whatever commit was actually shipped.
It is now required as "^1.0.10" and resolves to 1.0.14. The shipped code is
equivalent -- the previously locked commit 02d08ec8 corresponds to tag 1.0.11 --
so this is a packaging and auditability change, not a functional one.
https://github.com/owncloud/core/pull/41785
* Change - Restore Oracle database support in the command line installer: [#41808](https://github.com/owncloud/core/pull/41808)
The Oracle database layer -- ConnectionFactory, OracleConnection,
OracleMigrator, AdapterOCI8 and the OCI expression builder -- has always
remained in the code base, but the setup class that makes it reachable had been
removed, so an instance could no longer be installed against Oracle at all. That
also meant no CI job could exercise that layer.
The maintenance:install command accepts --database=oci again, together with the
--database-connection-string option needed to reach a schema inside an Oracle
pluggable database. The web installer is unchanged: Oracle is not offered there,
because the default supportedDatabases config still lists only sqlite, mysql and
pgsql.
This restores test coverage for Oracle-specific code paths. It is not a
statement about production support for Oracle.
https://github.com/owncloud/core/pull/41808
# Changelog for ownCloud Core [11.0.0] (2026-07-30)
The following sections list the changes in ownCloud core 11.0.0 relevant to
ownCloud admins and users.
[11.0.0]: https://github.com/owncloud/core/compare/v10.16.4...v11.0.0
## Summary
* Security - Prevent params body from overriding validated occ command: [#41577](https://github.com/owncloud/core/pull/41577)
* Security - Remove plaintext federation auth token from error log: [#41578](https://github.com/owncloud/core/pull/41578)
* Security - Replace strcmp token oracle with hash-based comparison in federation: [#41579](https://github.com/owncloud/core/pull/41579)
* Security - Restrict unserialize() allowed classes in CommandJob: [#41582](https://github.com/owncloud/core/pull/41582)
* Security - Sanitize storage connection error messages returned to clients: [#41585](https://github.com/owncloud/core/pull/41585)
* Security - Prevent user enumeration via differential password reset UI: [#41586](https://github.com/owncloud/core/pull/41586)
* Security - Disable group-admin feature by default behind allow_subadmins: [#41634](https://github.com/owncloud/core/pull/41634)
* Security - Do not trust cached binary paths: [#41732](https://github.com/owncloud/core/pull/41732)
* Security - Enforce the read permission in the public share preview endpoint: [#41751](https://github.com/owncloud/core/pull/41751)
* Security - Confine backend provided user homes to the data directory: [#41752](https://github.com/owncloud/core/pull/41752)
* Security - Encode search highlights before they are returned as a DAV property: [#41760](https://github.com/owncloud/core/pull/41760)
* Bugfix - Point documentation help links at the latest server docs: [#5132](https://github.com/owncloud/docs/issues/5132)
* Bugfix - Normalise trashbin original-location PROPFIND response: [#39337](https://github.com/owncloud/core/issues/39337)
* Bugfix - Add missing space to mail footer signature delimiter: [#41364](https://github.com/owncloud/core/issues/41364)
* Bugfix - Fix htaccess RewriteBase rules blocking API requests by file extension: [#41418](https://github.com/owncloud/core/issues/41418)
* Bugfix - Adjust code to avoid PHP8 messages: [#41597](https://github.com/owncloud/core/pull/41597)
* Bugfix - Support federation between systems in subdirectories: [#41599](https://github.com/owncloud/core/pull/41599)
* Bugfix - Remove owncloud.com/federation link from federated cloud settings: [#41608](https://github.com/owncloud/core/pull/41608)
* Bugfix - Fix JS test isolation bugs exposed by Jasmine 5 random test ordering: [#41616](https://github.com/owncloud/core/pull/41616)
* Bugfix - Honor language on anonymous pages: [#41618](https://github.com/owncloud/core/issues/41618)
* Bugfix - Decrypt versions and trashbin so encryption can be disabled: [#41623](https://github.com/owncloud/core/issues/41623)
* Bugfix - Fix user:home:list-dirs and user:home:list-users crashing on PHP 8: [#41630](https://github.com/owncloud/core/issues/41630)
* Bugfix - Add MIME types for OpenDocument formats: [#41648](https://github.com/owncloud/core/pull/41648)
* Bugfix - Handle deprecated code related to comments app: [#41656](https://github.com/owncloud/core/pull/41656)
* Bugfix - Hide navigation icon for apps not enabled for the user: [#41717](https://github.com/owncloud/core/issues/41717)
* Bugfix - Do not crash on malformed translations: [#41720](https://github.com/owncloud/core/issues/41720)
* Bugfix - Reject non-numeric avatar crop coordinates: [#41723](https://github.com/owncloud/core/issues/41723)
* Bugfix - Fix avatar cropper broken by Jcrop 2.0 file rename: [#41723](https://github.com/owncloud/core/issues/41723)
* Bugfix - Rewire legacy ajax routes to extension-free urls: [#41740](https://github.com/owncloud/core/issues/41740)
* Bugfix - Request legacy ajax endpoints through the front controller: [#41740](https://github.com/owncloud/core/issues/41740)
* Change - Update M$ Office icons: [#41347](https://github.com/owncloud/core/pull/41347)
* Change - No longer store auto loader information in any memory cache: [#41376](https://github.com/owncloud/core/pull/41376)
* Change - Raise minimum PHP version to 8.3: [#41449](https://github.com/owncloud/core/pull/41449)
* Change - Update PHP dependencies: [#41450](https://github.com/owncloud/core/pull/41450)
* Change - Drop command db:convert-type: [#41451](https://github.com/owncloud/core/pull/41451)
* Change - Removed legacy and deprecated code from ownCloud 11: [#41455](https://github.com/owncloud/core/pull/41455)
* Change - Use configurable URL for internet connectivity check: [#41506](https://github.com/owncloud/core/pull/41506)
* Change - Use phan major version 6 code analysis: [#41650](https://github.com/owncloud/core/pull/41650)
* Change - Remove msteamsbridge config sample: [#41668](https://github.com/owncloud/core/pull/41668)
* Change - G2 code-signing verifier and G1 signature sunset: [#41680](https://github.com/owncloud/core/pull/41680)
* Change - Remove occ integrity:sign-app and integrity:sign-core commands: [#41712](https://github.com/owncloud/core/pull/41712)
* Change - Remove the caching router: [#41733](https://github.com/owncloud/core/pull/41733)
* Change - Keep host local caches in the local cache tier: [#41734](https://github.com/owncloud/core/pull/41734)
* Change - Cover HTML metacharacters in the username validation allow-list: [#41738](https://github.com/owncloud/core/pull/41738)
* Change - Expose createLocal() on ICacheFactory: [#41753](https://github.com/owncloud/core/pull/41753)
* Change - Escape group names in the users administration group list: [#41758](https://github.com/owncloud/core/pull/41758)
* Change - Honour the write hook veto on legacy chunked WebDAV uploads: [#41762](https://github.com/owncloud/core/pull/41762)
## Details
* Security - Prevent params body from overriding validated occ command: [#41577](https://github.com/owncloud/core/pull/41577)
OccController validated the URL-path command against an allowlist but then
merged it with user-supplied params via array_merge, allowing a command key in
the request body to overwrite the validated value. An authenticated caller with
the updater secret could use this to execute any occ command regardless of the
allowlist. The params array is now stripped of any command key before the merge.
https://github.com/owncloud/core/pull/41577
* Security - Remove plaintext federation auth token from error log: [#41578](https://github.com/owncloud/core/pull/41578)
When getSharedSecret received an invalid token it logged both the submitted
value and the expected valid token in plaintext. Since the endpoint is public,
any unauthenticated caller could trigger this log entry at will for any trusted
server URL, exposing the valid token to anyone with log-read access.
A second leak in the same code path has also been closed: the GetSharedSecret
background job sends the token as a GET query parameter, so on an unexpected
HTTP response the Guzzle exception - whose message embeds the full request URI
including "?token=..." - was logged verbatim. Both log sites no longer emit the
token value.
https://github.com/owncloud/core/pull/41578
* Security - Replace strcmp token oracle with hash-based comparison in federation: [#41579](https://github.com/owncloud/core/pull/41579)
The requestSharedSecret endpoint used strcmp() to compare caller-supplied and
stored federation tokens, returning different HTTP responses based on
lexicographic ordering. This allowed an unauthenticated attacker to recover the
stored token via binary search in approximately 96 requests. Tokens are now
compared by their SHA-256 hashes, removing the plaintext oracle while preserving
the tiebreaking behaviour.
https://github.com/owncloud/core/pull/41579
* Security - Restrict unserialize() allowed classes in CommandJob: [#41582](https://github.com/owncloud/core/pull/41582)
CommandJob::run() called unserialize() without the allowed_classes option on
data sourced from the oc_jobs database table. An attacker with database write
access could inject a crafted PHP object payload to trigger gadget chains from
bundled libraries and achieve remote code execution. Deserialization is now
restricted to verified ICommand implementations only.
https://github.com/owncloud/core/pull/41582
* Security - Sanitize storage connection error messages returned to clients: [#41585](https://github.com/owncloud/core/pull/41585)
The external storage status handler returned raw exception messages including
Guzzle cURL error details such as resolved IP addresses and port numbers in the
JSON response. This allowed authenticated users to distinguish connection states
and map internal network topology. The full exception is now logged server-side
only; a generic message is returned to the client.
https://github.com/owncloud/core/pull/41585
* Security - Prevent user enumeration via differential password reset UI: [#41586](https://github.com/owncloud/core/pull/41586)
The login form showed a "Reset it?" link only when a valid user on a backend
that supports password changes was detected. LDAP users produced a different
response than non-existent users, allowing unauthenticated enumeration of
accounts on those backends. The backend capability check has been removed; the
reset link is now shown uniformly regardless of user existence or backend type.
https://github.com/owncloud/core/pull/41586
* Security - Disable group-admin feature by default behind allow_subadmins: [#41634](https://github.com/owncloud/core/pull/41634)
Disable the subadmin (group-admin) feature by default behind a new
allow_subadmins system config, as a security risk-mitigation. The feature's code
path has known security shortcomings; deployments that rely on it can opt back
in with 'allow_subadmins' => true in config.php. On upgrade, existing
group-admin assignments are ignored until an admin sets 'allow_subadmins' =>
true in config.php.
https://github.com/owncloud/core/pull/41634
* Security - Do not trust cached binary paths: [#41732](https://github.com/owncloud/core/pull/41732)
The paths of the helper binaries used to render previews - ffmpeg, avconv and
AtomicParsley - were cached in the distributed memory cache and used without
being checked, then interpolated unquoted into the shell commands built from
them. A cached path is now stored in the host local cache tier only, is
validated before it is used, and is quoted when the command line is assembled.
https://github.com/owncloud/core/pull/41732
* Security - Enforce the read permission in the public share preview endpoint: [#41751](https://github.com/owncloud/core/pull/41751)
The public share preview endpoint resolved the share by token and rendered the
requested file without consulting the share's permission bitmask. It now returns
404 when the share does not carry the read permission, which makes it consistent
with ShareController::downloadShare() and the public WebDAV route.
https://github.com/owncloud/core/pull/41751
* Security - Confine backend provided user homes to the data directory: [#41752](https://github.com/owncloud/core/pull/41752)
A user backend can supply a per user home directory - the LDAP backend for
instance can be configured to read it from a user attribute such as
homeDirectory. The account sync accepted that value after nothing more than a
check for a leading slash, so a home pointing at the ownCloud code directory
turned the user's file listing into read and write access to the application's
own PHP files. Writing a PHP file into a web reachable location, or modifying
one of the shipped ones, results in remote code execution. The relative form was
concatenated onto the data directory without normalization, so a value
containing ".." escaped it as well.
A backend provided home is now rejected unless it resolves inside the configured
datadirectory. Installations that legitimately keep user homes elsewhere, for
example on a separate NFS mount, can list the permitted base directories in the
new "user.home_base_dirs" config option. Symlinks are resolved before the
comparison, so a symlinked data directory keeps working while a symlink inside
it cannot be used to escape. Every entry in the option has to be an absolute
path; entries that are not are ignored, because a relative one would be resolved
against the working directory of whichever process happens to run the check.
Note that a home is only set when an account has none yet, so accounts that were
provisioned before this change keep the home already stored for them.
https://github.com/owncloud/core/pull/41752
https://github.com/owncloud/user_ldap/pull/849
* Security - Encode search highlights before they are returned as a DAV property: [#41760](https://github.com/owncloud/core/pull/41760)
The search-highlights property of the files search REPORT returned the
elasticsearch highlight fragment unencoded. The fragment is built from file
content, so a user who shared a crafted file could place arbitrary markup in the
property value. The property deliberately carries HTML - line breaks are
substituted with
- so a client rendering it as HTML would execute the
injected markup.
The fragment is now HTML-encoded before the line break substitution, which keeps
the intended
markup intact.
https://github.com/owncloud/core/pull/41760
* Bugfix - Point documentation help links at the latest server docs: [#5132](https://github.com/owncloud/docs/issues/5132)
Contextual documentation links (setup checks, help & tips, app info.xml keys)
were built as /server//go.php?to= using the running server's
concrete version, e.g. /server/10.16/. The documentation site publishes the
current stable release only under /server/latest/, so those links resolved to a
non-existent version path and 404'd. The version segment now defaults to
'latest'; callers may still pass an explicit published version.
https://github.com/owncloud/docs/issues/5132
https://github.com/owncloud/core/pull/41688
* Bugfix - Normalise trashbin original-location PROPFIND response: [#39337](https://github.com/owncloud/core/issues/39337)
In certain situations the trashbin original-location in a PROPFIND response
contained a leading slash. This change ensures that a relative path (without a
leading slash) is always returned.
https://github.com/owncloud/core/issues/39337
https://github.com/owncloud/core/pull/41649
* Bugfix - Add missing space to mail footer signature delimiter: [#41364](https://github.com/owncloud/core/issues/41364)
We've fixed the signature delimiter in the email footer templates. The delimiter
on the first line was missing the trailing space required by the signature block
convention (RFC 3676), so mail clients were unable to recognize and collapse the
signature. The delimiter is now correctly written as "-- " (dash-dash-space).
https://github.com/owncloud/core/issues/41364
https://github.com/owncloud/core/pull/41617
* Bugfix - Fix htaccess RewriteBase rules blocking API requests by file extension: [#41418](https://github.com/owncloud/core/issues/41418)
Files whose names end in extensions like .jpg, .png, .svg, .json and others
could not be marked as favorites or have their tags updated via the files API
when htaccess.RewriteBase was configured. The .htaccess rules generated by `occ
maintenance:update:htaccess` used a URI extension check to skip routing through
index.php, which inadvertently blocked API requests to paths like
`/apps/files/api/v1/files/photo.jpg`, returning 405 Method Not Allowed.
The fix replaces the extension-based condition with `RewriteCond
%{REQUEST_FILENAME} !-f`, which correctly routes virtual API paths through
index.php while still serving actual static files directly.
https://github.com/owncloud/core/issues/41418
* Bugfix - Adjust code to avoid PHP8 messages: [#41597](https://github.com/owncloud/core/pull/41597)
Avoid trying to access array offset on false in the encryption storage wrapper.
Handle passing null to normalizeUrl in the federation DbHandler.
https://github.com/owncloud/core/pull/41597
* Bugfix - Support federation between systems in subdirectories: [#41599](https://github.com/owncloud/core/pull/41599)
If a federated server was installed in a subdirectory like:
Mydomain.com/cloud
Then checks to see that the server is up and responding would fail. This problem
has been corrected.
https://github.com/owncloud/core/pull/41599
* Bugfix - Remove owncloud.com/federation link from federated cloud settings: [#41608](https://github.com/owncloud/core/pull/41608)
The "Add to your website" feature in the personal federation settings was
generating a link to https://owncloud.com/federation# which no longer works
after owncloud.com was restructured. The federation Cloud ID is now displayed
directly without linking to the defunct external page.
https://github.com/owncloud/core/pull/41608
* Bugfix - Fix JS test isolation bugs exposed by Jasmine 5 random test ordering: [#41616](https://github.com/owncloud/core/pull/41616)
Several JS test specs left shared singleton state dirty between tests, causing
intermittent failures when Jasmine 5 ran tests in random order. Fixed
OC._currentMenu leak in fileactionsmenuSpec, stale OCA.Files.fileActions
reference causing infinite recursion in files_sharing/appSpec, and stale models
in the OC.SystemTags.collection singleton in systemtagsinfoviewSpec and
systemtagsinputfieldSpec.
https://github.com/owncloud/core/pull/41616
* Bugfix - Honor language on anonymous pages: [#41618](https://github.com/owncloud/core/issues/41618)
Anonymous pages (the login page and the password-protected public share page)
always rendered in English even when default_language was configured or the
browser sent a matching Accept-Language header, while authenticated pages were
translated correctly. The language factory cached the "en" last-resort fallback
as the per-request language, which then short-circuited every later lookup
before default_language or Accept-Language could be consulted. The fallback is
no longer cached, so anonymous pages honor default_language and Accept-Language.
https://github.com/owncloud/core/issues/41618
* Bugfix - Decrypt versions and trashbin so encryption can be disabled: [#41623](https://github.com/owncloud/core/issues/41623)
"occ encryption:decrypt-all" only walked the regular "files" folder, leaving the
"encrypted" flag set on entries in "files_versions" and "files_trashbin".
Because "occ encryption:disable" refuses while any file cache row is still
flagged as encrypted, administrators were left unable to disable encryption even
though decrypt-all reported success.
Decrypt-all now also descends into "files_versions" and "files_trashbin", and
the disable command now lists the paths that are still flagged as encrypted
together with a hint on how to clean them up, instead of printing a generic
message.
https://github.com/owncloud/core/issues/41623
https://github.com/owncloud/core/pull/41624
* Bugfix - Fix user:home:list-dirs and user:home:list-users crashing on PHP 8: [#41630](https://github.com/owncloud/core/issues/41630)
The occ commands user:home:list-dirs and user:home:list-users --all passed null
as the search pattern to IUserManager::search() to mean "all users". On PHP 8
the null reached Connection::escapeLikeParameter(string $param) and raised a
TypeError, aborting the command. Both commands now pass the empty string, which
is the established "match all" sentinel used by every other caller.
https://github.com/owncloud/core/issues/41630
* Bugfix - Add MIME types for OpenDocument formats: [#41648](https://github.com/owncloud/core/pull/41648)
Add MIME type mappings for additional OpenDocument formats for file types odc,
odi, odm, otc, otg, oth, oti, otp, ots and ott.
Add MIME type aliases for chart and image formats that were currently missing in
the default mimetypealiases.dist.json file.
Update mimetypelist.js using ./occ maintenance:mimetype:update-js
https://github.com/owncloud/core/pull/41648
* Bugfix - Handle deprecated code related to comments app: [#41656](https://github.com/owncloud/core/pull/41656)
Code paths that caused deprecation warnings in PHP 8 have been corrected.
https://github.com/owncloud/core/pull/41656
* Bugfix - Hide navigation icon for apps not enabled for the user: [#41717](https://github.com/owncloud/core/issues/41717)
Apps that were enabled only for a specific group still showed their navigation
icon in the top-left app menu for every user, including users who were not in
that group. Clicking the icon then bounced the user back to the Files app. The
navigation manager now skips apps that are not enabled for the current user,
mirroring the per-user check already used for the web navigation entry.
https://github.com/owncloud/core/issues/41717
* Bugfix - Do not crash on malformed translations: [#41720](https://github.com/owncloud/core/issues/41720)
Changing the language (and any request that rendered a translated string with
parameters) could return an HTTP 500 error. On PHP 8 vsprintf() throws a
ValueError instead of returning false when a translation's format specifiers do
not match the supplied arguments — a common result of translators turning "%s"
into "% s" or "%S", or dropping a specifier. OC_L10N_String::__toString() did
not guard against this, so a single malformed translation string in a shipped
language file crashed the whole request. Such translations now fall back to the
untranslated source text so the request still succeeds.
https://github.com/owncloud/core/issues/41720
* Bugfix - Reject non-numeric avatar crop coordinates: [#41723](https://github.com/owncloud/core/issues/41723)
Submitting a profile picture crop with empty or non-numeric coordinates hit the
image cropping code with invalid values. On PHP 8 this raised a TypeError from
round() and returned an HTTP 500; on PHP 7 it silently produced a broken crop.
The client sends empty coordinates (crop[x]=&crop[y]=...) whenever the cropper
failed to produce a selection. postCroppedAvatar now validates that all four
coordinates are numeric and returns a clean HTTP 400 otherwise, instead of
crashing.
https://github.com/owncloud/core/issues/41723
https://github.com/owncloud/core/pull/41725
* Bugfix - Fix avatar cropper broken by Jcrop 2.0 file rename: [#41723](https://github.com/owncloud/core/issues/41723)
Uploading a non-square profile picture opened a cropper that immediately failed
with "$cropperImage.Jcrop is not a function". Bumping the Jcrop dependency from
0.9.12 to 2.0.4 renamed its distribution files from js/jquery.Jcrop.js and
css/jquery.Jcrop.css to js/Jcrop.js and css/Jcrop.css, but the personal profile
template still referenced the old paths. The script therefore failed to load,
the plugin never registered on jQuery, and the cropper could not be shown. The
template now loads the renamed Jcrop assets.
Original Jcrop PR: https://github.com/owncloud/core/pull/38666
https://github.com/owncloud/core/issues/41723
https://github.com/owncloud/core/pull/41724
* Bugfix - Rewire legacy ajax routes to extension-free urls: [#41740](https://github.com/owncloud/core/issues/41740)
The front controller rewrite only forwards a request to index.php when the
requested path does not exist on disk. A legacy route whose declared url was
itself a real file - for example /settings/ajax/setlanguage.php - therefore
never reached the router: the web server executed the script directly, without
the bootstrap index.php would have performed, and the request died with `Class
"OC" not found` (HTTP 500). Changing the personal language setting, the share
dialog e-mail lookup, the trashbin and public link preview thumbnails and the
Google Drive OAuth entry point were affected.
Every such route url has lost its .php suffix so that no route url resolves to a
file on disk any more, and the affected javascript callers now build routed urls
through OC.generateUrl(). Route names are unchanged, so linkToRoute() callers
keep working. The legacy .php urls are gone and no alias is provided - an alias
would re-introduce the very shadowing this change removes. /core/ajax/update.php
keeps its suffix by design: it bootstraps itself and is excluded from the
rewrite. Five routes whose include target no longer existed were removed.
Third-party apps posting to their own shadowed .php route urls need the same
treatment.
https://github.com/owncloud/core/issues/41740
https://github.com/owncloud/core/pull/41742
* Bugfix - Request legacy ajax endpoints through the front controller: [#41740](https://github.com/owncloud/core/issues/41740)
The front controller rewrite only forwards a request to index.php when the
requested path does not exist on disk. Five javascript call sites requested a
url that was itself a real file, so the web server executed the script directly,
without the bootstrap index.php would have performed, and the request died with
a fatal error (HTTP 500): changing the personal language, the share dialog
e-mail lookup, the Google Drive OAuth entry point, and the trashbin and public
link preview thumbnails.
All five now build their url with an explicit /index.php/ prefix so that the
request no longer matches a file on disk and reaches the router. The prefix has
to be part of the url literal because OC.generateUrl() omits /index.php when
mod_rewrite is active, which is how four of the five came to request the
shadowed url in the first place.
https://github.com/owncloud/core/issues/41740
https://github.com/owncloud/core/pull/41743
* Change - Update M$ Office icons: [#41347](https://github.com/owncloud/core/pull/41347)
Icons have been updated according to the M$ cloud storage partner program
https://github.com/owncloud/core/pull/41347
* Change - No longer store auto loader information in any memory cache: [#41376](https://github.com/owncloud/core/pull/41376)
With composer managing auto loading for a long time this is no longer necessary.
https://github.com/owncloud/core/pull/41376
* Change - Raise minimum PHP version to 8.3: [#41449](https://github.com/owncloud/core/pull/41449)
The minimum required PHP version is now 8.3. Numerous PHP 8.x deprecation
warnings were resolved across the codebase, the mail subsystem was migrated to
symfony/mailer, the unused ext-apc requirement was dropped, and the PHP version
check now runs early in lib/base.php.
https://github.com/owncloud/core/pull/41449
* Change - Update PHP dependencies: [#41450](https://github.com/owncloud/core/pull/41450)
The following have been updated:
* doctrine/dbal (2.13.9 to 3.10.6)
* firebase/php-jwt (7.0.5 to 7.1.0)
* google/apiclient (v2.19.0 to v2.19.4)
* google/apiclient-services (v0.435.0 to v0.452.0)
* google/auth (v1.50.0 to v1.53.0)
* guzzlehttp/guzzle (7.10.0 to 7.15.2)
* guzzlehttp/promises (2.3.0 to 2.5.1)
* guzzlehttp/psr7 (2.8.0 to 2.13.0)
* laravel/serializable-closure (v2.0.10 to v2.0.15)
* league/mime-type-detection (1.16.0 to 1.17.0)
* phpseclib/phpseclib (3.0.49 to 3.0.55)
* pimple/pimple (3.6.1 to 3.6.2)
* sabre/dav (4.7.0 to 4.7.1)
* sabre/event (5.1.7 to 5.1.8)
* sabre/vobject (4.5.8 to 4.6.1)
* symfony/console (v7.4.7 to v7.4.14)
* symfony/event-dispatcher (v7.4.9 to v7.4.14)
* symfony/mailer (v7.4.6 to v7.4.14)
* symfony/process (v7.4.5 to v7.4.13)
* symfony/routing (v7.4.6 to v7.4.13)
* symfony/string (v7.4.6 to v7.4.13)
* symfony/translation (v7.4.6 to v7.4.14)
* symfony/deprecation-contracts (v3.6.0 to v3.7.1)
* symfony/event-dispatcher-contracts (v3.7.0 to v3.7.1)
* symfony/service-contracts (v3.7.0 to v3.7.1)
* symfony/translation-contracts (v3.6.1 to v3.7.1)
https://github.com/owncloud/core/pull/41450
https://github.com/owncloud/core/pull/41477
https://github.com/owncloud/core/pull/41495
https://github.com/owncloud/core/pull/41561
https://github.com/owncloud/core/pull/41564
https://github.com/owncloud/core/pull/41569
https://github.com/owncloud/core/pull/41590
https://github.com/owncloud/core/pull/41613
https://github.com/owncloud/core/pull/41619
https://github.com/owncloud/core/pull/41626
https://github.com/owncloud/core/pull/41635
https://github.com/owncloud/core/pull/41639
https://github.com/owncloud/core/pull/41652
https://github.com/owncloud/core/pull/41660
https://github.com/owncloud/core/pull/41666
https://github.com/owncloud/core/pull/41670
https://github.com/owncloud/core/pull/41677
https://github.com/owncloud/core/pull/41681
https://github.com/owncloud/core/pull/41691
https://github.com/owncloud/core/pull/41697
https://github.com/owncloud/core/pull/41709
https://github.com/owncloud/core/pull/41756
* Change - Drop command db:convert-type: [#41451](https://github.com/owncloud/core/pull/41451)
This experimental command is untested and unsupported and therefore removed.
https://github.com/owncloud/core/pull/41451
* Change - Removed legacy and deprecated code from ownCloud 11: [#41455](https://github.com/owncloud/core/pull/41455)
The following have been removed:
* class OC_DB
* class OC_DB_StatementWrapper
* class OC_Group_Backend
* class OC_Group_Database
* class OC_OCS_Result
* class \OCP\DB
* class MDBSchemaWriter
* interface OC_Group_Interface
* interface OC_User_Interface
* method MDB2SchemaManager::getDbStructure()
* method MDB2SchemaManager::generateChangeScript()
https://github.com/owncloud/core/pull/41455
https://github.com/owncloud/core/pull/41458
https://github.com/owncloud/core/pull/41462
https://github.com/owncloud/core/pull/41464
https://github.com/owncloud/core/pull/41468
* Change - Use configurable URL for internet connectivity check: [#41506](https://github.com/owncloud/core/pull/41506)
Default URL is now configurable and the default is set to an independent
resource: https://detectportal.firefox.com/success.txt This also provides an
IPv6 compatible URL.
https://github.com/owncloud/core/issues/41465
https://github.com/owncloud/core/pull/41506
* Change - Use phan major version 6 code analysis: [#41650](https://github.com/owncloud/core/pull/41650)
Now that PHP 7 support has been dropped, we can use the latest release of the
phan code analyser.
Patch releases before 6.0.7 had a problem with the function signatures for some
Redis methods. That was corrected in https://github.com/phan/phan/pull/5546 and
released in phan version 6.0.7. So that version is required as the minimum here.
https://github.com/owncloud/core/pull/41650
* Change - Remove msteamsbridge config sample: [#41668](https://github.com/owncloud/core/pull/41668)
The owncloud/msteamsbridge integration app is being archived and is no longer
maintained. Its Microsoft Teams Bridge config sample block has been removed from
config.apps.sample.php so the config-to-docs sync no longer re-adds the
parameters to the admin documentation.
https://github.com/owncloud/core/pull/41668
* Change - G2 code-signing verifier and G1 signature sunset: [#41680](https://github.com/owncloud/core/pull/41680)
We've replaced the app-signature verification with a new G2 code-signing
verifier that validates the full certificate chain against bundled trust
anchors, enforces an algorithm allowlist, and checks a fail-closed CRL for
revocation.
Existing G1-signed apps continue to verify during the transition. However, all
G1 signatures stop verifying on 2027-01-01 (the hardcoded sunset at
2026-12-31T23:59:59Z), regardless of individual certificate expiry. After that
cutoff, affected apps must be re-signed with a G2 certificate to install or pass
integrity verification. Administrators running third-party apps signed under G1
should plan for re-signed releases ahead of that date.
https://github.com/owncloud/core/pull/41680
* Change - Remove occ integrity:sign-app and integrity:sign-core commands: [#41712](https://github.com/owncloud/core/pull/41712)
We've removed the occ integrity:sign-app and integrity:sign-core console
commands along with the signing-only code in the integrity checker
(createSignatureData, writeAppSignature and writeCoreSignature). Code signing is
a release and CI concern rather than an operator action performed against a
running instance, so this code was dead weight in the security-sensitive
integrity subsystem.
Integrity verification is unaffected: the integrity:check-app and
integrity:check-core commands and all signature verification continue to work as
before.
https://github.com/owncloud/core/pull/41712
* Change - Remove the caching router: [#41733](https://github.com/owncloud/core/pull/41733)
Generated urls are no longer stored in the memory cache. Measurement showed
generating a url to be faster than a cache round trip, so the cache only added a
place where urls could go stale or be tampered with.
https://github.com/owncloud/core/pull/41733
* Change - Keep host local caches in the local cache tier: [#41734](https://github.com/owncloud/core/pull/41734)
The image paths of the active theme and the mimetype id map were stored in the
distributed memory cache although both are derived from the files and the
database of a single instance. They now use the host local cache tier and their
entries expire, so a stale entry is scoped to one node and no longer lives
forever. The repair step for mimetypes deletes rows from the mimetype table and
now clears the mimetype cache afterwards, and occ upgrade clears both cache
tiers instead of only the distributed one.
https://github.com/owncloud/core/pull/41734
* Change - Cover HTML metacharacters in the username validation allow-list: [#41738](https://github.com/owncloud/core/pull/41738)
The username allow-list in OC\User\Manager::createUser() already rejects every
character outside "a-z", "A-Z", "0-9" and "+_.@-'", which blocks HTML and script
metacharacters from ever reaching a stored username. That behaviour was only
covered by three generic invalid-character cases, none of which resembled an
injection payload.
The invalid-character data provider now also exercises quote, angle-bracket and
full script-tag payloads, so any future relaxation of the allow-list that would
let markup into a username fails the test suite instead of passing unnoticed.
This is test-only coverage; no production behaviour changes.
https://github.com/owncloud/core/pull/41738
* Change - Expose createLocal() on ICacheFactory: [#41753](https://github.com/owncloud/core/pull/41753)
The cache factory has always been able to hand out a cache from the host local
tier, but the method was missing from the public ICacheFactory interface, so
core had to ask for it defensively and apps had no way to use it at all. It is
now part of the interface, which lets values that are only meaningful on the
machine that produced them be kept out of the cache shared between the nodes of
an installation.
Note for app developers: a class implementing OCP\ICacheFactory has to declare
createLocal() from this release on.
https://github.com/owncloud/core/pull/41753
* Change - Escape group names in the users administration group list: [#41758](https://github.com/owncloud/core/pull/41758)
The group list in the users administration panel built each list item by
concatenating the group id and group name into an HTML string, so both values
were interpreted as markup rather than text. Unlike usernames, group names are
not restricted to an allow-listed character set - Group\Manager::createGroup()
only rejects empty and untrimmed names - so a name containing HTML characters
was not rendered verbatim. Both interpolated values are now passed through
escapeHTML(), which makes the encoding consistent with the user rows, and the
behaviour is covered by tests in settings/tests/js/users/groupsSpec.js.
https://github.com/owncloud/core/pull/41758
* Change - Honour the write hook veto on legacy chunked WebDAV uploads: [#41762](https://github.com/owncloud/core/pull/41762)
The legacy WebDAV chunked upload path assembled the final file without
respecting the pre-write hook result, so the filename blacklist that applies to
ordinary uploads was not enforced for chunked uploads. The chunked assembly now
aborts when a write hook vetoes the file, matching the non-chunked upload path.
https://github.com/owncloud/core/pull/41762