Skip to content

fix(sources/postgres): apply URL encoding to query string params#3020

Merged
Yuan325 merged 4 commits into
googleapis:mainfrom
sjvanrossum:main
Apr 17, 2026
Merged

fix(sources/postgres): apply URL encoding to query string params#3020
Yuan325 merged 4 commits into
googleapis:mainfrom
sjvanrossum:main

Conversation

@sjvanrossum

@sjvanrossum sjvanrossum commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and values of query parameter maps are currently not escaped during encoding, which could result in misconfiguration and poses a minor security risk if the specification of query parameter maps were to be restricted by the application or deployment tooling.

PR Checklist

Thank you for opening a Pull Request! Before submitting your PR, there are a
few things you can do to make sure it goes smoothly:

  • Make sure you reviewed
    CONTRIBUTING.md
  • Make sure to open an issue as a
    bug/issue
    before writing your code! That way we can discuss the change, evaluate
    designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)
  • Make sure to add ! if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

@sjvanrossum sjvanrossum requested a review from a team as a code owner April 10, 2026 08:57

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the ConvertParamMapToRawQuery function in the Postgres source to utilize url.Values for building query strings, which improves reliability and allows for the removal of the strings import. A review comment suggests optimizing performance by pre-allocating the url.Values map with the size of the input parameters.

Comment thread internal/sources/postgres/postgres.go Outdated
@Yuan325

Yuan325 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

@sjvanrossum Thank you!

@Yuan325

Yuan325 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

/gcbrun

