Skip to content

[BUG] swag-dashboard: Proxy enumeration bug #1135

@dever23b

Description

@dever23b

Is there an existing issue for this?

  • I have searched the existing issues

Name of mod

swag-dashboard

Name of base container

swag

Current Behavior

When viewing the dashboard, list of proxies is empty and two errors are generated in the error log.

Errors:

*1 FastCGI sent in stderr: "PHP message: PHP Warning:  foreach() argument must be of type array|object, null given in /dashboard/www/index.php on line 63" while reading response header from upstream, client: [redacted], server: dashboard.*, request: "GET / HTTP/2.0", upstream: "fastcgi://127.0.0.1:9000", host: "dashboard.[redacted]"
*28 FastCGI sent in stderr: "PHP message: PHP Warning:  foreach() argument must be of type array|object, null given in /dashboard/www/proxies.php on line 18" while reading response header from upstream, client: [redacted], server: dashboard.*, request: "GET /proxies.php HTTP/2.0", upstream: "fastcgi://127.0.0.1:9000", host: "dashboard.[redacted]"

Further investigation: index.php and proxies.php do not perform any sanity checks on $output or $results before calling foreach(), exposing an unhandled error when $results is an expected value.

Additional information:
When I create a shell in the container and execute the python script manually (/lsiopy/bin/python3 /dashboard/swag-proxies.py | jq ), the script seems to return a valid JSON response. I don't quite understand why it's not getting interpreted properly when PHP calls it. Furthermore, this is only happening on a second Docker host I'm attempting to bring online. On my primary host, all of the proxied containers are displayed normally. I'm not quite sure what's different: I've tried to make configs of this container on both hosts very similar for consistency.

Expected Behavior

When viewing the dashboard, list of proxies is accurate and no errors are generated in the error log

Steps To Reproduce

  1. Run new swag container with swag-dashboard mod enabled
  2. Navigate to dashboard.*
  3. Observe

Environment

- OS: QNAP QTS 5.2.8
- How docker service was installed: Container Station

CPU architecture

x86-64

Docker creation

name: proxy
services:
    docker-proxy:
        image: tecnativa/docker-socket-proxy
        environment:
            CONTAINERS: 1
            NETWORKS: 1
            POST: 0
        networks:
            - docker
        privileged: true
        restart: unless-stopped
        userns_mode: host
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock:ro
    swag:
        image: lscr.io/linuxserver/swag:latest
        cap_add:
            - NET_ADMIN
        depends_on:
            - docker-proxy
        env_file:
            - /share/docker/local/proxy/swag.env
        networks:
           - docker
           - default
        ports:
            - "80:80"
            - "443:443"
        restart: unless-stopped
        sysctls:
            net.ipv4.ping_group_range: "1000 1000"
        volumes:
            - /share/docker/local/proxy/config:/config
networks:
    docker:
        internal: true
    default:
        external: true
        name: server

Container logs

