Fix mass assignment in Go and net/http
======================================

Decode the body into an input struct that declares only the fields users may
edit (here ProfileUpdate with DisplayName and Bio), never into the stored
struct, call DisallowUnknownFields, and copy each field across yourself.
encoding/json matches keys to fields case-insensitively, so a blocklist that
refuses "role" by its exact name lets "Role" through.

Page: https://softwaresecurity.com/fix/mass-assignment/go-nethttp/

What is in this archive
-----------------------
mass-assignment/go-nethttp/   the project: three implementations of the same code and one test suite
  impl/vulnerable.go   (vulnerable)
  impl/fixed.go   (fixed)
  impl/wrong.go   (a plausible fix that still fails)
run-all.mjs   runs the tests in all three modes and checks the results (Node.js and Docker)
LICENSE-CODE.txt

Run it
------
  Tested with Go 1.27.2 (golang:1.27.2-trixie, linux/arm64); also passes on Go
  1.26.9; go.mod needs Go 1.26.0 or later. run-all.mjs needs Node.js 22 or
  later. Supported versions: https://softwaresecurity.com/fix/versions/

  From the mass-assignment/go-nethttp folder, install the dependencies once
  (this needs network access):

    go mod download
    go build ./... tool

  Then run the tests. IMPL chooses the implementation the tests load:

    # every test passes
    IMPL=fixed go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...
    # an exploit test fails
    IMPL=vulnerable go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...
    # a test fails
    IMPL=wrong go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...

  Without Go installed, Docker runs the same commands in the image the card was
  verified in, pinned by its digest (run them from the
  mass-assignment/go-nethttp folder; the named volumes keep the dependency and
  build caches between runs, so the test runs need no network):

    docker run --rm --init \
      -v "$PWD":/card -w /card \
      -v fix-go-gomod:/go/pkg/mod \
      -v fix-go-gocache:/root/.cache/go-build \
      golang:1.27.2-trixie@sha256:e58d6f83b3416618d8bcac2b3dde1b7f7e3c4a77d25e88637f8bbae81536c48d \
      sh -c 'go mod download && go build ./... tool'

    # every test passes
    docker run --rm --init --network=none \
      -v "$PWD":/card -w /card \
      -v fix-go-gomod:/go/pkg/mod \
      -v fix-go-gocache:/root/.cache/go-build \
      -e IMPL=fixed \
      golang:1.27.2-trixie@sha256:e58d6f83b3416618d8bcac2b3dde1b7f7e3c4a77d25e88637f8bbae81536c48d \
      sh -c 'go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...'
    # an exploit test fails
    docker run --rm --init --network=none \
      -v "$PWD":/card -w /card \
      -v fix-go-gomod:/go/pkg/mod \
      -v fix-go-gocache:/root/.cache/go-build \
      -e IMPL=vulnerable \
      golang:1.27.2-trixie@sha256:e58d6f83b3416618d8bcac2b3dde1b7f7e3c4a77d25e88637f8bbae81536c48d \
      sh -c 'go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...'
    # a test fails
    docker run --rm --init --network=none \
      -v "$PWD":/card -w /card \
      -v fix-go-gomod:/go/pkg/mod \
      -v fix-go-gocache:/root/.cache/go-build \
      -e IMPL=wrong \
      golang:1.27.2-trixie@sha256:e58d6f83b3416618d8bcac2b3dde1b7f7e3c4a77d25e88637f8bbae81536c48d \
      sh -c 'go tool gotestsum --junitfile reports/junit.xml -- -count=1 ./...'

  The JUnit report is written to reports/junit.xml. To run all three modes and
  check the results in one step, run the harness from this top folder (it needs
  only Node.js and Docker: it runs the commands in the container; --install runs
  the install step first):

    node run-all.mjs --install mass-assignment/go-nethttp
    node run-all.mjs mass-assignment/go-nethttp

Verified
--------
  11 October 2026 on macOS 27.0 (Darwin 27.0.0, arm64); tests in Docker Desktop
  4.73.0 (Engine 29.4.3), linux/arm64, with go 1.27.2 (golang:1.27.2-trixie
  image); also run on 1.26.9 (golang:1.26.9-trixie), gotestsum 1.13.0, semgrep
  1.180.0, gosec 2.29.0, govulncheck 1.8.0, codeql CLI 2.27.1, codeql/go-queries
  1.6.12. Versions and results hold for that date: run the tests with your own
  versions before relying on the fix.

Licence
-------
  The code is MIT licensed (LICENSE-CODE.txt). The page text is CC BY 4.0.
