phpLDAPadmin 2.3 — Issues and Mitigations

1. Internal .env file overrides docker-compose environment variables

phpLDAPadmin 2.3 is a Laravel app that ships with an /app/.env file containing empty values for LDAP_HOST, LDAP_USERNAME, LDAP_PASSWORD. Laravel reads this file first, so these empty strings override any environment variables passed via docker-compose.

Mitigation: Mount a custom .env file into the container at /app/.env:

volumes:
  - ./phpldapadmin.env:/app/.env:z

2. APP_KEY must be pre-generated

The container's startup script tries to auto-generate an APP_KEY by writing to /app/.env. If the mounted file isn't writable at that moment, or the key is a placeholder, Laravel throws Unsupported cipher or incorrect key length.

Mitigation: Generate the key once and persist it in phpldapadmin.env:

podman exec -it phpldapadmin php artisan key:generate --force

Ensure the mounted .env file is writable (chmod 666) so the key persists. Copy the generated key into the local phpldapadmin.env for future container recreations.

3. Config caching race condition

The entrypoint runs config:cache at startup before the volume mount may be fully available. This can cache NULL values for LDAP settings.

Mitigation: After any .env change, always re-cache:

podman exec -it phpldapadmin php artisan config:cache

4. Mixed content (HTTP vs HTTPS)

phpLDAPadmin runs behind nginx which terminates TLS. The app generates http:// URLs for assets and AJAX calls because it sees plain HTTP internally. Browsers block these as mixed content.

Mitigations applied in nginx:

# Force the app to see HTTPS
proxy_set_header X-Forwarded-Proto https;

# Tell browsers to upgrade http requests
add_header Content-Security-Policy 'upgrade-insecure-requests';

# Rewrite http to https in response bodies
sub_filter 'http://ldap.cicd.pathoris.de' 'https://ldap.cicd.pathoris.de';
sub_filter_once off;
sub_filter_types text/html text/css application/javascript application/json;

Mitigations applied in phpldapadmin.env:

APP_URL=https://ldap.cicd.pathoris.de
ASSET_URL=https://ldap.cicd.pathoris.de
TRUSTED_PROXIES=*

5. CSRF 419 errors on AJAX calls

The /ajax/bases POST endpoint returns HTTP 419 (CSRF token mismatch) when: - Session cookies have wrong Secure flag (not sent over HTTPS) - Referrer-Policy: no-referrer strips the Referer header that Laravel checks

Mitigations:

In phpldapadmin.env:

SESSION_SECURE_COOKIE=true
SESSION_DOMAIN=ldap.cicd.pathoris.de

In nginx (for the ldap server block):

add_header Referrer-Policy same-origin;

After any session config change, clear browser cookies for the domain and reload.

6. Logging not working by default

The default LOG_CHANNEL=daily writes to /app/storage/logs/ which may not have log files created. Errors are silently lost.

Mitigation: Set LOG_CHANNEL=stderr in phpldapadmin.env so errors appear in podman logs phpldapadmin. Set APP_DEBUG=true temporarily for detailed browser error pages. Remember to set APP_DEBUG=false for production.