[1073] $ docker compose logs swag
swag-1  | [mod-init] Running Docker Modification Logic
swag-1  | [mod-init] Adding linuxserver/mods:universal-docker to container
swag-1  | [mod-init] Downloading linuxserver/mods:universal-docker from lscr.io
swag-1  | [mod-init] Installing linuxserver/mods:universal-docker
swag-1  | [mod-init] linuxserver/mods:universal-docker applied to container
swag-1  | [mod-init] Adding linuxserver/mods:swag-auto-proxy to container
swag-1  | [mod-init] Downloading linuxserver/mods:swag-auto-proxy from lscr.io
swag-1  | [mod-init] Installing linuxserver/mods:swag-auto-proxy
swag-1  | [mod-init] linuxserver/mods:swag-auto-proxy applied to container
swag-1  | [mod-init] Adding linuxserver/mods:swag-maxmind to container
swag-1  | [mod-init] Downloading linuxserver/mods:swag-maxmind from lscr.io
swag-1  | [mod-init] Installing linuxserver/mods:swag-maxmind
swag-1  | [mod-init] linuxserver/mods:swag-maxmind applied to container
swag-1  | [mod-init] Adding linuxserver/mods:swag-dashboard to container
swag-1  | [mod-init] Downloading linuxserver/mods:swag-dashboard from lscr.io
swag-1  | [mod-init] Installing linuxserver/mods:swag-dashboard
swag-1  | [mod-init] linuxserver/mods:swag-dashboard applied to container
swag-1  | [mod-init] Adding linuxserver/mods:universal-cloudflared to container
swag-1  | [mod-init] Downloading linuxserver/mods:universal-cloudflared from lscr.io
swag-1  | [mod-init] Installing linuxserver/mods:universal-cloudflared
swag-1  | [mod-init] linuxserver/mods:universal-cloudflared applied to container
swag-1  | [migrations] started
swag-1  | [migrations] 01-nginx-site-confs-default: skipped
swag-1  | [migrations] 02-swag-old-certbot-paths: skipped
swag-1  | [migrations] done
swag-1  | ───────────────────────────────────────
swag-1  |
swag-1  |       ██╗     ███████╗██╗ ██████╗
swag-1  |       ██║     ██╔════╝██║██╔═══██╗
swag-1  |       ██║     ███████╗██║██║   ██║
swag-1  |       ██║     ╚════██║██║██║   ██║
swag-1  |       ███████╗███████║██║╚██████╔╝
swag-1  |       ╚══════╝╚══════╝╚═╝ ╚═════╝
swag-1  |
swag-1  |    Brought to you by linuxserver.io
swag-1  | ───────────────────────────────────────
swag-1  |
swag-1  | To support the app dev(s) visit:
swag-1  | Certbot: https://supporters.eff.org/donate/support-work-on-certbot
swag-1  |
swag-1  | To support LSIO projects visit:
swag-1  | https://www.linuxserver.io/donate/
swag-1  |
swag-1  | ───────────────────────────────────────
swag-1  | GID/UID
swag-1  | ───────────────────────────────────────
swag-1  |
swag-1  | User UID:    1000
swag-1  | User GID:    1000
swag-1  | ───────────────────────────────────────
swag-1  | Linuxserver.io version: 5.2.2-ls427
swag-1  | Build-date: 2025-12-27T03:59:40+00:00
swag-1  | ───────────────────────────────────────
swag-1  |
swag-1  | using keys found in /config/keys
swag-1  | chmod: changing permissions of '/etc/logrotate.d/acpid': Bad address
swag-1  | chmod: changing permissions of '/etc/logrotate.d/fail2ban': Bad address
swag-1  | chmod: changing permissions of '/etc/logrotate.d/lerotate': Bad address
swag-1  | chmod: changing permissions of '/etc/logrotate.d/nginx': Bad address
swag-1  | chmod: changing permissions of '/etc/logrotate.d/php-fpm': Bad address
swag-1  | chmod: changing permissions of '/etc/logrotate.d/php-fpm84': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/site-confs': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/site-confs/default.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/site-confs/default.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/nginx.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ssl.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authelia-location.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authelia-server.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authentik-location.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authentik-server.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ldap-location.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ldap-server.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/proxy.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/tinyauth-location.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/tinyauth-server.conf.sample': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/nginx.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ssl.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/dhparams.pem': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/resolver.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/worker_processes.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/proxy-confs': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/proxy-confs/dashboard.subdomain.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/proxy-confs/qnap.subdomain.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/proxy.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authelia-location.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authelia-server.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authentik-location.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/authentik-server.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/tinyauth-location.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/tinyauth-server.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ldap-location.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/ldap-server.conf': Bad address
swag-1  | chmod: changing permissions of '/config/nginx/maxmind.conf': Bad address
swag-1  | Variables set:
swag-1  | PUID=1000
swag-1  | PGID=1000
swag-1  | TZ=America/New_York
swag-1  | URL=[redacted]
swag-1  | SUBDOMAINS=wildcard
swag-1  | EXTRA_DOMAINS=[redacted]
swag-1  | ONLY_SUBDOMAINS=false
swag-1  | VALIDATION=dns
swag-1  | CERTPROVIDER=letsencrypt
swag-1  | DNSPLUGIN=cloudflare
swag-1  | EMAIL=[redacted]
swag-1  | STAGING=
swag-1  |
swag-1  | Using Let's Encrypt as the cert provider
swag-1  | SUBDOMAINS entered, processing
swag-1  | Wildcard cert for [redacted] will be requested
swag-1  | EXTRA_DOMAINS entered, processing
swag-1  | Extra domains processed are: [redacted]
swag-1  | E-mail address entered:  [redacted]
swag-1  | dns validation via cloudflare plugin is selected
swag-1  | Certificate exists; parameters unchanged; starting nginx
swag-1  | The cert does not expire within the next day. Letting the cron script handle the renewal attempts overnight (2:08am).
swag-1  | **** Cloudflared setup script init... ****
swag-1  | **** Checking cloudflared setup script requirements... ****
swag-1  | **** Applying the SWAG dashboard mod... ****
swag-1  | **** Linux architecture found: amd64 ****
swag-1  | **** Installing cloudflared...****
swag-1  | **** Installing yq ****
swag-1  | **** Moving /cloudflared/cloudflared to /usr/local/bin/cloudflared... ****
swag-1  | **** installing docker and docker compose ****
swag-1  | Copying over docker and docker-compose binaries
swag-1  | **** Deleting tmp /cloudflared dir... ****
swag-1  | **** adding libmaxminddb to package install list ****
swag-1  | **** Cloudflared installed ****
swag-1  | **** Adding goaccess to package install list ****
swag-1  | **** libmaxminddb already installed, skipping ****
swag-1  | **** Applied the SWAG dashboard mod ****
swag-1  | **** Remote docker service tcp://docker-proxy:2375 will be used ****
swag-1  | cloudflared version 2026.3.0 (built 2026-03-09-14:08 UTC)
swag-1  | **** Checking for cloudflare tunnel parameters... ****
swag-1  | **** CF_REMOTE_MANAGE_TOKEN is set, cloudflared will attempt to connect to existing tunnel ****
swag-1  | **** Cloudflared setup script done, exiting... ****
swag-1  | **** Using docker binary from the universal-docker mod ****
swag-1  | [pkg-install-init] **** Installing all mod packages ****
swag-1  | fetch http://dl-cdn.alpinelinux.org/alpine/v3.22/main/x86_64/APKINDEX.tar.gz
swag-1  | fetch http://dl-cdn.alpinelinux.org/alpine/v3.22/community/x86_64/APKINDEX.tar.gz
swag-1  | (1/2) Installing goaccess (1.9.4-r0)
swag-1  | (2/2) Installing libmaxminddb (1.9.1-r0)
swag-1  | Executing busybox-1.37.0-r20.trigger
swag-1  | OK: 189 MiB in 223 packages
swag-1  | Applying the maxmind mod...
swag-1  | Applied the maxmind mod
swag-1  | **** No preset proxy conf found for pihole-pihole-1, generating from scratch ****
swag-1  | **** Setting upstream address pihole-pihole-1 for pihole-pihole-1 ****
swag-1  | **** Setting port 123 for pihole-pihole-1 ****
swag-1  | **** Setting proto http for pihole-pihole-1 ****
swag-1  | **** Setting url pihole.[redacted] pi.hole for pihole-pihole-1 ****
swag-1  | [custom-init] No custom files found, skipping...
swag-1  | Auto-reload: Watching the following folders for changes to .conf files:
swag-1  | /config/nginx
swag-1  | [ls.io-init] done.
swag-1  | Server ready
swag-1  | 2026-03-14T04:15:30Z INF Starting tunnel tunnelID=[redacted]
swag-1  | 2026-03-14T04:15:30Z INF Version 2026.3.0 (Checksum 4a9e50e6d6d798e90fcd01933151a90bf7edd99a0a55c28ad18f2e16263a5c30)
swag-1  | 2026-03-14T04:15:30Z INF GOOS: linux, GOVersion: go1.24.13, GoArch: amd64
swag-1  | 2026-03-14T04:15:30Z INF Settings: map[no-autoupdate:true token:*****]
swag-1  | 2026-03-14T04:15:30Z INF Generated Connector ID: fb21e223-cded-41d8-834b-3f1e1b09d86d
swag-1  | 2026-03-14T04:15:30Z INF Initial protocol quic
swag-1  | 2026-03-14T04:15:30Z INF ICMP proxy will use [redacted] as source for IPv4
swag-1  | 2026-03-14T04:15:30Z INF ICMP proxy will use ::1 in zone lo as source for IPv6
swag-1  | 2026-03-14T04:15:31Z INF ICMP proxy will use [redacted] as source for IPv4
swag-1  | 2026-03-14T04:15:31Z INF ICMP proxy will use ::1 in zone lo as source for IPv6
swag-1  | 2026-03-14T04:15:31Z INF Starting metrics server on 127.0.0.1:20241/metrics
swag-1  | 2026-03-14T04:15:31Z INF Tunnel connection curve preferences: [[redacted]] connIndex=0 event=0 ip=[redacted]
swag-1  | 2026/03/14 00:15:31 failed to sufficiently increase receive buffer size (was: 800 kiB, wanted: 7168 kiB, got: 3200 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details.
swag-1  | 2026-03-14T04:15:31Z INF Registered tunnel connection connIndex=0 connection=[redacted] event=0 ip=[redacted] location=[redacted] protocol=quic
swag-1  | 2026-03-14T04:15:31Z INF Tunnel connection curve preferences: [[redacted]] connIndex=1 event=0 ip=[redacted]
swag-1  | 2026-03-14T04:15:31Z INF Updated to new configuration config="{\"ingress\":[{\"hostname\":\"[redacted]\",\"originRequest\":{},\"service\":\"http://localhost\"},{\"hostname\":\"[redacted]\",\"originRequest\":{},\"service\":\"http://localhost\"},{\"service\":\"http_status:404\"}],\"warp-routing\":{\"enabled\":false}}" version=9
swag-1  | 2026-03-14T04:15:32Z INF Tunnel connection curve preferences: [[redacted]] connIndex=2 event=0 ip=[redacted]
swag-1  | 2026-03-14T04:15:32Z INF Registered tunnel connection connIndex=1 connection=[redacted] event=0 ip=[redacted] location=[redacted] protocol=quic
swag-1  | 2026-03-14T04:15:33Z INF Tunnel connection curve preferences: [[redacted][redacted]] connIndex=3 event=0 ip=[redacted]
swag-1  | 2026-03-14T04:15:34Z INF Registered tunnel connection connIndex=3 connection=[redacted] event=0 ip=[redacted] location=[redacted] protocol=quic
swag-1  | 2026-03-14T04:15:34Z INF Registered tunnel connection connIndex=2 connection=[redacted] event=0 ip=[redacted] location=[redacted] protocol=quic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions