mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
graphql: document depth limit
This commit is contained in:
parent
5ebd8032b9
commit
52791a1a7b
2 changed files with 40 additions and 1 deletions
|
|
@ -430,6 +430,40 @@ func TestWithdrawals(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGraphQLMaxDepth ensures that queries exceeding the configured maximum depth
|
||||||
|
// are rejected to prevent resource exhaustion from deeply nested operations.
|
||||||
|
func TestGraphQLMaxDepth(t *testing.T) {
|
||||||
|
stack := createNode(t)
|
||||||
|
defer stack.Close()
|
||||||
|
|
||||||
|
h, err := newHandler(stack, nil, nil, []string{}, []string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not create graphql service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var b strings.Builder
|
||||||
|
for i := 0; i < maxQueryDepth+1; i++ {
|
||||||
|
b.WriteString("ommers{")
|
||||||
|
}
|
||||||
|
b.WriteString("number")
|
||||||
|
for i := 0; i < maxQueryDepth+1; i++ {
|
||||||
|
b.WriteString("}")
|
||||||
|
}
|
||||||
|
query := fmt.Sprintf("{block{%s}}", b.String())
|
||||||
|
|
||||||
|
res := h.Schema.Exec(context.Background(), query, "", nil)
|
||||||
|
var found bool
|
||||||
|
for _, err := range res.Errors {
|
||||||
|
if err.Rule == "MaxDepthExceeded" {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Fatalf("expected max depth exceeded error, got %v", res.Errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createNode(t *testing.T) *node.Node {
|
func createNode(t *testing.T) *node.Node {
|
||||||
stack, err := node.New(&node.Config{
|
stack, err := node.New(&node.Config{
|
||||||
HTTPHost: "127.0.0.1",
|
HTTPHost: "127.0.0.1",
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ import (
|
||||||
gqlErrors "github.com/graph-gophers/graphql-go/errors"
|
gqlErrors "github.com/graph-gophers/graphql-go/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// maxQueryDepth limits the maximum field nesting depth allowed in GraphQL queries.
|
||||||
|
// Without this bound, deeply nested queries could exhaust resources and lead to DoS.
|
||||||
|
// See https://github.com/ethereum/go-ethereum/issues/26026 for more details.
|
||||||
|
const maxQueryDepth = 20
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
Schema *graphql.Schema
|
Schema *graphql.Schema
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +121,7 @@ func New(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterS
|
||||||
func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) (*handler, error) {
|
func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) (*handler, error) {
|
||||||
q := Resolver{backend, filterSystem}
|
q := Resolver{backend, filterSystem}
|
||||||
|
|
||||||
s, err := graphql.ParseSchema(schema, &q)
|
s, err := graphql.ParseSchema(schema, &q, graphql.MaxDepth(maxQueryDepth))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue