Skip to content

Hijack() method incorrectly rejects valid HTTP hijacking scenarios #4462

@nanziok

Description

@nanziok

Description

The Hijack() method in Gin's responseWriter incorrectly blocks legitimate HTTP connection hijacking by using w.Written() as the guard condition. According to the HTTP standard and Go's net/http implementation, hijacking is allowed after WriteHeader() has been called (e.g., for WebSocket protocol upgrades), but must be blocked only after response body data has been written.

After only writing the headers, w.size is now 0, not -1.

Gin Version

1.11.0

Can you reproduce the bug?

Yes

Source Code

r := gin.New()
r.Use(gin.Recovery())
r.GET("/ws", func(c *gin.Context) {
	c.Writer.Header().Add("Content-Type", "binary/octet-stream")
	c.Writer.WriteHeader(http.StatusSwitchingProtocols)
	c.Writer.WriteHeaderNow()
	hijacker, ok := c.Writer.(http.Hijacker)
	if !ok {
		fmt.Println("hijack not supported")
		return
	}
	netConn, _, err := hijacker.Hijack()
	if err != nil {
		fmt.Println("failed to hijack connection", err)
		return
	}
	defer netConn.Close()
	fmt.Println("hijacked")
})
r.Run(":8080")

Go Version

1.25.3

Operating System

Win

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugFound something you weren't expecting? Report it here!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions