cloudflare/cloudflared · error

Unsupported auth version: %v

Error message

Unsupported auth version: %v

What it means

The username/password (0x01) sub-negotiation authenticator reads a 2-byte header and requires version byte 0x01 (userAuthVersion). If the client sends a different sub-negotiation version, Handle returns 'Unsupported auth version'. This indicates the client's username/password auth framing is malformed or from a different RFC draft.

Source

Thrown at socks/authenticator.go:53

		IsValid: isValid,
	}
}

// Handle writes back the version and NoAuth
func (a *UserPassAuthAuthenticator) Handle(reader io.Reader, writer io.Writer) error {
	if _, err := writer.Write([]byte{socks5Version, UserPassAuth}); err != nil {
		return err
	}

	// Get the version and username length
	header := []byte{0, 0}
	if _, err := io.ReadAtLeast(reader, header, 2); err != nil {
		return err
	}

	// Ensure compatibility. Someone call E-harmony
	if header[0] != userAuthVersion {
		return fmt.Errorf("Unsupported auth version: %v", header[0])
	}

	// Get the user name
	userLen := int(header[1])
	user := make([]byte, userLen)
	if _, err := io.ReadAtLeast(reader, user, userLen); err != nil {
		return err
	}

	// Get the password length
	if _, err := reader.Read(header[:1]); err != nil {
		return err
	}

	// Get the password
	passLen := int(header[0])
	pass := make([]byte, passLen)
	if _, err := io.ReadAtLeast(reader, pass, passLen); err != nil {

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Ensure the client sends RFC 1929 username/password framing starting with version byte 0x01.
  2. Update the client library if it uses the pre-RFC draft version of sub-negotiation.
  3. Verify bytes aren't offset — check the method negotiation consumed exactly the right number of bytes.
  4. Capture the connection bytes to confirm the version byte value the client actually sends.

Example fix

// before (client)
conn.Write([]byte{0x02, 1, 'u', 1, 'p'})
// after
conn.Write(append([]byte{0x01, byte(len(user))}, append([]byte(user), append([]byte{byte(len(pass))}, []byte(pass)...)...)...))
Defensive patterns

Strategy: validation

Validate before calling

// client-side: RFC 1929 framing starts with 0x01
if header[0] != 0x01 { return fmt.Errorf("bad subnegotiation version %d", header[0]) }

Try / catch

if err := authenticator.Handle(reader, writer); err != nil {
    return fmt.Errorf("user/pass auth failed: %w", err)
}

Prevention

When it happens

Trigger: Client sends username/password auth bytes whose first byte is not 0x01 after selecting the user/pass method; short reads producing a wrong header byte.

Common situations: Clients implementing the obsolete draft (version 0x02) username/password framing; corrupt/garbage bytes from a non-conforming client; custom client code hardcoding the wrong version byte.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/0eb6c5d29d5771a0. Report an issue: GitHub.