fix(dialect): escape driver.Valuer error messages in AppendError - #1416
Open
kyungseopk1m wants to merge 1 commit into
Open
fix(dialect): escape driver.Valuer error messages in AppendError#1416kyungseopk1m wants to merge 1 commit into
kyungseopk1m wants to merge 1 commit into
Conversation
AppendError wrote err.Error() into the "?!(...)" marker verbatim. The message is untrusted: it can come from a driver.Valuer, a JSON or msgpack encoder, or a pgdialect element appender, so a crafted message could close the marker and inject SQL. Take a StringEscaper and run the message through AppendString, which already quotes and escapes exhaustively. The interface is declared in dialect rather than reusing schema.QueryGen because schema already imports dialect; schema.Dialect satisfies it structurally. appendElem and appendRange in pgdialect had no access to a dialect, so they now take the escaper as a parameter. Range.AppendQuery and MultiRange.AppendQuery already received a schema.QueryGen and discarded it, so their signatures are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
dialect.AppendErrorwriteserr.Error()into the?!(...)marker without escaping. That message is untrusted, so a crafted error can close the marker and inject SQL.Closes #1307.
Why
AppendErroris the shared failure path for value formatting. The error text reaching it can be attacker controlled in several places:driver.Valuer.Value()returning an error (the case reported in Possible SQL Injection via driver.Valuer Error Messages #1307)AppendJSONValue/appendMsgpackencoder failurespgdialectelement and range appendersBefore this change:
formats as
The quote terminates the surrounding literal and the rest is parsed as SQL.
Fix
AppendErrornow takes aStringEscaperand runs the message throughAppendString, which already quotes and escapes exhaustively. This follows the direction suggested in the review of #1369.The interface is declared in
dialectinstead of reusingschema.QueryGen, becauseschemaalready importsdialectand takingQueryGenthere creates an import cycle. It is a single method, andschema.Dialectsatisfies it structurally with no changes:All 13 call sites pass
gen.Dialect().Two helpers in
pgdialecthad no dialect in scope and now take the escaper as a parameter:appendElemis a plain[]bytehelper, so the escaper is threaded through its three callers.appendRangeis reached fromRange.AppendQueryandMultiRange.AppendQuery, which already received aschema.QueryGenand discarded it as_. Naming that parameter was enough, so their signatures are unchanged.One note on
schema/dialect.go.BaseDialect.AppendStringreports a NUL byte throughAppendError, so it now passes itself as the escaper. The message there is a fixed constant with no quotes or NUL bytes, so the recursion terminates on the first pass. Leaving that one call site on the old raw path would have kept an unescaped route into the marker, which is what this change is trying to remove.Breaking change
dialect.AppendErrorgains a parameter, anddialect.StringEscaperis new.appendElemandappendRangeare unexported. The issue carries thev2label, so the signature change looked acceptable; happy to gate it differently if you prefer.Tests
New regression tests:
dialect/append_test.gocovers a plain message, an embedded quote, and a marker breakout attempt.schema/append_value_test.gocoversappendDriverValuewith adriver.Valuerreturning an injecting error.dialect/pgdialect/elem_test.gocoversappendElemandRange.AppendQueryon the same input.Reverting the
AppendErrorbody to the old raw append fails all four, and the failure output shows the unescaped payload.go build,go test, andgo vetare clean on both the root module anddialect/pgdialect.internal/dbtestbuilds; its suite needs a live database and was not run.Related
Same class as the escaping fixes in #1396, #1405, and #1406.