Change:
There is about the use of imagemagick in NextCloud due to . Admins may want to disable it unless they are certain that users won't upload untrusted files (which can easily happen by accident if folder sync is active). NextCloud is only passing certain file types to imagemagick but it is doing so based on the file extension. Therefore, an attacker can pass any file type to imagemagick. I have tested this with a PNM image (not supported by NextCloud) that I have renamed to . doesn't get a preview image but does, i.e. NextCloud thinks it is HEIF and passes it to ImageMagick, which processes it as PNM. There are several ways to disable imagick: in the NextCloud config. This will not only disable imagick but also previews for PNG and JPEG (which do not use imagick). in the NextCloud config. This may need manual adjustment after a NextCloud update. the extension for PHP. This also disables it for NextCloud plugins. Option 1 and 2 can already be used by an admin if the drawbacks are acceptable. However, I think 3 is the best option in most cases. has options that disable the other PHP extensions that used to be by default. I think we should do the same for imagick. If imagick is disabled, NextCloud will automatically disable the preview generators that need it. It will also show a warning about that (which is subject to debate in the issue linked above) and there may be some implications for the themes app (which I don't use). Therefore, I think we should keep imagick enabled by default and leave the decision to the admin. We could also add a suitable policy for ImageMagick and thereby disable any file formats or features that are considered insecure. I don't think I could write such a policy and be sure that it is secure (or even "secure enough"). In addition, we will have to keep it up-to-date with newer versions and CVEs. That is why I recommend that we only add a simple off switch. The above information is based on NextCloud 20. I will wait until and NextCloud 21 have landed in nixos-unstable (and on my server) and then test again and create a PR if there is any interest in having this upstream.
Ouch, decisions based purely on a file ext is a behavior that sounds pretty broken to me :/ Optiobally disabling imagemagick and adjusting the config accordingly sounds reasonable to me, so feel free to file a PR. You can ping me for a review or if you need assistance with modifying the module :)
It's ok for what they do with it. It won't do double duty as a mitigation but I guess that was never intended. Thanks. Any suggestions on a name for the new option? Simply ? Should I add any tests for that? The existing tests only test three different configurations so adding one just for imagick seems like overkill. It should be quite easy though. If we want to test that previews actually aren't generated... Well, that's a different story. We would have to automate the web interface, for that. I think the existing tests are only testing the service, CLI and WebDAV.
As imagemagick enabled will remain the default, I'd suggest . Yes, adding a fourth VM test just for imagemagick is indeed an overkill IMHO since those tend to be fairly expensive. I'd suggest to write a testcase in , other integrations such as are also tested there. Right that could be a non-trivial thing to solve. Maybe check if there's a REST API or a way to implement this with the CLI of . But I don't think it'd be worth spending too much time on this if there's no reasonable way to test :)
I think we still want to test the default option in so we will need a second configuration that disables imagick. We don't have to start that VM if we only want to check whether imagick is in its closure. As there isn't any test helper for that, we probably don't want to do that though ;-) see Unfortunately, qemu on ARM is too unreliable for the automatic tests because qemu crashes when started on one of the little cores (i.e. 4 out of 6 times). I have done some interactive testing of the above commit but not an automated run. I will have to find some system that is not ARM, not high-security, not already virtualized...
Qemu/KVM does work if a kernel build or stress-ng is hogging the big cores :) is ready for review.

Discussion:
extensions = { enabled, all }: (with all; enabled <del> ++ [ imagick ] # Always enabled </del> <ins> ++ optional (!cfg.disableImagemagick) imagick </ins> # Optionally enabled depending on caching settings ++ optional cfg.caching.apcu apcu ++ optional cfg.caching.redis redis

}; }; <ins> disableImagemagick = mkOption { type = types.bool; default = false; description = '' Whether to not load the ImageMagick module into PHP. This is used by the theming app and for generating previews of certain images (e.g. SVG and HEIF). You may want to disable it for increased security. In that case, previews will still be available for some images (e.g. JPEG and PNG). See https://github.com/nextcloud/server/issues/13099 ''; }; </ins> caching = { apcu = mkOption { type = types.bool;

maintainers = [ globin eqyiel ]; }; <del> nodes = { </del> <ins> nodes = rec { </ins> # The only thing the client needs to do is download a file. client = { ... }: { services.davfs2.enable = true;

environment.systemPackages = [ cfg.services.nextcloud.occ ]; }; <ins> nextcloudWithoutMagick = args@{ config, pkgs, lib, ... }: lib.mkMerge [ (nextcloud args) { services.nextcloud.disableImagemagick = true; } ]; </ins> }; <del> testScript = let </del> <ins> testScript = { nodes, ... }: let </ins> withRcloneEnv = pkgs.writeScript "with-rclone-env" '' #!${pkgs.runtimeShell} export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav

#!${pkgs.runtimeShell} diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file) ''; <ins> findInClosure = what: drv: pkgs.runCommand "find-in-closure" { exportReferencesGraph = [ "graph" drv ]; inherit what; } '' test -e graph grep "$what" graph >$out || true ''; nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.config.system.build.vm; nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.config.system.build.vm; </ins> in '' <del> start_all() </del> <ins> assert open("${nextcloudUsesImagick}").read() != "" assert open("${nextcloudWithoutDoesntUseIt}").read() == "" nextcloud.start() client.start() </ins> nextcloud.wait_for_unit("multi-user.target") # This is just to ensure the nextcloud-occ program is working nextcloud.succeed("nextcloud-occ status")