diff -Nru golang-github-gorilla-csrf-1.7.1/.circleci/config.yml golang-github-gorilla-csrf-1.7.2/.circleci/config.yml --- golang-github-gorilla-csrf-1.7.1/.circleci/config.yml 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.circleci/config.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -version: 2.1 - -jobs: - "test": - parameters: - version: - type: string - default: "latest" - golint: - type: boolean - default: true - modules: - type: boolean - default: true - goproxy: - type: string - default: "" - docker: - - image: "circleci/golang:<< parameters.version >>" - working_directory: /go/src/github.com/gorilla/csrf - environment: - GO111MODULE: "on" - GOPROXY: "<< parameters.goproxy >>" - steps: - - checkout - - run: - name: "Print the Go version" - command: > - go version - - run: - name: "Fetch dependencies" - command: > - if [[ << parameters.modules >> = true ]]; then - go mod download - export GO111MODULE=on - else - go get -v ./... - fi - # Only run gofmt, vet & lint against the latest Go version - - run: - name: "Run golint" - command: > - if [ << parameters.version >> = "latest" ] && [ << parameters.golint >> = true ]; then - go get -u golang.org/x/lint/golint - golint ./... - fi - - run: - name: "Run gofmt" - command: > - if [[ << parameters.version >> = "latest" ]]; then - diff -u <(echo -n) <(gofmt -d -e .) - fi - - run: - name: "Run go vet" - command: > - if [[ << parameters.version >> = "latest" ]]; then - go vet -v ./... - fi - - run: - name: "Run go test (+ race detector)" - command: > - go test -v -race ./... - -workflows: - tests: - jobs: - - test: - matrix: - parameters: - version: ["latest", "1.15", "1.14", "1.13", "1.12", "1.11"] diff -Nru golang-github-gorilla-csrf-1.7.1/.editorconfig golang-github-gorilla-csrf-1.7.2/.editorconfig --- golang-github-gorilla-csrf-1.7.1/.editorconfig 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.editorconfig 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset \ No newline at end of file diff -Nru golang-github-gorilla-csrf-1.7.1/.github/release-drafter.yml golang-github-gorilla-csrf-1.7.2/.github/release-drafter.yml --- golang-github-gorilla-csrf-1.7.1/.github/release-drafter.yml 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/release-drafter.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -# Config for https://github.com/apps/release-drafter -template: | - - - - ## CHANGELOG - $CHANGES - diff -Nru golang-github-gorilla-csrf-1.7.1/.github/stale.yml golang-github-gorilla-csrf-1.7.2/.github/stale.yml --- golang-github-gorilla-csrf-1.7.1/.github/stale.yml 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/stale.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -daysUntilStale: 60 -daysUntilClose: 7 -# Issues with these labels will never be considered stale -exemptLabels: - - v2 - - needs-review - - work-required -staleLabel: stale -markComment: > - This issue has been automatically marked as stale because it hasn't seen - a recent update. It'll be automatically closed in a few days. -closeComment: false diff -Nru golang-github-gorilla-csrf-1.7.1/.github/workflows/issues.yml golang-github-gorilla-csrf-1.7.2/.github/workflows/issues.yml --- golang-github-gorilla-csrf-1.7.1/.github/workflows/issues.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/workflows/issues.yml 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,21 @@ +# Add all the issues created to the project. +name: Add issue or pull request to Project + +on: + issues: + types: + - opened + pull_request_target: + types: + - opened + - reopened + +jobs: + add-to-project: + runs-on: ubuntu-latest + steps: + - name: Add issue to project + uses: actions/add-to-project@v0.5.0 + with: + project-url: https://github.com/orgs/gorilla/projects/4 + github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }} diff -Nru golang-github-gorilla-csrf-1.7.1/.github/workflows/security.yml golang-github-gorilla-csrf-1.7.2/.github/workflows/security.yml --- golang-github-gorilla-csrf-1.7.1/.github/workflows/security.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/workflows/security.yml 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,37 @@ +name: Security +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + scan: + strategy: + matrix: + go: ['1.20','1.21'] + fail-fast: true + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run GoSec + uses: securego/gosec@master + with: + args: -exclude-dir examples ./... + + - name: Run GoVulnCheck + uses: golang/govulncheck-action@v1 + with: + go-version-input: ${{ matrix.go }} + go-package: ./... diff -Nru golang-github-gorilla-csrf-1.7.1/.github/workflows/test.yml golang-github-gorilla-csrf-1.7.2/.github/workflows/test.yml --- golang-github-gorilla-csrf-1.7.1/.github/workflows/test.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/workflows/test.yml 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,35 @@ +name: Test +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + unit: + strategy: + matrix: + go: ['1.20','1.21'] + os: [ubuntu-latest, macos-latest, windows-latest] + fail-fast: true + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run Tests + run: go test -race -cover -coverprofile=coverage -covermode=atomic -v ./... + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: ./coverage diff -Nru golang-github-gorilla-csrf-1.7.1/.github/workflows/verify.yml golang-github-gorilla-csrf-1.7.2/.github/workflows/verify.yml --- golang-github-gorilla-csrf-1.7.1/.github/workflows/verify.yml 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.github/workflows/verify.yml 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,32 @@ +name: Verify +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + lint: + strategy: + matrix: + go: ['1.20','1.21'] + fail-fast: true + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run GolangCI-Lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.53 + args: --timeout=5m diff -Nru golang-github-gorilla-csrf-1.7.1/.gitignore golang-github-gorilla-csrf-1.7.2/.gitignore --- golang-github-gorilla-csrf-1.7.1/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/.gitignore 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1 @@ +coverage.coverprofile diff -Nru golang-github-gorilla-csrf-1.7.1/AUTHORS golang-github-gorilla-csrf-1.7.2/AUTHORS --- golang-github-gorilla-csrf-1.7.1/AUTHORS 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/AUTHORS 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -# This is the official list of gorilla/csrf authors for copyright purposes. -# Please keep the list sorted. - -adiabatic -Florian D. Loch -Google LLC (https://opensource.google.com) -jamesgroat -Joshua Carp -Kamil Kisiel -Kevin Burke -Kévin Dunglas -Kristoffer Berdal -Martin Angers -Matt Silverlock -Philip I. Thomas -Richard Musiol -Seth Hoenig -Stefano Vettorazzi -Wayne Ashley Berry -田浩浩 -陈东海 diff -Nru golang-github-gorilla-csrf-1.7.1/LICENSE golang-github-gorilla-csrf-1.7.2/LICENSE --- golang-github-gorilla-csrf-1.7.1/LICENSE 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/LICENSE 2023-11-05 02:08:39.000000000 +0000 @@ -1,26 +1,27 @@ -Copyright (c) 2015-2018, The Gorilla Authors. All rights reserved. +Copyright (c) 2023 The Gorilla Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors -may be used to endorse or promote products derived from this software without -specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru golang-github-gorilla-csrf-1.7.1/Makefile golang-github-gorilla-csrf-1.7.2/Makefile --- golang-github-gorilla-csrf-1.7.1/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/Makefile 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,34 @@ +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest + +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: golangci-lint +golangci-lint: + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... + +.PHONY: verify +verify: golangci-lint gosec govulncheck + +.PHONY: test +test: + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... diff -Nru golang-github-gorilla-csrf-1.7.1/README.md golang-github-gorilla-csrf-1.7.2/README.md --- golang-github-gorilla-csrf-1.7.1/README.md 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/README.md 2023-11-05 02:08:39.000000000 +0000 @@ -1,9 +1,12 @@ # gorilla/csrf -[![GoDoc](https://godoc.org/github.com/gorilla/csrf?status.svg)](https://godoc.org/github.com/gorilla/csrf) -[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/csrf/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/csrf?badge) -[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) -[![CircleCI](https://circleci.com/gh/gorilla/csrf.svg?style=svg)](https://circleci.com/gh/gorilla/csrf) +![testing](https://github.com/gorilla/csrf/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/csrf/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/csrf) +[![godoc](https://godoc.org/github.com/gorilla/csrf?status.svg)](https://godoc.org/github.com/gorilla/csrf) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/csrf/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/csrf?badge) + + +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) gorilla/csrf is a HTTP middleware library that provides [cross-site request forgery](http://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/) (CSRF) diff -Nru golang-github-gorilla-csrf-1.7.1/context.go golang-github-gorilla-csrf-1.7.2/context.go --- golang-github-gorilla-csrf-1.7.1/context.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/context.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,26 +1,25 @@ +//go:build go1.7 // +build go1.7 package csrf import ( "context" + "fmt" "net/http" - - "github.com/pkg/errors" ) func contextGet(r *http.Request, key string) (interface{}, error) { val := r.Context().Value(key) if val == nil { - return nil, errors.Errorf("no value exists in the context for key %q", key) + return nil, fmt.Errorf("no value exists in the context for key %q", key) } - return val, nil } func contextSave(r *http.Request, key string, val interface{}) *http.Request { ctx := r.Context() - ctx = context.WithValue(ctx, key, val) + ctx = context.WithValue(ctx, key, val) // nolint:staticcheck return r.WithContext(ctx) } diff -Nru golang-github-gorilla-csrf-1.7.1/csrf.go golang-github-gorilla-csrf-1.7.2/csrf.go --- golang-github-gorilla-csrf-1.7.1/csrf.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/csrf.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,12 +1,11 @@ package csrf import ( + "errors" "fmt" "net/http" "net/url" - "github.com/pkg/errors" - "github.com/gorilla/securecookie" ) @@ -15,8 +14,8 @@ // Context/session keys & prefixes const ( - tokenKey string = "gorilla.csrf.Token" - formKey string = "gorilla.csrf.Form" + tokenKey string = "gorilla.csrf.Token" // #nosec G101 + formKey string = "gorilla.csrf.Form" // #nosec G101 errorKey string = "gorilla.csrf.Error" skipCheckKey string = "gorilla.csrf.Skip" cookieName string = "_gorilla_csrf" @@ -108,6 +107,7 @@ // 'Forbidden' error response. // // Example: +// // package main // // import ( @@ -144,7 +144,6 @@ // // This is useful if you're sending JSON to clients or a front-end JavaScript // // framework. // } -// func Protect(authKey []byte, opts ...Option) func(http.Handler) http.Handler { return func(h http.Handler) http.Handler { cs := parseOptions(h, opts...) @@ -267,7 +266,7 @@ } } - if valid == false { + if !valid { r = envError(r, ErrBadReferer) cs.opts.ErrorHandler.ServeHTTP(w, r) return @@ -315,5 +314,4 @@ http.Error(w, fmt.Sprintf("%s - %s", http.StatusText(http.StatusForbidden), FailureReason(r)), http.StatusForbidden) - return } diff -Nru golang-github-gorilla-csrf-1.7.1/csrf_test.go golang-github-gorilla-csrf-1.7.2/csrf_test.go --- golang-github-gorilla-csrf-1.7.1/csrf_test.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/csrf_test.go 2023-11-05 02:08:39.000000000 +0000 @@ -153,7 +153,7 @@ p := Protect(testKey)(s) var token string - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { token = Token(r) })) @@ -238,7 +238,7 @@ p := Protect(testKey)(s) var token string - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { token = Token(r) })) @@ -294,7 +294,7 @@ p := Protect(testKey, TrustedOrigins(item.trustedOrigin))(s) var token string - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { token = Token(r) })) @@ -342,7 +342,7 @@ p := Protect(testKey)(s) var token string - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { token = Token(r) })) @@ -379,12 +379,12 @@ var finalErr error s := http.NewServeMux() - p := Protect(testKey, ErrorHandler(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + p := Protect(testKey, ErrorHandler(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { finalErr = FailureReason(r) })))(s) var token string - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { token = Token(r) })) diff -Nru golang-github-gorilla-csrf-1.7.1/debian/changelog golang-github-gorilla-csrf-1.7.2/debian/changelog --- golang-github-gorilla-csrf-1.7.1/debian/changelog 2023-10-23 18:38:10.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/debian/changelog 2024-01-01 17:25:53.000000000 +0000 @@ -1,8 +1,15 @@ -golang-github-gorilla-csrf (1.7.1-1~bpo2204+1) jammy-backports; urgency=medium +golang-github-gorilla-csrf (1.7.2-1~bpo22.04+1) jammy; urgency=medium - * Rebuild for jammy-backports. + * Rebuild for jammy. - -- Mateusz Łukasik Mon, 23 Oct 2023 20:38:10 +0200 + -- Mateusz Łukasik Mon, 01 Jan 2024 18:25:53 +0100 + +golang-github-gorilla-csrf (1.7.2-1) unstable; urgency=medium + + * New upstream version 1.7.2 + * Update versioned dependencies as per go.mod + + -- Anthony Fok Fri, 08 Dec 2023 23:36:30 -0700 golang-github-gorilla-csrf (1.7.1-1) unstable; urgency=medium diff -Nru golang-github-gorilla-csrf-1.7.1/debian/control golang-github-gorilla-csrf-1.7.2/debian/control --- golang-github-gorilla-csrf-1.7.1/debian/control 2023-03-13 13:33:24.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/debian/control 2023-12-09 06:35:54.000000000 +0000 @@ -6,9 +6,8 @@ Rules-Requires-Root: no Build-Depends: debhelper-compat (= 13), dh-sequence-golang, - golang-any, - golang-github-gorilla-securecookie-dev, - golang-github-pkg-errors-dev (>= 0.9.1) + golang-any (>= 2:1.20~), + golang-github-gorilla-securecookie-dev (>= 1.1.2), Testsuite: autopkgtest-pkg-go Standards-Version: 4.6.2 Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-github-gorilla-csrf @@ -20,8 +19,7 @@ Architecture: all Multi-Arch: foreign Depends: ${misc:Depends}, - golang-github-gorilla-securecookie-dev, - golang-github-pkg-errors-dev (>= 0.9.1) + golang-github-gorilla-securecookie-dev (>= 1.1.2), Description: Cross Site Request Forgery (CSRF) prevention middleware for Go gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes: diff -Nru golang-github-gorilla-csrf-1.7.1/examples/api-backends/README.md golang-github-gorilla-csrf-1.7.2/examples/api-backends/README.md --- golang-github-gorilla-csrf-1.7.1/examples/api-backends/README.md 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/api-backends/README.md 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,11 @@ +# API Backends + +Examples in this directory are intended to provide basic working backend CSRF-protected APIs, +compatible with the JavaScript frontend examples available in the +[`examples/javascript-frontends`](../javascript-frontends). + +In addition to CSRF protection, these backends provide the CORS configuration required for +communicating the CSRF cookies and headers with JavaScript client code running in the browser. + +See [`examples/javascript-frontends`](../javascript-frontends/README.md) for details on CORS and +CSRF configuration compatibility requirements. diff -Nru golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/go.mod golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/go.mod --- golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/go.mod 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/go.mod 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,17 @@ +// +build ignore + +module github.com/gorilla-mux/examples/api-backends/gorilla-mux + +go 1.20 + +require ( + github.com/gorilla/csrf v1.7.1 + github.com/gorilla/handlers v1.5.1 + github.com/gorilla/mux v1.8.0 +) + +require ( + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect +) diff -Nru golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/go.sum golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/go.sum --- golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/go.sum 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/go.sum 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,13 @@ +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/gorilla/csrf v1.7.1 h1:Ir3o2c1/Uzj6FBxMlAUB6SivgVMy1ONXwYgXn+/aHPE= +github.com/gorilla/csrf v1.7.1/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff -Nru golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/main.go golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/main.go --- golang-github-gorilla-csrf-1.7.1/examples/api-backends/gorilla-mux/main.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/api-backends/gorilla-mux/main.go 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,66 @@ +// +build ignore + +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "strings" + "time" + + "github.com/gorilla/csrf" + "github.com/gorilla/handlers" + "github.com/gorilla/mux" +) + +func main() { + router := mux.NewRouter() + + loggingMiddleware := func(h http.Handler) http.Handler { + return handlers.LoggingHandler(os.Stdout, h) + } + router.Use(loggingMiddleware) + + CSRFMiddleware := csrf.Protect( + []byte("place-your-32-byte-long-key-here"), + csrf.Secure(false), // false in development only! + csrf.RequestHeader("X-CSRF-Token"), // Must be in CORS Allowed and Exposed Headers + ) + + APIRouter := router.PathPrefix("/api").Subrouter() + APIRouter.Use(CSRFMiddleware) + APIRouter.HandleFunc("", Get).Methods(http.MethodGet) + APIRouter.HandleFunc("", Post).Methods(http.MethodPost) + + CORSMiddleware := handlers.CORS( + handlers.AllowCredentials(), + handlers.AllowedOriginValidator( + func(origin string) bool { + return strings.HasPrefix(origin, "http://localhost") + }, + ), + handlers.AllowedHeaders([]string{"X-CSRF-Token"}), + handlers.ExposedHeaders([]string{"X-CSRF-Token"}), + ) + + server := &http.Server{ + Handler: CORSMiddleware(router), + Addr: "localhost:8080", + ReadTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + } + + fmt.Println("starting http server on localhost:8080") + log.Panic(server.ListenAndServe()) +} + +func Get(w http.ResponseWriter, r *http.Request) { + w.Header().Add("X-CSRF-Token", csrf.Token(r)) + w.WriteHeader(http.StatusOK) +} + +func Post(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/README.md golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/README.md --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/README.md 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/README.md 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,19 @@ +# JavaScript Frontends + +Examples in this directory are intended to provide basic working frontend JavaScript, compatible +with the API backend examples available in the [`examples/api-backends`](../api-backends). + +## CSRF and CORS compatibility + +In order to be compatible with a CSRF-protected backend, frontend clients must: + +1. Be served from a domain allowed by the backend's CORS Allowed Origins configuration. + 1. `http://localhost*` for the backend examples provided + 2. An example server to serve the HTML and JavaScript for the frontend examples from localhost is included in + [`examples/javascript-frontends/example-frontend-server`](../javascript-frontends/example-frontend-server) +3. Use the HTTP headers expected by the backend to send and receive CSRF Tokens. + The backends configure this as the Gorilla `csrf.RequestHeader`, + as well as the CORS Allowed Headers and Exposed Headers. + 1. `X-CSRF-Token` for the backend examples provided + 2. Note that some JavaScript HTTP clients automatically lowercase all received headers, + so the values must be accessed with the key `"x-csrf-token"` in the frontend code. diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/go.mod golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/go.mod --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/go.mod 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/go.mod 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,10 @@ +module github.com/gorilla-mux/examples/javascript-frontends/example-frontend-server + +go 1.20 + +require ( + github.com/gorilla/handlers v1.5.1 + github.com/gorilla/mux v1.8.0 +) + +require github.com/felixge/httpsnoop v1.0.3 // indirect diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/go.sum golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/go.sum --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/go.sum 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/go.sum 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,7 @@ +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/main.go golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/main.go --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/example-frontend-server/main.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/example-frontend-server/main.go 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,42 @@ +// +build ignore + +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "time" + + "github.com/gorilla/handlers" + "github.com/gorilla/mux" +) + +func main() { + router := mux.NewRouter() + + loggingMiddleware := func(h http.Handler) http.Handler { + return handlers.LoggingHandler(os.Stdout, h) + } + router.Use(loggingMiddleware) + + wd, err := os.Getwd() + if err != nil { + log.Panic(err) + } + // change this directory to point at a different Javascript frontend to serve + httpStaticAssetsDir := http.Dir(fmt.Sprintf("%s/../frontends/axios/", wd)) + + router.PathPrefix("/").Handler(http.FileServer(httpStaticAssetsDir)) + + server := &http.Server{ + Handler: router, + Addr: "localhost:8081", + ReadTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + } + + fmt.Println("starting http server on localhost:8081") + log.Panic(server.ListenAndServe()) +} diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/frontends/axios/index.html golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/frontends/axios/index.html --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/frontends/axios/index.html 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/frontends/axios/index.html 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + Gorilla CSRF + + + +
+

