Skip to content

Commit 580f2a0

Browse files
committed
mcp: verify 'Origin' and 'Content-Type' headers (#842)
This PR introduces protection against cross-origin requests by installing `http.CrossOriginProtection`. By default, the zero value is used which does not contain any trusted origins or bypass patterns. The protection can be customized by providing a custom `http.CrossOriginProtection` in `mcp.StreamableHTTPOptions`. Currently, the deny handler set on the protection is ignored. This default has an MCPGODEBUG option (`disableoriginverification`) to disable the default protection. It will be available until `v1.6.0` of the SDK. We also increase the Go version required by the SDK to 1.25, since this is the version that introduced `http.CrossOriginProtection`. This is in line with the SDK's policy of supporting two newest Go versions (1.26 was released in February 2026). Additionally, we start validating if the `Content-Type` header for `POST` requests is set to `application/json` to avoid accepting CORS-safelisted requests.
1 parent 421ddf1 commit 580f2a0

15 files changed

Lines changed: 252 additions & 11 deletions

.github/workflows/codeql.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ on:
88
schedule:
99
- cron: '31 9 * * 4'
1010

11+
# Declare default permissions as read only.
12+
permissions: read-all
13+
1114
jobs:
1215
analyze:
1316
name: Analyze (${{ matrix.language }})

.github/workflows/conformance.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Set up Go
2323
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
2424
with:
25-
go-version: "^1.25"
25+
go-version: "^1.26"
2626
- name: Start everything-server
2727
run: |
2828
go run ./conformance/everything-server/main.go -http=":3001" &
@@ -45,7 +45,7 @@ jobs:
4545
- name: Set up Go
4646
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
4747
with:
48-
go-version: "^1.25"
48+
go-version: "^1.26"
4949
- name: "Run conformance tests"
5050
uses: modelcontextprotocol/conformance@a2855b03582a6c0b31065ad4d9af248316ce61a3 # v0.1.15
5151
with:

.github/workflows/docs-check.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
steps:
1818
- name: Set up Go
1919
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
20+
with:
21+
go-version: "^1.26"
2022
- name: Check out code
2123
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2224
- name: Check docs are up-to-date

.github/workflows/nightly.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Set up Go
2828
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
2929
with:
30-
go-version: "^1.25"
30+
go-version: "^1.26"
3131
- name: Set up Node.js
3232
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
3333
with:

.github/workflows/test.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
runs-on: ubuntu-latest
4141
strategy:
4242
matrix:
43-
go: ["1.24", "1.25"]
43+
go: ["1.25", "1.26"]
4444
steps:
4545
- name: Check out code
4646
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -52,13 +52,15 @@ jobs:
5252
run: go test -v ./...
5353

5454
race-test:
55+
# Temporarily disable until fixes are prepared.
56+
if: false
5557
runs-on: ubuntu-latest
5658
steps:
5759
- name: Check out code
5860
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
5961
- name: Set up Go
6062
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
6163
with:
62-
go-version: "1.24"
64+
go-version: "1.25"
6365
- name: Test with -race
6466
run: go test -v -race ./...

docs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ protocol.
3939

4040
See [troubleshooting.md](troubleshooting.md) for a troubleshooting guide.
4141

42+
# Backwards compatibility
43+
44+
See [mcpgodebug.md](mcpgodebug.md) for a list of backwards incompatible behavior changes
45+
and description how they can be temporarily undone.
46+
4247
# Rough edges
4348

4449
See [rough_edges.md](rough_edges.md) for a list of rough edges or API

docs/mcpgodebug.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!-- Autogenerated by weave; DO NOT EDIT -->
2+
# Backwards compatibility and MCPGODEBUG
3+
4+
According to our compatibility promise, we can't break backward compatibility
5+
of the SDK API. However, sometimes we need to change the behavior of the SDK
6+
in a backward-incompatible way in order to fix bugs or security issues.
7+
In those cases we introduce temporary compatibility parameters, that can be
8+
used to opt-out of the new behavior. They are usually maintained for two
9+
minor release cycles and then removed.
10+
11+
The compatibility parameters are provided via the `MCPGODEBUG` environment
12+
variable. The value of the variable is a comma-separated list of parameter
13+
value assignments, e.g.:
14+
15+
```
16+
MCPGODEBUG=parameter1=value1,parameter2=value2
17+
```
18+
19+
## `MCPGODEBUG` history
20+
21+
### 1.4.1
22+
23+
Options listed below will be removed in the 1.6.0 version of the SDK.
24+
25+
- `disablecrossoriginprotection` added. If set to `1`, newly added cross-origin
26+
protection will be disabled. The default behavior was changed to enable
27+
cross-origin protection.
28+
29+
### 1.4.0
30+
31+
Options listed below will be removed in the 1.6.0 version of the SDK.
32+
33+
- `jsonescaping` added. If set to `1`, JSON marshaling will preserve the previous
34+
behavior of escaping HTML characters in JSON strings. The default behavior
35+
was changed to not escape HTML characters, to be consistent with other SDKs.
36+
37+
- `disablelocalhostprotection` added. If set to `1`, newly added DNS rebinding
38+
protection will be disabled. The default behavior was changed to enable DNS rebinding
39+
protection. The protection can also be disabled by setting the
40+
`DisableLocalhostProtection` field in the `StreamableHTTPOptions` struct to
41+
`true`, which is the recommended way to disable the protection long term.

docs/protocol.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ and step-up authentication (when the server returns `insufficient_scope` error).
360360
## Security
361361

362362
Here we discuss the mitigations described under
363-
the MCP spec's [Security Best Practices](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices) section, and how we handle them.
363+
the MCP's [Security Best Practices](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices) section, and how we handle them.
364364

365365
### Confused Deputy
366366

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/modelcontextprotocol/go-sdk
22

3-
go 1.24.0
3+
go 1.25.0
44

55
require (
66
github.com/golang-jwt/jwt/v5 v5.3.0

internal/docs/README.src.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ protocol.
3838

3939
See [troubleshooting.md](troubleshooting.md) for a troubleshooting guide.
4040

41+
# Backwards compatibility
42+
43+
See [mcpgodebug.md](mcpgodebug.md) for a list of backwards incompatible behavior changes
44+
and description how they can be temporarily undone.
45+
4146
# Rough edges
4247

4348
See [rough_edges.md](rough_edges.md) for a list of rough edges or API

0 commit comments

Comments
 (0)