mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-25 02:48:16 +08:00
Merge 9040029d9caa7373784bdbc3b604710a962081bb into d9307dbcbbe796a64d9e0ef23452da888dd7f904
This commit is contained in:
commit
e8307ad045
43
.github/workflows/cifuzz.yml
vendored
Normal file
43
.github/workflows/cifuzz.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: CIFuzz
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
- '.github/workflows/cifuzz.yml'
|
||||
push:
|
||||
branches: [main, master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sanitizer: [address]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Build Fuzzers (${{ matrix.sanitizer }})
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@ba0e2e0399a10b7b42afb16e7a6c4ccd3ff52431
|
||||
with:
|
||||
oss-fuzz-project-name: 'gin'
|
||||
language: go
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
- name: Run Fuzzers (${{ matrix.sanitizer }})
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@ba0e2e0399a10b7b42afb16e7a6c4ccd3ff52431
|
||||
with:
|
||||
oss-fuzz-project-name: 'gin'
|
||||
language: go
|
||||
fuzz-seconds: 300
|
||||
sanitizer: ${{ matrix.sanitizer }}
|
||||
output-sarif: true
|
||||
- name: Upload Sarif
|
||||
if: always() && steps.build.outcome == 'success'
|
||||
uses: github/codeql-action/upload-sarif@601d5b1bcb3e5ef5eea97a6d0dcdbbb8c2b80116
|
||||
with:
|
||||
sarif_file: cifuzz-sarif/results.sarif
|
||||
category: fuzz-${{ matrix.sanitizer }}
|
||||
102
fuzz_test.go
Normal file
102
fuzz_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright 2014 Manu Martinez-Almeida
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gin_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
)
|
||||
|
||||
// FuzzJSONBinding tests JSON request body binding with arbitrary
|
||||
// attacker-controlled byte input.
|
||||
//
|
||||
// This is the pre-auth boundary for every JSON API built with Gin.
|
||||
// Every JSON request body passes through this code path.
|
||||
// Gin has 88K+ GitHub stars and is imported by thousands of Go projects.
|
||||
//
|
||||
// 5 GitHub Security Advisories exist for Gin.
|
||||
func FuzzJSONBinding(f *testing.F) {
|
||||
jsonBinding := binding.JSON
|
||||
|
||||
f.Add([]byte(`{"name":"test","age":30}`))
|
||||
f.Add([]byte(`{}`))
|
||||
f.Add([]byte(``))
|
||||
f.Add([]byte(`{"a":`))
|
||||
f.Add([]byte(`null`))
|
||||
f.Add([]byte(`[1,2,3]`))
|
||||
f.Add(make([]byte, 10000))
|
||||
|
||||
f.Fuzz(func(t *testing.T, body []byte) {
|
||||
if len(body) > 1<<16 {
|
||||
return
|
||||
}
|
||||
|
||||
var obj map[string]any
|
||||
// BindBody must never panic on any input
|
||||
_ = jsonBinding.BindBody(body, &obj)
|
||||
})
|
||||
}
|
||||
|
||||
// FuzzGinPathMatch tests URL path parameter matching with
|
||||
// arbitrary attacker-controlled paths.
|
||||
//
|
||||
// Path matching determines routing and extracts parameters
|
||||
// from URLs. This is the first code that processes every
|
||||
// incoming HTTP request.
|
||||
func FuzzGinPathMatch(f *testing.F) {
|
||||
f.Add("/users/:id", "/users/123")
|
||||
f.Add("/api/:version/users/:id", "/api/v1/users/42")
|
||||
f.Add("/", "/")
|
||||
f.Add("/static/*filepath", "/static/css/main.css")
|
||||
f.Add(strings.Repeat("/a", 100), "/a/a")
|
||||
|
||||
f.Fuzz(func(t *testing.T, pattern, path string) {
|
||||
if len(pattern) > 10000 || len(path) > 10000 {
|
||||
return
|
||||
}
|
||||
if pattern == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Test route construction + matching
|
||||
router := gin.New()
|
||||
func() {
|
||||
defer func() { _ = recover() }()
|
||||
router.GET(pattern, func(c *gin.Context) {})
|
||||
router.Handle("GET", path, func(c *gin.Context) {})
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// FuzzFormBinding tests form POST body binding with arbitrary
|
||||
// key-value pairs from HTTP POST requests.
|
||||
func FuzzFormBinding(f *testing.F) {
|
||||
f.Add("name=test&age=30")
|
||||
f.Add("")
|
||||
f.Add("a=1&b=2&c=3")
|
||||
|
||||
f.Fuzz(func(t *testing.T, formData string) {
|
||||
if len(formData) > 1<<16 {
|
||||
return
|
||||
}
|
||||
|
||||
// Form binding parses POST form data
|
||||
// Create a minimal request with form body
|
||||
req, err := http.NewRequest("POST", "/", strings.NewReader(formData))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
var obj map[string]string
|
||||
_ = binding.Form.Bind(req, &obj)
|
||||
})
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user