Gorilla CSRF: Axios JS Frontend

+

See Console and Network tabs of your browser's Developer Tools for further details

+
+ +
+

Get Request:

+

Full Response:

+ +

CSRF Token:

+ +
+ + +
+

Post Request:

+

Full Response:

+

+ Note that the X-CSRF-Token value is in the Axios config.headers; + it is not a response header set by the server. +

+ +
+ + + \ No newline at end of file diff -Nru golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/frontends/axios/index.js golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/frontends/axios/index.js --- golang-github-gorilla-csrf-1.7.1/examples/javascript-frontends/frontends/axios/index.js 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/examples/javascript-frontends/frontends/axios/index.js 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,50 @@ +// make GET request to backend on page load in order to obtain +// a CSRF Token and load it into the Axios instance's headers +// https://github.com/axios/axios#creating-an-instance +const initializeAxiosInstance = async (url) => { + try { + let resp = await axios.get(url, {withCredentials: true}); + console.log(resp); + document.getElementById("get-request-full-response").innerHTML = JSON.stringify(resp); + + let csrfToken = parseCSRFToken(resp); + console.log(csrfToken); + document.getElementById("get-response-csrf-token").innerHTML = csrfToken; + + return axios.create({ + // withCredentials must be true to in order for the browser + // to send cookies, which are necessary for CSRF verification + withCredentials: true, + headers: {"X-CSRF-Token": csrfToken} + }); + } catch (err) { + console.log(err); + } +}; + +const post = async (axiosInstance, url) => { + try { + let resp = await axiosInstance.post(url); + console.log(resp); + document.getElementById("post-request-full-response").innerHTML = JSON.stringify(resp); + } catch (err) { + console.log(err); + } +}; + +// general-purpose func to deal with clients like Axios, +// which lowercase all headers received from the server response +const parseCSRFToken = (resp) => { + let csrfToken = resp.headers[csrfTokenHeader]; + if (!csrfToken) { + csrfToken = resp.headers[csrfTokenHeader.toLowerCase()]; + } + return csrfToken +} + +const url = "http://localhost:8080/api"; +const csrfTokenHeader = "X-CSRF-Token"; +initializeAxiosInstance(url) + .then(axiosInstance => { + post(axiosInstance, url); + }); diff -Nru golang-github-gorilla-csrf-1.7.1/go.mod golang-github-gorilla-csrf-1.7.2/go.mod --- golang-github-gorilla-csrf-1.7.1/go.mod 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/go.mod 2023-11-05 02:08:39.000000000 +0000 @@ -1,8 +1,5 @@ module github.com/gorilla/csrf -require ( - github.com/gorilla/securecookie v1.1.1 - github.com/pkg/errors v0.9.1 -) +require github.com/gorilla/securecookie v1.1.2 -go 1.13 +go 1.20 diff -Nru golang-github-gorilla-csrf-1.7.1/go.sum golang-github-gorilla-csrf-1.7.2/go.sum --- golang-github-gorilla-csrf-1.7.1/go.sum 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/go.sum 2023-11-05 02:08:39.000000000 +0000 @@ -1,6 +1,3 @@ -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= diff -Nru golang-github-gorilla-csrf-1.7.1/helpers.go golang-github-gorilla-csrf-1.7.2/helpers.go --- golang-github-gorilla-csrf-1.7.1/helpers.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/helpers.go 2023-11-05 02:08:39.000000000 +0000 @@ -51,18 +51,17 @@ // // Example: // -// // The following tag in our form.tmpl template: -// {{ .csrfField }} -// -// // ... becomes: -// +// // The following tag in our form.tmpl template: +// {{ .csrfField }} // +// // ... becomes: +// func TemplateField(r *http.Request) template.HTML { if name, err := contextGet(r, formKey); err == nil { fragment := fmt.Sprintf(``, name, Token(r)) - return template.HTML(fragment) + return template.HTML(fragment) // #nosec G203 } return template.HTML("") @@ -75,7 +74,7 @@ // token and returning them together as a 64-byte slice. This effectively // randomises the token on a per-request basis without breaking multiple browser // tabs/windows. -func mask(realToken []byte, r *http.Request) string { +func mask(realToken []byte, _ *http.Request) string { otp, err := generateRandomBytes(tokenLength) if err != nil { return "" diff -Nru golang-github-gorilla-csrf-1.7.1/helpers_test.go golang-github-gorilla-csrf-1.7.2/helpers_test.go --- golang-github-gorilla-csrf-1.7.1/helpers_test.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/helpers_test.go 2023-11-05 02:08:39.000000000 +0000 @@ -6,6 +6,7 @@ "encoding/base64" "fmt" "io" + "log" "mime/multipart" "net/http" "net/http/httptest" @@ -34,9 +35,12 @@ s.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token = Token(r) t := template.Must((template.New("base").Parse(testTemplate))) - t.Execute(w, map[string]interface{}{ + err := t.Execute(w, map[string]interface{}{ TemplateTag: TemplateField(r), }) + if err != nil { + log.Printf("errored during executing the template: %v", err) + } })) r, err := http.NewRequest("GET", "/", nil) @@ -71,9 +75,12 @@ s.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token = Token(r) t := template.Must((template.New("base").Parse(testTemplate))) - t.Execute(w, map[string]interface{}{ + err := t.Execute(w, map[string]interface{}{ TemplateTag: TemplateField(r), }) + if err != nil { + log.Printf("errored during executing the template: %v", err) + } })) r, err := http.NewRequest("GET", "/", nil) @@ -93,7 +100,11 @@ t.Fatal(err) } - wr.Write([]byte(token)) + _, err = wr.Write([]byte(token)) + if err != nil { + t.Fatal(err) + } + mp.Close() r, err = http.NewRequest("POST", "http://www.gorillatoolkit.org/", &b) @@ -185,7 +196,7 @@ for _, token := range testTokens { if res := xorToken(token.a, token.b); res != nil { - if bytes.Compare(res, token.expected) != 0 { + if !bytes.Equal(res, token.expected) { t.Fatalf("xorBytes failed to return the expected result: got %v want %v", res, token.expected) } @@ -226,9 +237,12 @@ token = Token(r) templateField = string(TemplateField(r)) t := template.Must((template.New("base").Parse(testTemplate))) - t.Execute(w, map[string]interface{}{ + err := t.Execute(w, map[string]interface{}{ TemplateTag: TemplateField(r), }) + if err != nil { + log.Printf("errored during executing the template: %v", err) + } })) testFieldName := "custom_field_name" @@ -280,7 +294,7 @@ var teapot = 418 // Issue a POST request without a CSRF token in the request. - s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { // Set a non-200 header to make the test explicit. w.WriteHeader(teapot) })) diff -Nru golang-github-gorilla-csrf-1.7.1/store.go golang-github-gorilla-csrf-1.7.2/store.go --- golang-github-gorilla-csrf-1.7.1/store.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/store.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,3 +1,4 @@ +//go:build go1.11 // +build go1.11 package csrf diff -Nru golang-github-gorilla-csrf-1.7.1/store_legacy.go golang-github-gorilla-csrf-1.7.2/store_legacy.go --- golang-github-gorilla-csrf-1.7.1/store_legacy.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/store_legacy.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,4 +1,6 @@ +//go:build !go1.11 // +build !go1.11 + // file for compatibility with go versions prior to 1.11 package csrf diff -Nru golang-github-gorilla-csrf-1.7.1/store_legacy_test.go golang-github-gorilla-csrf-1.7.2/store_legacy_test.go --- golang-github-gorilla-csrf-1.7.1/store_legacy_test.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/store_legacy_test.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,17 +1,18 @@ +//go:build !go1.11 // +build !go1.11 + // file for compatibility with go versions prior to 1.11 package csrf import ( + "errors" "fmt" "net/http" "net/http/httptest" "strings" "testing" - "github.com/pkg/errors" - "github.com/gorilla/securecookie" ) diff -Nru golang-github-gorilla-csrf-1.7.1/store_test.go golang-github-gorilla-csrf-1.7.2/store_test.go --- golang-github-gorilla-csrf-1.7.1/store_test.go 2021-07-29 15:50:12.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/store_test.go 2023-11-05 02:08:39.000000000 +0000 @@ -1,16 +1,16 @@ +//go:build go1.11 // +build go1.11 package csrf import ( + "errors" "fmt" "net/http" "net/http/httptest" "strings" "testing" - "github.com/pkg/errors" - "github.com/gorilla/securecookie" ) @@ -19,7 +19,7 @@ // brokenSaveStore is a CSRF store that cannot, well, save. type brokenSaveStore struct { - store + store // nolint:unused } func (bs *brokenSaveStore) Get(*http.Request) ([]byte, error) { diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/.editorconfig golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/.editorconfig --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/.editorconfig 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/.editorconfig 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/.gitignore golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/.gitignore --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/.gitignore 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1 @@ +coverage.coverprofile diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/LICENSE golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/LICENSE --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/LICENSE 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,27 @@ +Copyright (c) 2023 The Gorilla Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/Makefile golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/Makefile --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/Makefile 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,39 @@ +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest + +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: golangci-lint +golangci-lint: + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... + +.PHONY: verify +verify: golangci-lint gosec govulncheck + +.PHONY: test +test: + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... + +.PHONY: fuzz +fuzz: + @echo "##### Running fuzz tests" + go test -v -fuzz FuzzEncodeDecode -fuzztime 60s diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/README.md golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/README.md --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/README.md 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/README.md 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,144 @@ +# gorilla/securecookie + +![testing](https://github.com/gorilla/securecookie/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/securecookie/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/securecookie) +[![godoc](https://godoc.org/github.com/gorilla/securecookie?status.svg)](https://godoc.org/github.com/gorilla/securecookie) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/securecookie/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/securecookie?badge) + +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) + +securecookie encodes and decodes authenticated and optionally encrypted +cookie values. + +Secure cookies can't be forged, because their values are validated using HMAC. +When encrypted, the content is also inaccessible to malicious eyes. It is still +recommended that sensitive data not be stored in cookies, and that HTTPS be used +to prevent cookie [replay attacks](https://en.wikipedia.org/wiki/Replay_attack). + +## Examples + +To use it, first create a new SecureCookie instance: + +```go +// Hash keys should be at least 32 bytes long +var hashKey = []byte("very-secret") +// Block keys should be 16 bytes (AES-128) or 32 bytes (AES-256) long. +// Shorter keys may weaken the encryption used. +var blockKey = []byte("a-lot-secret") +var s = securecookie.New(hashKey, blockKey) +``` + +The hashKey is required, used to authenticate the cookie value using HMAC. +It is recommended to use a key with 32 or 64 bytes. + +The blockKey is optional, used to encrypt the cookie value -- set it to nil +to not use encryption. If set, the length must correspond to the block size +of the encryption algorithm. For AES, used by default, valid lengths are +16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. + +Strong keys can be created using the convenience function +`GenerateRandomKey()`. Note that keys created using `GenerateRandomKey()` are not +automatically persisted. New keys will be created when the application is +restarted, and previously issued cookies will not be able to be decoded. + +Once a SecureCookie instance is set, use it to encode a cookie value: + +```go +func SetCookieHandler(w http.ResponseWriter, r *http.Request) { + value := map[string]string{ + "foo": "bar", + } + if encoded, err := s.Encode("cookie-name", value); err == nil { + cookie := &http.Cookie{ + Name: "cookie-name", + Value: encoded, + Path: "/", + Secure: true, + HttpOnly: true, + } + http.SetCookie(w, cookie) + } +} +``` + +Later, use the same SecureCookie instance to decode and validate a cookie +value: + +```go +func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { + if cookie, err := r.Cookie("cookie-name"); err == nil { + value := make(map[string]string) + if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { + fmt.Fprintf(w, "The value of foo is %q", value["foo"]) + } + } +} +``` + +We stored a map[string]string, but secure cookies can hold any value that +can be encoded using `encoding/gob`. To store custom types, they must be +registered first using gob.Register(). For basic types this is not needed; +it works out of the box. An optional JSON encoder that uses `encoding/json` is +available for types compatible with JSON. + +### Key Rotation +Rotating keys is an important part of any security strategy. The `EncodeMulti` and +`DecodeMulti` functions allow for multiple keys to be rotated in and out. +For example, let's take a system that stores keys in a map: + +```go +// keys stored in a map will not be persisted between restarts +// a more persistent storage should be considered for production applications. +var cookies = map[string]*securecookie.SecureCookie{ + "previous": securecookie.New( + securecookie.GenerateRandomKey(64), + securecookie.GenerateRandomKey(32), + ), + "current": securecookie.New( + securecookie.GenerateRandomKey(64), + securecookie.GenerateRandomKey(32), + ), +} +``` + +Using the current key to encode new cookies: +```go +func SetCookieHandler(w http.ResponseWriter, r *http.Request) { + value := map[string]string{ + "foo": "bar", + } + if encoded, err := securecookie.EncodeMulti("cookie-name", value, cookies["current"]); err == nil { + cookie := &http.Cookie{ + Name: "cookie-name", + Value: encoded, + Path: "/", + } + http.SetCookie(w, cookie) + } +} +``` + +Later, decode cookies. Check against all valid keys: +```go +func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { + if cookie, err := r.Cookie("cookie-name"); err == nil { + value := make(map[string]string) + err = securecookie.DecodeMulti("cookie-name", cookie.Value, &value, cookies["current"], cookies["previous"]) + if err == nil { + fmt.Fprintf(w, "The value of foo is %q", value["foo"]) + } + } +} +``` + +Rotate the keys. This strategy allows previously issued cookies to be valid until the next rotation: +```go +func Rotate(newCookie *securecookie.SecureCookie) { + cookies["previous"] = cookies["current"] + cookies["current"] = newCookie +} +``` + +## License + +BSD licensed. See the LICENSE file for details. diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/doc.go golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/doc.go --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/doc.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/doc.go 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,61 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package securecookie encodes and decodes authenticated and optionally +encrypted cookie values. + +Secure cookies can't be forged, because their values are validated using HMAC. +When encrypted, the content is also inaccessible to malicious eyes. + +To use it, first create a new SecureCookie instance: + + var hashKey = []byte("very-secret") + var blockKey = []byte("a-lot-secret") + var s = securecookie.New(hashKey, blockKey) + +The hashKey is required, used to authenticate the cookie value using HMAC. +It is recommended to use a key with 32 or 64 bytes. + +The blockKey is optional, used to encrypt the cookie value -- set it to nil +to not use encryption. If set, the length must correspond to the block size +of the encryption algorithm. For AES, used by default, valid lengths are +16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. + +Strong keys can be created using the convenience function GenerateRandomKey(). + +Once a SecureCookie instance is set, use it to encode a cookie value: + + func SetCookieHandler(w http.ResponseWriter, r *http.Request) { + value := map[string]string{ + "foo": "bar", + } + if encoded, err := s.Encode("cookie-name", value); err == nil { + cookie := &http.Cookie{ + Name: "cookie-name", + Value: encoded, + Path: "/", + } + http.SetCookie(w, cookie) + } + } + +Later, use the same SecureCookie instance to decode and validate a cookie +value: + + func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { + if cookie, err := r.Cookie("cookie-name"); err == nil { + value := make(map[string]string) + if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { + fmt.Fprintf(w, "The value of foo is %q", value["foo"]) + } + } + } + +We stored a map[string]string, but secure cookies can hold any value that +can be encoded using encoding/gob. To store custom types, they must be +registered first using gob.Register(). For basic types this is not needed; +it works out of the box. +*/ +package securecookie diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/securecookie.go golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/securecookie.go --- golang-github-gorilla-csrf-1.7.1/vendor/github.com/gorilla/securecookie/securecookie.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/github.com/gorilla/securecookie/securecookie.go 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,649 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package securecookie + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "crypto/subtle" + "encoding/base64" + "encoding/gob" + "encoding/json" + "fmt" + "hash" + "io" + "strconv" + "strings" + "time" +) + +// Error is the interface of all errors returned by functions in this library. +type Error interface { + error + + // IsUsage returns true for errors indicating the client code probably + // uses this library incorrectly. For example, the client may have + // failed to provide a valid hash key, or may have failed to configure + // the Serializer adequately for encoding value. + IsUsage() bool + + // IsDecode returns true for errors indicating that a cookie could not + // be decoded and validated. Since cookies are usually untrusted + // user-provided input, errors of this type should be expected. + // Usually, the proper action is simply to reject the request. + IsDecode() bool + + // IsInternal returns true for unexpected errors occurring in the + // securecookie implementation. + IsInternal() bool + + // Cause, if it returns a non-nil value, indicates that this error was + // propagated from some underlying library. If this method returns nil, + // this error was raised directly by this library. + // + // Cause is provided principally for debugging/logging purposes; it is + // rare that application logic should perform meaningfully different + // logic based on Cause. See, for example, the caveats described on + // (MultiError).Cause(). + Cause() error +} + +// errorType is a bitmask giving the error type(s) of an cookieError value. +type errorType int + +const ( + usageError = errorType(1 << iota) + decodeError + internalError +) + +type cookieError struct { + typ errorType + msg string + cause error +} + +func (e cookieError) IsUsage() bool { return (e.typ & usageError) != 0 } +func (e cookieError) IsDecode() bool { return (e.typ & decodeError) != 0 } +func (e cookieError) IsInternal() bool { return (e.typ & internalError) != 0 } + +func (e cookieError) Cause() error { return e.cause } + +func (e cookieError) Error() string { + parts := []string{"securecookie: "} + if e.msg == "" { + parts = append(parts, "error") + } else { + parts = append(parts, e.msg) + } + if c := e.Cause(); c != nil { + parts = append(parts, " - caused by: ", c.Error()) + } + return strings.Join(parts, "") +} + +var ( + errGeneratingIV = cookieError{typ: internalError, msg: "failed to generate random iv"} + + errNoCodecs = cookieError{typ: usageError, msg: "no codecs provided"} + errHashKeyNotSet = cookieError{typ: usageError, msg: "hash key is not set"} + errBlockKeyNotSet = cookieError{typ: usageError, msg: "block key is not set"} + errEncodedValueTooLong = cookieError{typ: usageError, msg: "the value is too long"} + + errValueToDecodeTooLong = cookieError{typ: decodeError, msg: "the value is too long"} + errTimestampInvalid = cookieError{typ: decodeError, msg: "invalid timestamp"} + errTimestampTooNew = cookieError{typ: decodeError, msg: "timestamp is too new"} + errTimestampExpired = cookieError{typ: decodeError, msg: "expired timestamp"} + errDecryptionFailed = cookieError{typ: decodeError, msg: "the value could not be decrypted"} + errValueNotByte = cookieError{typ: decodeError, msg: "value not a []byte."} + errValueNotBytePtr = cookieError{typ: decodeError, msg: "value not a pointer to []byte."} + + // ErrMacInvalid indicates that cookie decoding failed because the HMAC + // could not be extracted and verified. Direct use of this error + // variable is deprecated; it is public only for legacy compatibility, + // and may be privatized in the future, as it is rarely useful to + // distinguish between this error and other Error implementations. + ErrMacInvalid = cookieError{typ: decodeError, msg: "the value is not valid"} +) + +// Codec defines an interface to encode and decode cookie values. +type Codec interface { + Encode(name string, value interface{}) (string, error) + Decode(name, value string, dst interface{}) error +} + +// New returns a new SecureCookie. +// +// hashKey is required, used to authenticate values using HMAC. Create it using +// GenerateRandomKey(). It is recommended to use a key with 32 or 64 bytes. +// +// blockKey is optional, used to encrypt values. Create it using +// GenerateRandomKey(). The key length must correspond to the key size +// of the encryption algorithm. For AES, used by default, valid lengths are +// 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. +// The default encoder used for cookie serialization is encoding/gob. +// +// Note that keys created using GenerateRandomKey() are not automatically +// persisted. New keys will be created when the application is restarted, and +// previously issued cookies will not be able to be decoded. +func New(hashKey, blockKey []byte) *SecureCookie { + s := &SecureCookie{ + hashKey: hashKey, + blockKey: blockKey, + hashFunc: sha256.New, + maxAge: 86400 * 30, + maxLength: 4096, + sz: GobEncoder{}, + } + if len(hashKey) == 0 { + s.err = errHashKeyNotSet + } + if blockKey != nil { + s.BlockFunc(aes.NewCipher) + } + return s +} + +// SecureCookie encodes and decodes authenticated and optionally encrypted +// cookie values. +type SecureCookie struct { + hashKey []byte + hashFunc func() hash.Hash + blockKey []byte + block cipher.Block + maxLength int + maxAge int64 + minAge int64 + err error + sz Serializer + // For testing purposes, the function that returns the current timestamp. + // If not set, it will use time.Now().UTC().Unix(). + timeFunc func() int64 +} + +// Serializer provides an interface for providing custom serializers for cookie +// values. +type Serializer interface { + Serialize(src interface{}) ([]byte, error) + Deserialize(src []byte, dst interface{}) error +} + +// GobEncoder encodes cookie values using encoding/gob. This is the simplest +// encoder and can handle complex types via gob.Register. +type GobEncoder struct{} + +// JSONEncoder encodes cookie values using encoding/json. Users who wish to +// encode complex types need to satisfy the json.Marshaller and +// json.Unmarshaller interfaces. +type JSONEncoder struct{} + +// NopEncoder does not encode cookie values, and instead simply accepts a []byte +// (as an interface{}) and returns a []byte. This is particularly useful when +// you encoding an object upstream and do not wish to re-encode it. +type NopEncoder struct{} + +// MaxLength restricts the maximum length, in bytes, for the cookie value. +// +// Default is 4096, which is the maximum value accepted by Internet Explorer. +func (s *SecureCookie) MaxLength(value int) *SecureCookie { + s.maxLength = value + return s +} + +// MaxAge restricts the maximum age, in seconds, for the cookie value. +// +// Default is 86400 * 30. Set it to 0 for no restriction. +func (s *SecureCookie) MaxAge(value int) *SecureCookie { + s.maxAge = int64(value) + return s +} + +// MinAge restricts the minimum age, in seconds, for the cookie value. +// +// Default is 0 (no restriction). +func (s *SecureCookie) MinAge(value int) *SecureCookie { + s.minAge = int64(value) + return s +} + +// HashFunc sets the hash function used to create HMAC. +// +// Default is crypto/sha256.New. +func (s *SecureCookie) HashFunc(f func() hash.Hash) *SecureCookie { + s.hashFunc = f + return s +} + +// BlockFunc sets the encryption function used to create a cipher.Block. +// +// Default is crypto/aes.New. +func (s *SecureCookie) BlockFunc(f func([]byte) (cipher.Block, error)) *SecureCookie { + if s.blockKey == nil { + s.err = errBlockKeyNotSet + } else if block, err := f(s.blockKey); err == nil { + s.block = block + } else { + s.err = cookieError{cause: err, typ: usageError} + } + return s +} + +// Encoding sets the encoding/serialization method for cookies. +// +// Default is encoding/gob. To encode special structures using encoding/gob, +// they must be registered first using gob.Register(). +func (s *SecureCookie) SetSerializer(sz Serializer) *SecureCookie { + s.sz = sz + + return s +} + +// Encode encodes a cookie value. +// +// It serializes, optionally encrypts, signs with a message authentication code, +// and finally encodes the value. +// +// The name argument is the cookie name. It is stored with the encoded value. +// The value argument is the value to be encoded. It can be any value that can +// be encoded using the currently selected serializer; see SetSerializer(). +// +// It is the client's responsibility to ensure that value, when encoded using +// the current serialization/encryption settings on s and then base64-encoded, +// is shorter than the maximum permissible length. +func (s *SecureCookie) Encode(name string, value interface{}) (string, error) { + if s.err != nil { + return "", s.err + } + if s.hashKey == nil { + s.err = errHashKeyNotSet + return "", s.err + } + var err error + var b []byte + // 1. Serialize. + if b, err = s.sz.Serialize(value); err != nil { + return "", cookieError{cause: err, typ: usageError} + } + // 2. Encrypt (optional). + if s.block != nil { + if b, err = encrypt(s.block, b); err != nil { + return "", cookieError{cause: err, typ: usageError} + } + } + b = encode(b) + // 3. Create MAC for "name|date|value". Extra pipe to be used later. + b = []byte(fmt.Sprintf("%s|%d|%s|", name, s.timestamp(), b)) + mac := createMac(hmac.New(s.hashFunc, s.hashKey), b[:len(b)-1]) + // Append mac, remove name. + b = append(b, mac...)[len(name)+1:] + // 4. Encode to base64. + b = encode(b) + // 5. Check length. + if s.maxLength != 0 && len(b) > s.maxLength { + return "", fmt.Errorf("%s: %d", errEncodedValueTooLong, len(b)) + } + // Done. + return string(b), nil +} + +// Decode decodes a cookie value. +// +// It decodes, verifies a message authentication code, optionally decrypts and +// finally deserializes the value. +// +// The name argument is the cookie name. It must be the same name used when +// it was stored. The value argument is the encoded cookie value. The dst +// argument is where the cookie will be decoded. It must be a pointer. +func (s *SecureCookie) Decode(name, value string, dst interface{}) error { + if s.err != nil { + return s.err + } + if s.hashKey == nil { + s.err = errHashKeyNotSet + return s.err + } + // 1. Check length. + if s.maxLength != 0 && len(value) > s.maxLength { + return fmt.Errorf("%s: %d", errValueToDecodeTooLong, len(value)) + } + // 2. Decode from base64. + b, err := decode([]byte(value)) + if err != nil { + return err + } + // 3. Verify MAC. Value is "date|value|mac". + parts := bytes.SplitN(b, []byte("|"), 3) + if len(parts) != 3 { + return ErrMacInvalid + } + h := hmac.New(s.hashFunc, s.hashKey) + b = append([]byte(name+"|"), b[:len(b)-len(parts[2])-1]...) + if err = verifyMac(h, b, parts[2]); err != nil { + return err + } + // 4. Verify date ranges. + var t1 int64 + if t1, err = strconv.ParseInt(string(parts[0]), 10, 64); err != nil { + return errTimestampInvalid + } + t2 := s.timestamp() + if s.minAge != 0 && t1 > t2-s.minAge { + return errTimestampTooNew + } + if s.maxAge != 0 && t1 < t2-s.maxAge { + return errTimestampExpired + } + // 5. Decrypt (optional). + b, err = decode(parts[1]) + if err != nil { + return err + } + if s.block != nil { + if b, err = decrypt(s.block, b); err != nil { + return err + } + } + // 6. Deserialize. + if err = s.sz.Deserialize(b, dst); err != nil { + return cookieError{cause: err, typ: decodeError} + } + // Done. + return nil +} + +// timestamp returns the current timestamp, in seconds. +// +// For testing purposes, the function that generates the timestamp can be +// overridden. If not set, it will return time.Now().UTC().Unix(). +func (s *SecureCookie) timestamp() int64 { + if s.timeFunc == nil { + return time.Now().UTC().Unix() + } + return s.timeFunc() +} + +// Authentication ------------------------------------------------------------- + +// createMac creates a message authentication code (MAC). +func createMac(h hash.Hash, value []byte) []byte { + h.Write(value) + return h.Sum(nil) +} + +// verifyMac verifies that a message authentication code (MAC) is valid. +func verifyMac(h hash.Hash, value []byte, mac []byte) error { + mac2 := createMac(h, value) + // Check that both MACs are of equal length, as subtle.ConstantTimeCompare + // does not do this prior to Go 1.4. + if len(mac) == len(mac2) && subtle.ConstantTimeCompare(mac, mac2) == 1 { + return nil + } + return ErrMacInvalid +} + +// Encryption ----------------------------------------------------------------- + +// encrypt encrypts a value using the given block in counter mode. +// +// A random initialization vector ( https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Initialization_vector_(IV) ) with the length of the +// block size is prepended to the resulting ciphertext. +func encrypt(block cipher.Block, value []byte) ([]byte, error) { + iv := GenerateRandomKey(block.BlockSize()) + if iv == nil { + return nil, errGeneratingIV + } + // Encrypt it. + stream := cipher.NewCTR(block, iv) + stream.XORKeyStream(value, value) + // Return iv + ciphertext. + return append(iv, value...), nil +} + +// decrypt decrypts a value using the given block in counter mode. +// +// The value to be decrypted must be prepended by a initialization vector +// ( https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Initialization_vector_(IV) ) with the length of the block size. +func decrypt(block cipher.Block, value []byte) ([]byte, error) { + size := block.BlockSize() + if len(value) > size { + // Extract iv. + iv := value[:size] + // Extract ciphertext. + value = value[size:] + // Decrypt it. + stream := cipher.NewCTR(block, iv) + stream.XORKeyStream(value, value) + return value, nil + } + return nil, errDecryptionFailed +} + +// Serialization -------------------------------------------------------------- + +// Serialize encodes a value using gob. +func (e GobEncoder) Serialize(src interface{}) ([]byte, error) { + buf := new(bytes.Buffer) + enc := gob.NewEncoder(buf) + if err := enc.Encode(src); err != nil { + return nil, cookieError{cause: err, typ: usageError} + } + return buf.Bytes(), nil +} + +// Deserialize decodes a value using gob. +func (e GobEncoder) Deserialize(src []byte, dst interface{}) error { + dec := gob.NewDecoder(bytes.NewBuffer(src)) + if err := dec.Decode(dst); err != nil { + return cookieError{cause: err, typ: decodeError} + } + return nil +} + +// Serialize encodes a value using encoding/json. +func (e JSONEncoder) Serialize(src interface{}) ([]byte, error) { + buf := new(bytes.Buffer) + enc := json.NewEncoder(buf) + if err := enc.Encode(src); err != nil { + return nil, cookieError{cause: err, typ: usageError} + } + return buf.Bytes(), nil +} + +// Deserialize decodes a value using encoding/json. +func (e JSONEncoder) Deserialize(src []byte, dst interface{}) error { + dec := json.NewDecoder(bytes.NewReader(src)) + if err := dec.Decode(dst); err != nil { + return cookieError{cause: err, typ: decodeError} + } + return nil +} + +// Serialize passes a []byte through as-is. +func (e NopEncoder) Serialize(src interface{}) ([]byte, error) { + if b, ok := src.([]byte); ok { + return b, nil + } + + return nil, errValueNotByte +} + +// Deserialize passes a []byte through as-is. +func (e NopEncoder) Deserialize(src []byte, dst interface{}) error { + if dat, ok := dst.(*[]byte); ok { + *dat = src + return nil + } + return errValueNotBytePtr +} + +// Encoding ------------------------------------------------------------------- + +// encode encodes a value using base64. +func encode(value []byte) []byte { + encoded := make([]byte, base64.URLEncoding.EncodedLen(len(value))) + base64.URLEncoding.Encode(encoded, value) + return encoded +} + +// decode decodes a cookie using base64. +func decode(value []byte) ([]byte, error) { + decoded := make([]byte, base64.URLEncoding.DecodedLen(len(value))) + b, err := base64.URLEncoding.Decode(decoded, value) + if err != nil { + return nil, cookieError{cause: err, typ: decodeError, msg: "base64 decode failed"} + } + return decoded[:b], nil +} + +// Helpers -------------------------------------------------------------------- + +// GenerateRandomKey creates a random key with the given length in bytes. +// On failure, returns nil. +// +// Note that keys created using `GenerateRandomKey()` are not automatically +// persisted. New keys will be created when the application is restarted, and +// previously issued cookies will not be able to be decoded. +// +// Callers should explicitly check for the possibility of a nil return, treat +// it as a failure of the system random number generator, and not continue. +func GenerateRandomKey(length int) []byte { + k := make([]byte, length) + if _, err := io.ReadFull(rand.Reader, k); err != nil { + return nil + } + return k +} + +// CodecsFromPairs returns a slice of SecureCookie instances. +// +// It is a convenience function to create a list of codecs for key rotation. Note +// that the generated Codecs will have the default options applied: callers +// should iterate over each Codec and type-assert the underlying *SecureCookie to +// change these. +// +// Example: +// +// codecs := securecookie.CodecsFromPairs( +// []byte("new-hash-key"), +// []byte("new-block-key"), +// []byte("old-hash-key"), +// []byte("old-block-key"), +// ) +// +// // Modify each instance. +// for _, s := range codecs { +// if cookie, ok := s.(*securecookie.SecureCookie); ok { +// cookie.MaxAge(86400 * 7) +// cookie.SetSerializer(securecookie.JSONEncoder{}) +// cookie.HashFunc(sha512.New512_256) +// } +// } +func CodecsFromPairs(keyPairs ...[]byte) []Codec { + codecs := make([]Codec, len(keyPairs)/2+len(keyPairs)%2) + for i := 0; i < len(keyPairs); i += 2 { + var blockKey []byte + if i+1 < len(keyPairs) { + blockKey = keyPairs[i+1] + } + codecs[i/2] = New(keyPairs[i], blockKey) + } + return codecs +} + +// EncodeMulti encodes a cookie value using a group of codecs. +// +// The codecs are tried in order. Multiple codecs are accepted to allow +// key rotation. +// +// On error, may return a MultiError. +func EncodeMulti(name string, value interface{}, codecs ...Codec) (string, error) { + if len(codecs) == 0 { + return "", errNoCodecs + } + + var errors MultiError + for _, codec := range codecs { + encoded, err := codec.Encode(name, value) + if err == nil { + return encoded, nil + } + errors = append(errors, err) + } + return "", errors +} + +// DecodeMulti decodes a cookie value using a group of codecs. +// +// The codecs are tried in order. Multiple codecs are accepted to allow +// key rotation. +// +// On error, may return a MultiError. +func DecodeMulti(name string, value string, dst interface{}, codecs ...Codec) error { + if len(codecs) == 0 { + return errNoCodecs + } + + var errors MultiError + for _, codec := range codecs { + err := codec.Decode(name, value, dst) + if err == nil { + return nil + } + errors = append(errors, err) + } + return errors +} + +// MultiError groups multiple errors. +type MultiError []error + +func (m MultiError) IsUsage() bool { return m.any(func(e Error) bool { return e.IsUsage() }) } +func (m MultiError) IsDecode() bool { return m.any(func(e Error) bool { return e.IsDecode() }) } +func (m MultiError) IsInternal() bool { return m.any(func(e Error) bool { return e.IsInternal() }) } + +// Cause returns nil for MultiError; there is no unique underlying cause in the +// general case. +// +// Note: we could conceivably return a non-nil Cause only when there is exactly +// one child error with a Cause. However, it would be brittle for client code +// to rely on the arity of causes inside a MultiError, so we have opted not to +// provide this functionality. Clients which really wish to access the Causes +// of the underlying errors are free to iterate through the errors themselves. +func (m MultiError) Cause() error { return nil } + +func (m MultiError) Error() string { + s, n := "", 0 + for _, e := range m { + if e != nil { + if n == 0 { + s = e.Error() + } + n++ + } + } + switch n { + case 0: + return "(0 errors)" + case 1: + return s + case 2: + return s + " (and 1 other error)" + } + return fmt.Sprintf("%s (and %d other errors)", s, n-1) +} + +// any returns true if any element of m is an Error for which pred returns true. +func (m MultiError) any(pred func(Error) bool) bool { + for _, e := range m { + if ourErr, ok := e.(Error); ok && pred(ourErr) { + return true + } + } + return false +} diff -Nru golang-github-gorilla-csrf-1.7.1/vendor/modules.txt golang-github-gorilla-csrf-1.7.2/vendor/modules.txt --- golang-github-gorilla-csrf-1.7.1/vendor/modules.txt 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-gorilla-csrf-1.7.2/vendor/modules.txt 2023-11-05 02:08:39.000000000 +0000 @@ -0,0 +1,3 @@ +# github.com/gorilla/securecookie v1.1.2 +## explicit; go 1.20 +github.com/gorilla/securecookie