@Yuan325 Yuan325 enabled auto-merge (squash) April 17, 2026 18:34
@Yuan325 Yuan325 merged commit 6b860f4 into googleapis:main Apr 17, 2026
14 checks passed
github-actions Bot pushed a commit to Jaleel-zhu/genai-toolbox that referenced this pull request Apr 17, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
github-actions Bot pushed a commit to pepe57/genai-toolbox that referenced this pull request Apr 18, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
github-actions Bot pushed a commit to bhardwajRahul/genai-toolbox that referenced this pull request Apr 18, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
github-actions Bot pushed a commit to CrazyForks/genai-toolbox that referenced this pull request Apr 18, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
github-actions Bot pushed a commit to TheTechOddBug/genai-toolbox that referenced this pull request Apr 18, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
github-actions Bot pushed a commit to anikasharma03/genai-toolbox that referenced this pull request Apr 20, 2026
…ams (googleapis#3020)

## Description

Fixes an URL encoding issue in PostgreSQL connection strings. Keys and
values of query parameter maps are currently not escaped during
encoding, which could result in misconfiguration and poses a minor
security risk if the specification of query parameter maps were to be
restricted by the application or deployment tooling.

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [x] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/mcp-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/mcp-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com> 6b860f4
Yuan325 added a commit that referenced this pull request May 5, 2026
## Summary

The postgres source built its connection URL with `fmt.Sprintf("%s:%s",
host, port)`, which produces invalid authority for IPv6 literals. pgx
then parsed the result as an 8-segment IPv6 with the port absorbed as a
trailing hextet, producing dial errors such as:

```
dial tcp [fd00::1:5432]:5432: connect: no route to host
```

Replacing the concatenation with
[`net.JoinHostPort`](https://pkg.go.dev/net#JoinHostPort) wraps IPv6
literals in brackets as required by RFC 3986, and leaves IPv4 addresses
and hostnames unchanged.

URL construction is extracted into a new `BuildPostgresURL` helper so it
can be unit-tested without a live database.

## Relationship to #3020

#3020 ("apply URL encoding to query string params") merged to `main`
while this PR was open. It applied the same `url.Values.Encode()` fix
directly inside `ConvertParamMapToRawQuery`. This PR independently
introduced the same encoding improvement but inlined it into the new
`BuildPostgresURL` helper and removed `ConvertParamMapToRawQuery` as no
longer needed (the postgres package was its only caller;
`internal/sources/cockroachdb` has its own independent copy and is
unaffected). After rebasing on `main`, the conflict was resolved in
favor of this PR's version, which is a strict superset: same
URL-encoding behavior plus IPv6 support and a testable builder.

## Changes

- `internal/sources/postgres/postgres.go`
  - Introduce `BuildPostgresURL` that uses `net.JoinHostPort`.
- Encode query parameters with
[`url.Values.Encode()`](https://pkg.go.dev/net/url#Values.Encode) (per
gemini-code-assist review): proper escaping of `&`, `=`, spaces, and
deterministic key order. Equivalent behavior to #3020, encapsulated in
the new helper.
- Remove the now-unused `ConvertParamMapToRawQuery` helper. It was only
referenced from this file; `internal/sources/cockroachdb` has its own
independent copy and is not affected.
- `internal/sources/postgres/postgres_test.go`
- Add `TestBuildPostgresURL` covering hostname, IPv4 (`127.0.0.1`), IPv6
loopback (`::1`), IPv6 documentation (`2001:db8::1`), IPv6 link-local
with zone id (`fe80::1%eth0`), query-parameter key ordering, and
URL-encoding of values containing special characters. Each expected URL
is also fed through `pgx.ParseConfig` to verify downstream
compatibility.
  - Drop `TestConvertParamMapToRawQuery` alongside the removed function.

## Backward compatibility

- `net.JoinHostPort` behaves identically to `fmt.Sprintf("%s:%s", host,
port)` for hostnames and IPv4 addresses — brackets are only added when
the host contains a colon.
- The query-string output order is now deterministic (sorted by key)
rather than map-iteration order. The previous order was already
non-deterministic, so any consumer that depended on a specific order was
already broken.
- `queryParams` values that previously contained special characters such
as `&` or `=` would have produced malformed URLs; they are now correctly
percent-encoded (same fix as #3020).

## Test plan

- [x] `go test -race ./internal/sources/postgres/...` — all tests pass
including new IPv6 and query-param encoding cases.
- [x] `go vet ./internal/sources/postgres/...` — clean.
- [x] End-to-end: built the patched toolbox and used it via `--prebuilt
postgres --stdio` to connect to a real PostgreSQL instance reachable
only over IPv6 (ULA address via a WireGuard-style tunnel). The MCP
client listed tools and executed queries successfully, whereas the
unpatched binary failed with the mangled dial error shown above.
- [x] Rebased onto current `main` (post-#3020); conflicts resolved
cleanly, all tests green.

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com>
Yuan325 added a commit that referenced this pull request May 7, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.2.0](v1.1.0...v1.2.0)
(2026-05-07)


### Features

* Add support for HTTPS/TLS listener
([#3126](#3126))
([8bc385d](8bc385d))
* **source/bigquery:** Add maximumBytesBilled source config
([#2724](#2724))
([42f2d07](42f2d07))
* **source/cloud-storage:** Add bucket and object management tools
([#3129](#3129))
([8de9bcf](8de9bcf))
* **source/cloud-storage:** Add Cloud Storage source with list_objects
and read_object tools
([#3081](#3081))
([da27b37](da27b37))
* **source/cloud-storage:** Add write/copy/move/delete object tools
([#3139](#3139))
([b225fc4](b225fc4))
* **tools/knowledge-catalog:** Search Data Quality Scans
([#2444](#2444))
([1c63551](1c63551))


### Bug Fixes

* Allow converting string literal block with list
([#3050](#3050))
([36ab2a9](36ab2a9)),
closes [#3023](#3023)
* **mcp:** Implement router-level logger injection for MCP auth
([#3067](#3067))
([ccc7cf5](ccc7cf5))
* Prevent test.db from being created during unit tests
([#3042](#3042))
([d10d2ca](d10d2ca))
* Remove hardcoded * allowed origin for sse
([#3054](#3054))
([c4c7bd9](c4c7bd9))
* **sources/postgres:** Apply URL encoding to query string params
([#3020](#3020))
([6b860f4](6b860f4))
* **tool/looker-conversational-analytics:** OAuth token in GDA payload
fix ([#3058](#3058))
([6632d96](6632d96))
* **tools/bigquery-execute-sql:** Avoid surfacing invalid queries as MCP
500s ([#3056](#3056))
([7ed92c8](7ed92c8))
* **tools/looker:** Fix OAuth for Converational Analytics
([#3044](#3044))
([f9e3e55](f9e3e55))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com>
pavankrishna13 pushed a commit to pavankrishna13/genai-toolbox that referenced this pull request May 19, 2026
…#3052)

## Summary

The postgres source built its connection URL with `fmt.Sprintf("%s:%s",
host, port)`, which produces invalid authority for IPv6 literals. pgx
then parsed the result as an 8-segment IPv6 with the port absorbed as a
trailing hextet, producing dial errors such as:

```
dial tcp [fd00::1:5432]:5432: connect: no route to host
```

Replacing the concatenation with
[`net.JoinHostPort`](https://pkg.go.dev/net#JoinHostPort) wraps IPv6
literals in brackets as required by RFC 3986, and leaves IPv4 addresses
and hostnames unchanged.

URL construction is extracted into a new `BuildPostgresURL` helper so it
can be unit-tested without a live database.

## Relationship to googleapis#3020

googleapis#3020 ("apply URL encoding to query string params") merged to `main`
while this PR was open. It applied the same `url.Values.Encode()` fix
directly inside `ConvertParamMapToRawQuery`. This PR independently
introduced the same encoding improvement but inlined it into the new
`BuildPostgresURL` helper and removed `ConvertParamMapToRawQuery` as no
longer needed (the postgres package was its only caller;
`internal/sources/cockroachdb` has its own independent copy and is
unaffected). After rebasing on `main`, the conflict was resolved in
favor of this PR's version, which is a strict superset: same
URL-encoding behavior plus IPv6 support and a testable builder.

## Changes

- `internal/sources/postgres/postgres.go`
  - Introduce `BuildPostgresURL` that uses `net.JoinHostPort`.
- Encode query parameters with
[`url.Values.Encode()`](https://pkg.go.dev/net/url#Values.Encode) (per
gemini-code-assist review): proper escaping of `&`, `=`, spaces, and
deterministic key order. Equivalent behavior to googleapis#3020, encapsulated in
the new helper.
- Remove the now-unused `ConvertParamMapToRawQuery` helper. It was only
referenced from this file; `internal/sources/cockroachdb` has its own
independent copy and is not affected.
- `internal/sources/postgres/postgres_test.go`
- Add `TestBuildPostgresURL` covering hostname, IPv4 (`127.0.0.1`), IPv6
loopback (`::1`), IPv6 documentation (`2001:db8::1`), IPv6 link-local
with zone id (`fe80::1%eth0`), query-parameter key ordering, and
URL-encoding of values containing special characters. Each expected URL
is also fed through `pgx.ParseConfig` to verify downstream
compatibility.
  - Drop `TestConvertParamMapToRawQuery` alongside the removed function.

## Backward compatibility

- `net.JoinHostPort` behaves identically to `fmt.Sprintf("%s:%s", host,
port)` for hostnames and IPv4 addresses — brackets are only added when
the host contains a colon.
- The query-string output order is now deterministic (sorted by key)
rather than map-iteration order. The previous order was already
non-deterministic, so any consumer that depended on a specific order was
already broken.
- `queryParams` values that previously contained special characters such
as `&` or `=` would have produced malformed URLs; they are now correctly
percent-encoded (same fix as googleapis#3020).

## Test plan

- [x] `go test -race ./internal/sources/postgres/...` — all tests pass
including new IPv6 and query-param encoding cases.
- [x] `go vet ./internal/sources/postgres/...` — clean.
- [x] End-to-end: built the patched toolbox and used it via `--prebuilt
postgres --stdio` to connect to a real PostgreSQL instance reachable
only over IPv6 (ULA address via a WireGuard-style tunnel). The MCP
client listed tools and executed queries successfully, whereas the
unpatched binary failed with the mangled dial error shown above.
- [x] Rebased onto current `main` (post-googleapis#3020); conflicts resolved
cleanly, all tests green.

---------

Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com>
pavankrishna13 pushed a commit to pavankrishna13/genai-toolbox that referenced this pull request May 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.2.0](googleapis/mcp-toolbox@v1.1.0...v1.2.0)
(2026-05-07)


### Features

* Add support for HTTPS/TLS listener
([googleapis#3126](googleapis#3126))
([8bc385d](googleapis@8bc385d))
* **source/bigquery:** Add maximumBytesBilled source config
([googleapis#2724](googleapis#2724))
([42f2d07](googleapis@42f2d07))
* **source/cloud-storage:** Add bucket and object management tools
([googleapis#3129](googleapis#3129))
([8de9bcf](googleapis@8de9bcf))
* **source/cloud-storage:** Add Cloud Storage source with list_objects
and read_object tools
([googleapis#3081](googleapis#3081))
([da27b37](googleapis@da27b37))
* **source/cloud-storage:** Add write/copy/move/delete object tools
([googleapis#3139](googleapis#3139))
([b225fc4](googleapis@b225fc4))
* **tools/knowledge-catalog:** Search Data Quality Scans
([googleapis#2444](googleapis#2444))
([1c63551](googleapis@1c63551))


### Bug Fixes

* Allow converting string literal block with list
([googleapis#3050](googleapis#3050))
([36ab2a9](googleapis@36ab2a9)),
closes [googleapis#3023](googleapis#3023)
* **mcp:** Implement router-level logger injection for MCP auth
([googleapis#3067](googleapis#3067))
([ccc7cf5](googleapis@ccc7cf5))
* Prevent test.db from being created during unit tests
([googleapis#3042](googleapis#3042))
([d10d2ca](googleapis@d10d2ca))
* Remove hardcoded * allowed origin for sse
([googleapis#3054](googleapis#3054))
([c4c7bd9](googleapis@c4c7bd9))
* **sources/postgres:** Apply URL encoding to query string params
([googleapis#3020](googleapis#3020))
([6b860f4](googleapis@6b860f4))
* **tool/looker-conversational-analytics:** OAuth token in GDA payload
fix ([googleapis#3058](googleapis#3058))
([6632d96](googleapis@6632d96))
* **tools/bigquery-execute-sql:** Avoid surfacing invalid queries as MCP
500s ([googleapis#3056](googleapis#3056))
([7ed92c8](googleapis@7ed92c8))
* **tools/looker:** Fix OAuth for Converational Analytics
([googleapis#3044](googleapis#3044))
([f9e3e55](googleapis@f9e3e55))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Co-authored-by: Yuan Teoh <45984206+Yuan325@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants