Skip to content

Healthcheck reports false positives for GPG and JWT #604

@alehostert

Description

@alehostert

Passbolt version: 5.11.0
PHP version: 8.3.21 (LiteSpeed / lsphp83)
OS: Infinite OS (Linux 6.19.11-1-default)
Cache backend: FileEngine (no Redis)
Deployment: Single container, custom web server (LiteSpeed), deployed via Infinite OS Marketplace

Description

The passbolt healthcheck command reports the following FAILs:

[FAIL] The /config/jwt/ directory should not be writable.
[FAIL] The private key cannot be used to decrypt and verify a message
[FAIL] The public key cannot be used to verify a signature.

However, manual verification confirms all three checks are actually passing correctly.

Details

The installation follow the steps described in Infinite OS Marketplace manifest. For example, the jwt keys are generated this way:

  - su nobody --shell /bin/bash -c "/usr/local/lsws/lsphp83/bin/php %installDirectory%/bin/cake.php passbolt create_jwt_keys --quiet"

The app is working fine, just the healtcheck disagrees with me :)

The OpenLiteSpeed is configured to run with nobody:nogroup:

head -4 /usr/local/lsws/conf/httpd_config.conf
serverName
httpdworkers 2                
user                      nobody
group                     nogroup

1. JWT directory permissions

The healthcheck reports the jwt/ directory as writable, but the actual permissions are:

drwxr-x--- 2 nobody nogroup 49 Mar 12 13:55 /app/html/config/jwt/
-rw-r----- 1 nobody nogroup 3272 jwt.key
-rw-r----- 1 nobody nogroup  800 jwt.pem

This matches exactly the permissions recommended by the healthcheck help text itself (750 on dir, 640 on files).

2. GPG decrypt + verify

The healthcheck reports:

[FAIL] The private key cannot be used to decrypt and verify a message
[FAIL] The public key cannot be used to verify a signature.

Running the equivalent operations manually as the web server user (nobody) succeeds:

# Encrypt + sign
su nobody --shell /bin/bash -c '
  echo "test" | gpg --homedir /app/.gnupg --encrypt --sign \
    --recipient [fingerprint] --armor > /tmp/gpg_test.asc && echo "OK encrypt+sign"
'
# Output: OK encrypt+sign

# Decrypt (includes signature verification)
su nobody --shell /bin/bash -c '
  gpg --homedir /app/.gnupg --decrypt /tmp/gpg_test.asc && echo "OK decrypt"
'
# Output:
# gpg: encrypted with 3072-bit RSA key ...
# test
# gpg: Good signature from "..." [ultimate]
# OK decrypt

Note: combining --decrypt --verify in a single gpg call returns gpg: conflicting commands — this may be relevant to how the healthcheck performs its internal test.

su nobody --shell /bin/bash -c '
  gpg --homedir /app/.gnupg --decrypt --verify /tmp/gpg_test.asc && echo "OK decrypt+verify"
'
gpg: conflicting commands

Expected behavior

Healthcheck should report PASS for JWT directory permissions and GPG operations when they are demonstrably functional.

Additional context

  • The instance has been running in production for several months without any issues related to GPG or JWT authentication. The app runs 100% fine.
  • The environment uses Infinite OS, a container based on minideb
  • Cache is configured as FileEngine (no Redis). The dashboard initially showed a cache warning, which also appeared to be a false positive — cache files were being written correctly to tmp/cache/.
grep -A 4 "'Cache'" /app/html/config/app.php
    'Cache' => [
        'default' => [
            'className' => FileEngine::class,
            'path' => CACHE,
            'url' => env('CACHE_DEFAULT_URL', null),

ls -la /app/html/tmp/cache/
total 60
drwxr-xrwx 6 nobody nogroup    97 Apr 13 14:08 .
drwxr-xrwx 7 nobody nogroup    92 Apr 13 13:53 ..
-rw-rw-r-- 1 nobody nogroup 52729 Apr 13 14:08 cake_table.actions.all
drwxr-xrwx 2 nobody nogroup    77 Apr 13 13:53 database
drwxr-xrwx 2 nobody nogroup  4096 Apr 13 14:08 models
drwxr-xrwx 2 nobody nogroup  4096 Apr 13 14:08 persistent
drwxr-xrwx 2 nobody nogroup     6 Jun 17  2025 views

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions