Skip to content

JDBC backend: a clear renders every catalog row it skipped into one unbounded log line, with the values as they stand #931

Description

@vharseko

Lands with #893, which is where readCatalogRows() and reportSkippedRows() are: they are not on master yet.

Problem

A clear reads the catalog of its backend and passes over any row it cannot act on — one whose key is not the name of a tree, or whose value records a table outside the namespace this backend names its tables in. Every such row is described into a list, and the whole list goes into one logger.warn:

// readCatalogRows(): one description per row, no cap
skippedRows.add(...);              // embeds the key and the recorded table name verbatim
...
// reportSkippedRows(): the whole List rendered into a single line
reportClearLine(LocalizableMessage.raw("jdbc: backend %s: %d row(s) of its catalog named nothing this clear could drop and were passed over: %s. ...",
    config.getBackendId(), skippedRows.size(), skippedRows));

Two things follow, and the second is the one worth acting on:

  1. No cap. A catalog holding thousands of such rows becomes one multi-megabyte log record.
  2. The values are embedded as they stand. They come out of a table, and the whole premise of this line is a catalog "written into by something other than this backend". A key or a recorded name carrying a newline splices arbitrary text into the server log where it reads as further log records — the pattern CodeQL flags as log injection.

Why it is not urgent

Nothing this version writes makes such a row: getTableName() names every table opendj_<hash> and every key is TreeName.toString(). The line exists precisely for a catalog somebody else wrote into, so its input is untrusted by construction — but reaching it takes a writer on that database.

What the fix looks like

Report the first N and a count of the rest, and put the embedded values through a sanitiser that strips control characters (or renders them escaped) before they reach the line. CachedConnection.redact() is the nearest precedent in this package for "a value that reaches a log is put through something first"; this wants the same shape, for a different reason.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugjavaPull requests that update java codejdbc

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions