#15818·chatwoot

[BUG] sidekiq_alive binds to 0.0.0.0:7433 by default on Linux/VM installs, causing 100% CPU lockup from external TCP scans

Author: md-riazCreated Sep 15, 2026Updated Sep 16, 2026
LabelsperformanceBug

Describe the bug

In PR #12008 (commit 2a5ecf84a1), the sidekiq_alive gem was added to the Gemfile to provide a healthcheck probe on port 7433.

However, no initializer (config/initializers/sidekiq_alive.rb) or environment variable configuration was provided. On standard self-hosted Linux (systemd / VM / bare-metal) deployments, sidekiq_alive defaults to binding to 0.0.0.0:7433, exposing the internal health check port directly to the public internet.

Furthermore, sidekiq_alive-2.5.0's built-in http_server.rb contains an infinite loop bug on client disconnect / EOF. In SidekiqAlive::HttpServer#serve:

ruby
# parse HTTP headers
while (line = io.gets) !~ /^(\n|\r)/
  if line =~ /^([\w-]+):\s*(.*)$/
    request.header[::Regexp.last_match(1)] = ::Regexp.last_match(2).strip
  end
end

When an external network crawler or port scanner (e.g. ZGrab, Shodan, automated scanner bots) connects to port 7433 and closes the TCP connection without sending valid HTTP headers, io.gets returns nil. Because nil !~ /^(\n|\r)/ evaluates to true, the loop becomes while true and never terminates, spinning at 100% CPU on the Sidekiq Ruby thread indefinitely.

In our production Linux VM, a single crawler connection trapped thread gserver.rb:264 in this loop, consuming 100% of an entire CPU core continuously for hours, starving Sidekiq job processing and degrading overall server performance.

To Reproduce

  1. Deploy Chatwoot on an Ubuntu Linux VM following the official self-hosted Linux installation guide without a host-level firewall.
  2. Verify that port 7433 is publicly listening on 0.0.0.0:
    bash
    ss -tlpn | grep 7433
    # LISTEN 0 4096 0.0.0.0:7433 users:(("ruby",pid=...,fd=...))
  3. Send a TCP handshake / raw connection (or wait for an internet scanner probe):
    bash
    nc -z <SERVER_PUBLIC_IP> 7433
  4. Inspect threads under Sidekiq:
    bash
    top -H -p <SIDEKIQ_PID>
  5. A Ruby thread named gserver.rb:264 gets permanently trapped in the loop and consumes 100% CPU.

Expected behavior

  1. sidekiq_alive should bind to 127.0.0.1 by default on non-containerized environments (or be configurable via SIDEKIQ_ALIVE_HOST).
  2. .env.example should document SIDEKIQ_ALIVE_HOST=127.0.0.1 and SIDEKIQ_ALIVE_PORT=7433.
  3. Chatwoot should provide a config/initializers/sidekiq_alive.rb to ensure safe localhost defaults.

Environment

Linux VM

Cloud Provider

Other [please specify in the description]

Operating system

Ubuntu 22.04 LTS

Proposed Fix

  1. Code Level: Add config/initializers/sidekiq_alive.rb:

    ruby
    if defined?(SidekiqAlive)
      SidekiqAlive.setup do |config|
        config.host = ENV.fetch('SIDEKIQ_ALIVE_HOST', '127.0.0.1')
        config.port = Integer(ENV.fetch('SIDEKIQ_ALIVE_PORT', 7433))
      end
    end
  2. Configuration Level: Add to .env.example:

    bash
    # Sidekiq Health Check (SidekiqAlive)
    # Defaults to 127.0.0.1 to avoid exposing the probe port publicly on VM installations
    SIDEKIQ_ALIVE_HOST=127.0.0.1
    SIDEKIQ_ALIVE_PORT=7433
  3. Deployment / Docs Level: Update chatwoot-worker.1.service template and self-hosted documentation to include SIDEKIQ_ALIVE_HOST=127.0.0.1.