Skip to content

[HIGH] Prevent SQL injection through embed_params type names - #744

Open
OskarEichler wants to merge 1 commit into
ged:masterfrom
OskarEichler:codex/security-quote-embedded-type-names
Open

[HIGH] Prevent SQL injection through embed_params type names#744
OskarEichler wants to merge 1 commit into
ged:masterfrom
OskarEichler:codex/security-quote-embedded-type-names

Conversation

@OskarEichler

Copy link
Copy Markdown
Contributor

Summary

Quote type-name components before PG::Connection#embed_params inserts them into generated SQL. This prevents caller-supplied :typename values (or mutable coder names) from terminating the cast and appending an additional SQL statement.

Urgency: HIGH. A caller that lets untrusted metadata reach :typename and then executes the generated SQL can run arbitrary SQL with the connection's database privileges. embed_params is documented primarily for debugging, which limits expected exposure, but its result is executable SQL and the examples/tests execute it.

Reproduction

On current master, this input:

params = [{ value: "x", type: 25, typename: "text; SELECT pg_sleep(0.25); --" }]
sql = conn.embed_params("SELECT $1", params)
conn.exec(sql)

produces:

SELECT 'x'::text; SELECT pg_sleep(0.25); --

A local PostgreSQL reproduction completed in 0.252 seconds, confirming that the appended statement ran.

After this change, unsafe identifier components are quoted and PostgreSQL rejects the invalid type immediately (0.000 seconds in the same focused reproduction). Ordinary names such as int8, int[], and schema-qualified names retain their existing generated form.

Verification

  • rbenv exec ruby -c lib/pg/connection.rb
  • rbenv exec bundle exec rspec spec/pg/connection_spec.rb:3057 — 20 examples, 0 failures
  • Focused before/after local PostgreSQL reproduction described above
  • git diff --check

Scope and compatibility

  • The affected method is present on current master; it is not part of the installed 1.6.3 release reviewed downstream.
  • This intentionally stops treating punctuation, comments, and other unsafe text in :typename as raw SQL syntax.
  • Simple unquoted identifiers, schema-qualified identifiers, and array suffixes retain their current output.
  • Breaking-change note: callers relying on arbitrary type expressions rather than actual type names may now receive a PostgreSQL unknown-type error and should pass a concrete type identifier instead.

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.

1 participant