#3799·kubescape

operator scan/remediate hangs indefinitely if the port-forward to the Operator pod never becomes ready

Author: SeeyaVhoraCreated Sep 10, 2026Updated Sep 10, 2026

Problem Description

When running kubescape operator scan or kubescape operator remediate, Kubescape connects to the in-cluster Kubescape Operator by establishing a port-forward to its pod via CreatePortForwarder and StartPortForwarder.

In core/cautils/portforwarder.go, waitForPortForwardReadiness() waits for readiness using an unbounded select:

go
select {
case <-p.readyChan:
    return nil
case err := <-p.errChan:
    if err == nil {
        err = fmt.Errorf("port-forward exited before becoming ready: %s", strings.TrimSpace(p.errOut.String()))
    }
    return err
}

If the dial stalls (e.g. network partition, dropped packets, or the API server accepts the TCP connection but never completes the SPDY upgrade handshake), neither readyChan nor errChan is ever closed or sent on. Furthermore, http.Client inside CreatePortForwarder has no timeout configured, leaving the connection attempt completely unbounded.

Trigger Sequence & Impact

  1. User invokes kubescape operator scan or kubescape operator remediate.
  2. Kubescape initiates a port-forward connection to the operator pod.
  3. If the remote endpoint hangs during connection setup or the SPDY upgrade handshake stalls, waitForPortForwardReadiness blocks indefinitely.
  4. The CLI hangs indefinitely with no timeout, no diagnostic error, and no recourse other than sending SIGKILL or terminating the process manually.

Context & Prior Art

This coordination logic has seen prior merged fixes for closely related hang/blocking edge cases:

  • #2381 — avoid blocking on repeated stop signals
  • #3272 / #3273 — safely stop PortForwarder without dropping stop signals
  • Earlier fix adding ForwardPorts error surfacing to waitForPortForwardReadiness

Adding an explicit bounded timeout to waitForPortForwardReadiness and the underlying dialer will close this remaining gap and provide a clear, actionable diagnostic error instead of an indefinite hang.