This issue has been created
There is 1 update, 1 comment.
 
 
XWiki Docker images / cid:jira-generated-image-avatar-c0b980f8-7961-45c1-ba0b-0ef0ab9ef0da XDOCKER-426 Open

Harden the Dockerfile build steps (LibreOffice symlink, shell error mode, checksum format)

 
View issue   ยท   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-7926fcf4-bc2e-4d68-87f0-c254b2e52bfc Vincent Massol created this issue on 29/Jul/26 19:47
 
Summary: Harden the Dockerfile build steps (LibreOffice symlink, shell error mode, checksum format)
Issue Type: cid:jira-generated-image-avatar-c0b980f8-7961-45c1-ba0b-0ef0ab9ef0da Improvement
Assignee: Unassigned
Created: 29/Jul/26 19:47
Priority: cid:jira-generated-image-static-major-addf0594-ceae-412e-b5e0-b2ee8946a4b6 Major
Reporter: Vincent Massol
Description:

Problem

While reviewing the Docker Official Images pull request that publishes XWiki 18.6.0 (docker-library/official-images#21937), the Docker Official Images maintainer made three suggestions about the Dockerfile we generate. None of them is a bug a user can hit today, but the first one turns a silent runtime failure into a build failure, and the other two align the file with the shell conventions used across the official images.

1. The LibreOffice symlink is resolved through an unquoted glob, and is never verified

The LibreOffice installation step ends with:

ln -fs $(ls -d /opt/libreoffice*) /opt/libreoffice

Two issues:

  • The command substitution is unquoted, so word splitting would break the ln invocation should the glob ever match more than one path.
  • More importantly, nothing verifies that the symlink actually points at a LibreOffice installation. That symlink is what XWiki (through JODConverter) probes to locate LibreOffice automatically, so if it ends up pointing at the wrong place the image still builds fine and office import/export silently fails at runtime.

The install directory can be derived from the pinned version instead of being discovered on the filesystem: the Document Foundation packages install into /opt/libreoffice<major>.<minor>/, and the updateLibreOffice Gradle task only ever writes a three-component version, so stripping the patch component always yields the right directory. Verifying the result in the same step makes a wrong installation fail the build.

2. The RUN blocks rely on exit-code chaining rather than an explicit error mode

The RUN blocks chain their commands with &&. The Docker Official Images convention is set -eux; with ; separators. Beyond being the house style, it is more robust to later edits: with && chaining, adding a line and forgetting its trailing && silently ignores that command's failure, whereas set -e always propagates it. set -x also traces each command in the build log, which helps when a build fails on one of the transient network errors these downloads are prone to.

3. The sha256 verifications do not use the conventional binary-mode format

The checksum verifications are written as:

echo "$SHA256 file" | sha256sum -c -

The conventional form for verifying a downloaded binary prefixes the filename with * and passes --strict, which makes sha256sum reject a malformed input line rather than skip it.

Proposal

Apply the three changes to template/Dockerfile and regenerate. For consistency, apply points 2 and 3 to every RUN block and every checksum verification in the file rather than only to the two blocks quoted in the review, so that the Dockerfile does not end up with mixed styles.

 
 

1 update

 
cid:jira-generated-image-avatar-7926fcf4-bc2e-4d68-87f0-c254b2e52bfc Changes by Vincent Massol on 29/Jul/26 19:48
 
Assignee: Vincent Massol
 
 

1 comment

 
cid:jira-generated-image-avatar-7926fcf4-bc2e-4d68-87f0-c254b2e52bfc Vincent Massol on 29/Jul/26 19:54
 

PR: https://github.com/xwiki/xwiki-docker/pull/100

While verifying that the new test -x /opt/libreoffice/program/soffice guard actually fails the build when the symlink is wrong, a second problem with the ln invocation turned up, beyond the unquoted glob reported in the review: ln -fs dereferences an already-existing /opt/libreoffice symlink that points to a directory, and creates the new link *inside* that directory instead of replacing it. The original symlink is left pointing at the previous installation, and no error is reported.

$ readlink /opt/libreoffice
/opt/libreoffice25.8
$ ln -fs /opt/libreoffice26.0 /opt/libreoffice
$ readlink /opt/libreoffice
/opt/libreoffice25.8          <- unchanged
$ ls /opt/libreoffice25.8/libreoffice26.0
/opt/libreoffice25.8/libreoffice26.0   <- stray link created here

This cannot be triggered by the Dockerfile as written, since the symlink is created once in a layer where it does not exist yet. It matters anyway because it would defeat the new guard: test -x would keep passing against the stale target. The PR therefore passes -n to ln so that the command replaces the symlink itself regardless of the prior state.