fix(reports): derive report SELECT aliases from the whitelist #472

Merged
Claude-Run merged 1 commit from fix/PMS-690-report-alias-injection into main 2026-08-01 03:17:15 +02:00
Member

The saved-report compiler wrote the caller's column header straight into the SELECT list as a quoted identifier, so a header carrying a " closed the identifier and appended arbitrary SQL to the compiled query. The alias was the one value that escaped the whitelist discipline the field, filter and sort paths already have.

The SQL alias now comes from the whitelisted field key that ticket_column accepts, so no columns payload reaches the SQL text. CompiledQuery carries the SQL output names in a new columns vector and the operator-chosen display headers in aliases; the executor re-keys each row_to_json object from the former to the latter, so the wire shape (rows keyed by header, aliases listing the headers) is unchanged for the SPA and for the scheduled-report CSV render. A field selected twice gets a _2 suffix on its SQL alias so the two columns keep distinct row keys.

parse_columns additionally rejects a header containing a double quote or longer than 100 characters with a 400, so a hostile payload fails loudly instead of rendering under a different name.

#PMS-690

The saved-report compiler wrote the caller's column `header` straight into the SELECT list as a quoted identifier, so a `header` carrying a `"` closed the identifier and appended arbitrary SQL to the compiled query. The alias was the one value that escaped the whitelist discipline the field, filter and sort paths already have. The SQL alias now comes from the whitelisted field key that `ticket_column` accepts, so no `columns` payload reaches the SQL text. `CompiledQuery` carries the SQL output names in a new `columns` vector and the operator-chosen display headers in `aliases`; the executor re-keys each `row_to_json` object from the former to the latter, so the wire shape (rows keyed by header, `aliases` listing the headers) is unchanged for the SPA and for the scheduled-report CSV render. A field selected twice gets a `_2` suffix on its SQL alias so the two columns keep distinct row keys. `parse_columns` additionally rejects a header containing a double quote or longer than 100 characters with a 400, so a hostile payload fails loudly instead of rendering under a different name. #PMS-690
fix(reports): derive report SELECT aliases from the whitelist
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 2m36s
Check / fmt + clippy + build + tests (pull_request) Successful in 4m33s
Integration / integration tests (pull_request) Successful in 8m53s
Create release / Gate (release-branch merges only) (pull_request) Successful in 1s
Create release / Create release from merged PR (pull_request) Has been skipped
6773722c0e
The saved-report compiler wrote the caller's column `header` straight into the SELECT list as a quoted identifier, so a `header` carrying a `"` closed the identifier and appended arbitrary SQL to the compiled query. The alias was the one value that escaped the whitelist discipline the field, filter and sort paths already have.

The SQL alias now comes from the whitelisted field key that `ticket_column` accepts, so no `columns` payload reaches the SQL text. `CompiledQuery` carries the SQL output names in a new `columns` vector and the operator-chosen display headers in `aliases`; the executor re-keys each `row_to_json` object from the former to the latter, so the wire shape (rows keyed by header, `aliases` listing the headers) is unchanged for the SPA and for the scheduled-report CSV render. A field selected twice gets a `_2` suffix on its SQL alias so the two columns keep distinct row keys.

`parse_columns` additionally rejects a header containing a double quote or longer than 100 characters with a 400, so a hostile payload fails loudly instead of rendering under a different name.

#PMS-690
Claude-Run deleted branch fix/PMS-690-report-alias-injection 2026-08-01 03:17:16 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!472
No description provided.