Skip to content

[HIGH] Prevent SQL injection in set_client_encoding - #741

Merged
larskanis merged 1 commit into
ged:masterfrom
OskarEichler:codex/security-escape-client-encoding
Sep 3, 2026
Merged

[HIGH] Prevent SQL injection in set_client_encoding#741
larskanis merged 1 commit into
ged:masterfrom
OskarEichler:codex/security-escape-client-encoding

Conversation

@OskarEichler

Copy link
Copy Markdown
Contributor

Summary

PG::Connection#set_client_encoding interpolates its argument into a SET client_encoding statement. A quote in the public method's argument can terminate the value and append arbitrary SQL that runs with the connection's database privileges.

This change builds the asynchronous SET statement with PG::Connection#escape_literal, reusing libpq's connection-aware quoting. Valid encoding names retain their existing behavior; invalid or malicious names are handled as one value and rejected by PostgreSQL.

Reproduction

Against PostgreSQL 15 and the current master extension:

payload = "UTF8'; SELECT pg_sleep(0.25); --"
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
conn.set_client_encoding(payload)
puts Process.clock_gettime(Process::CLOCK_MONOTONIC) - started

The call succeeded after approximately 0.25 seconds, showing that the appended statement executed. With this patch, PostgreSQL immediately raises PG::InvalidParameterValue for the complete quoted value and the connection remains on UTF-8.

Verification

  • Built the native extension on Ruby 4.0.6 / PostgreSQL libpq 15.
  • Verified set_client_encoding("UTF8") succeeds.
  • Verified the reproduction payload is rejected in 0.000 seconds rather than executing pg_sleep.
  • Ran the focused existing encoding and scheduler specs: 2 examples, 0 failures.
  • git diff --check passes.

Limitations

The focused reproduction used a local PostgreSQL 15 development database. I did not run it against other server versions or production systems.

Breaking changes

None for valid encoding names. Invalid values containing SQL syntax are now passed as a single quoted value and rejected instead of being interpreted as SQL.

@larskanis
larskanis merged commit bbba5d5 into ged:master Sep 3, 2026
11 of 19 checks passed
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