shadow1ng/fscan · warning

redis_ping_failed

Error message

redis_ping_failed

What it means

After connecting and authenticating the handshake to a Redis server, the plugin sends a PING and expects a reply containing "PONG". If the raw response bytes do not contain PONG, it closes the connection and fails the auth attempt with redis_ping_failed, embedding the actual response text via i18n.Tr. This guards against servers that accept TCP on 6379 but do not speak RESP correctly (proxies, honeypots, HTTP endpoints, or a server requiring AUTH that returns an error string instead of PONG).

Source

Thrown at plugins/services/redis.go:173

	_ = conn.SetReadDeadline(time.Now().Add(timeout))
	response := make([]byte, 512)
	n, pingReadErr := conn.Read(response)
	if pingReadErr != nil {
		_ = conn.Close()
		return &AuthResult{
			Success:   false,
			ErrorType: ErrorTypeNetwork,
			Error:     pingReadErr,
		}
	}

	responseStr := string(response[:n])
	if !strings.Contains(responseStr, "PONG") {
		_ = conn.Close()
		return &AuthResult{
			Success:   false,
			ErrorType: ErrorTypeUnknown,
			Error:     fmt.Errorf("%s", i18n.Tr("redis_ping_failed", strings.TrimSpace(responseStr))),
		}
	}

	return &AuthResult{
		Success:   true,
		Conn:      conn,
		ErrorType: ErrorTypeUnknown,
		Error:     nil,
	}
}

// classifyRedisErrorType Redis错误分类
func classifyRedisErrorType(err error) ErrorType {
	if err == nil {
		return ErrorTypeUnknown
	}

	redisAuthErrors := []string{

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Check the actual response text embedded in the error to see what the server returned.
  2. If it is -NOAUTH, provide correct Redis credentials before the PING (set the password in the auth config).
  3. Verify the target is really Redis: run redis-cli -h <host> -p <port> PING manually.
  4. Confirm protected-mode is disabled or the scanner source IP is allowed (bind/ACL settings in redis.conf).

Example fix

// before (server returns -NOAUTH)
conn.Write([]byte("PING\r\n")) // -> "-NOAUTH Authentication required."
// after
conn.Write([]byte("AUTH mypassword\r\n"))
conn.Write([]byte("PING\r\n")) // -> "+PONG"
Defensive patterns

Strategy: try-catch

Validate before calling

conn, err := net.DialTimeout("tcp", host+":6379", 3*time.Second)
if err == nil {
    fmt.Fprintf(conn, "PING\r\n")
    buf := make([]byte, 64)
    n, _ := conn.Read(buf)
    if !strings.Contains(string(buf[:n]), "PONG") { /* expect redis_ping_failed; inspect raw response */ }
    conn.Close()
}

Type guard

func isPong(resp string) bool { return strings.Contains(resp, "PONG") }

Try / catch

res, err := plugin.Scan(ctx, target)
if err != nil {
    var ae *AuthResult
    if strings.Contains(err.Error(), "-NOAUTH") {
        // supply credentials and retry
    } else {
        log.Printf("redis probe not a real Redis server: %v", err)
    }
}

Prevention

When it happens

Trigger: doRedisAuth connects to a Redis port, completes its handshake, sends PING, and the response string does not contain "PONG" — e.g. the server returned "-NOAUTH Authentication required", "-ERR unknown command", an HTTP error page, or garbage bytes.

Common situations: Redis protected-mode or ACLs rejecting unauthenticated PING; the port actually hosts a different service (memcached, an HTTP proxy, a honeypot); a RESP-incompatible middleware in front of Redis; scanning a non-Redis service that happens to listen on 6379.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/06bb0808699e46a3. Report an issue: GitHub.