Skip to content

HYPERFLEET-1366 - refactor: remove search and order field allowlists - #321

Open
Mischulee wants to merge 1 commit into
openshift-hyperfleet:mainfrom
Mischulee:HYPERFLEET-1366
Open

HYPERFLEET-1366 - refactor: remove search and order field allowlists#321
Mischulee wants to merge 1 commit into
openshift-hyperfleet:mainfrom
Mischulee:HYPERFLEET-1366

Conversation

@Mischulee

@Mischulee Mischulee commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the searchAllowedFields and orderAllowedFields allowlists from pkg/db/sql_helpers.go so all fields are now valid search and order targets

  • Adds a handler in loadList to return a 400 instead of a 500 when a field name passes syntax validation but doesn't exist in the database to preserve correct error classification

  • Ticket: HYPERFLEET-1366

Test Plan

  • Unit tests added/updated
  • make test-all passes
  • make lint passes
  • Helm chart changes validated with make test-helm (if applicable)
  • Deployed to a development cluster and verified (if Helm/config changes)
  • E2E tests passed (if cross-component or major changes)

@openshift-ci
openshift-ci Bot requested review from aredenba-rh and ldornele July 30, 2026 10:17
@openshift-ci

openshift-ci Bot commented Jul 30, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign crizzo71 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Summary by CodeRabbit

  • Improvements
    • Search queries accept a broader set of field references.
    • Ordering continues to validate the order expression format, ignores empty entries, and normalizes direction (asc/desc).
  • Bug Fixes
    • Requests referencing nonexistent database columns now consistently return 400 Bad Request with invalid field in search or order query.
    • Ordering-related error messaging/behavior is aligned for nonexistent fields.
  • Tests
    • Added and updated integration/unit tests to cover nonexistent search/order fields and adjusted expected error substrings.

Walkthrough

Search and order parsing no longer uses field allowlists. Structurally valid search names and regex-valid order clauses proceed to SQL generation, while PostgreSQL undefined_column errors are translated into 400 Bad Request responses. Tests remove obsolete allowlist expectations, update ordering error assertions, and add nonexistent search-field coverage. The change concerns CWE-89; no CVE is identified in the supplied changes.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: aredenba-rh, ldornele, mliptak0

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant API
  participant loadList
  participant PostgreSQL
  Client->>API: Search or order query
  API->>loadList: Load list
  loadList->>PostgreSQL: Execute generated SQL
  PostgreSQL-->>loadList: undefined_column error
  loadList-->>API: BadRequest
  API-->>Client: 400 invalid field in search or order query
Loading
🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sec-02: Secrets In Log Output ✅ Passed No log statement in touched non-test code includes token/password/credential/secret; repo-wide log+secret scan found none. CWE-532 not triggered.
No Hardcoded Secrets ✅ Passed No CWE-798 hardcoded-credential patterns, credential URLs, or long base64 literals appear in the touched diff; changes are field-validation/error-handling only.
No Weak Cryptography ✅ Passed Touched files only add regex validation and DB error mapping; no md5/des/rc4/SHA1-for-security, ECB, custom crypto, or secret compares. CWE-327/328/759 not present.
No Injection Vectors ✅ Passed No CWE-89/78/79/502 sink in changed code: search/order inputs are validated, SQL values are parameterized, and injection tests reject bad input.
No Privileged Containers ✅ Passed Diff only changes Go sources/tests; no Kubernetes/OpenShift manifest, Helm, or Dockerfile privilege flags were introduced.
No Pii Or Sensitive Data In Logs ✅ Passed PR diff adds no log calls; existing logs don’t expose PII, raw bodies, session IDs, or credentials. CWE-532 not triggered.
Title check ✅ Passed The title names the same core change: removing search and order field allowlists.
Description check ✅ Passed The description is on-topic and describes the allowlist removal and related test updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Comment @coderabbitai help to get the list of available commands.

@hyperfleet-ci-bot

hyperfleet-ci-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

Risk Score: 0 — risk/low

Signal Detail Points
PR size 104 lines +0
Sensitive paths none +0
Test coverage Tests cover changed packages +0

Computed by hyperfleet-risk-scorer

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/db/sql_helpers.go (1)

72-73: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject unknown ORDER BY fields before SQL generation. ArgsToOrder() only checks syntax; nonexistent_field asc still reaches d.OrderBy() and becomes a DB error instead of a 400. CWE-20. Validate against the resource’s orderable-field mapping in pkg/db/sql_helpers.go / pkg/services/generic.go, and keep an unknown-field rejection case in test/integration/order_field_mapping_test.go.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/db/sql_helpers.go` around lines 72 - 73, Validate parsed ORDER BY fields
from ArgsToOrder against the resource’s orderable-field mapping before
d.OrderBy() generates SQL, rejecting unknown fields as a 400 while preserving
valid mappings; update the related handling in pkg/db/sql_helpers.go and
pkg/services/generic.go. In pkg/db/sql_helpers.go lines 72-73 and 747-750, apply
the validation at both affected sites as appropriate, and add an unknown-field
rejection case in test/integration/order_field_mapping_test.go lines 151-160.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@pkg/db/sql_helpers.go`:
- Around line 72-73: Validate parsed ORDER BY fields from ArgsToOrder against
the resource’s orderable-field mapping before d.OrderBy() generates SQL,
rejecting unknown fields as a 400 while preserving valid mappings; update the
related handling in pkg/db/sql_helpers.go and pkg/services/generic.go. In
pkg/db/sql_helpers.go lines 72-73 and 747-750, apply the validation at both
affected sites as appropriate, and add an unknown-field rejection case in
test/integration/order_field_mapping_test.go lines 151-160.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 090b05a3-e57e-4e15-a581-563406d7702a

📥 Commits

Reviewing files that changed from the base of the PR and between 632b388 and a59d594.

📒 Files selected for processing (4)
  • pkg/db/sql_helpers.go
  • pkg/db/sql_helpers_test.go
  • pkg/services/generic_test.go
  • test/integration/order_field_mapping_test.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
💤 Files with no reviewable changes (2)
  • pkg/services/generic_test.go
  • pkg/db/sql_helpers_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/db/sql_helpers.go (1)

72-73: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Reject arbitrary identifiers here before they reach sq.Expr.
getField returns trimmedName unchanged for non-spec. inputs, and the TSL SQL walker emits KindIdentifier values as raw SQL. That leaves a CWE-89 path unless every allowed field is validated against a strict grammar or mapped/quoted before returning it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/db/sql_helpers.go` around lines 72 - 73, Update getField so non-spec.
inputs are not returned unchanged: validate them against a strict identifier
grammar or resolve them through an allowlist and quote/map them before they
reach sq.Expr. Preserve the existing handling for valid spec.-prefixed fields
while rejecting any unsupported identifier input.

Sources: Path instructions, MCP tools

🧹 Nitpick comments (1)
pkg/db/transaction_middleware.go (1)

79-84: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add direct unit coverage for IsUndefinedColumnError.

This exported classifier controls the 400/500 boundary. Add table-driven tests for nil, wrapped *pq.Error{Code: "42703"}, another PostgreSQL code, and a non-pq error; the integration test alone will not catch driver or wrapping regressions.

As per path instructions, new exported functions and critical error paths SHOULD have tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/db/transaction_middleware.go` around lines 79 - 84, Add direct
table-driven unit tests for IsUndefinedColumnError covering nil, a wrapped
*pq.Error with code 42703, a different PostgreSQL code, and a non-pq error.
Assert only the expected boolean classification for each case, including wrapped
errors, to protect the exported classifier’s behavior.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/db/sql_helpers.go`:
- Around line 732-734: Update ArgsToOrder and its orderPattern validation to use
the same field grammar as getField, allowing valid digit-bearing names and
nested spec.* paths while retaining the existing direction handling and safety
checks; only restrict sorting to flat lowercase columns if that limitation is
explicitly documented.

In `@pkg/services/generic.go`:
- Around line 281-282: Update the error handling around d.Fetch and the
db.IsUndefinedColumnError(err) case so only errors explicitly tagged as
originating from user-supplied search or order fields return errors.BadRequest.
Propagate untagged undefined-column errors through the existing server-error
path, preserving the distinction between invalid query input and broken static
queries or schema drift.

---

Outside diff comments:
In `@pkg/db/sql_helpers.go`:
- Around line 72-73: Update getField so non-spec. inputs are not returned
unchanged: validate them against a strict identifier grammar or resolve them
through an allowlist and quote/map them before they reach sq.Expr. Preserve the
existing handling for valid spec.-prefixed fields while rejecting any
unsupported identifier input.

---

Nitpick comments:
In `@pkg/db/transaction_middleware.go`:
- Around line 79-84: Add direct table-driven unit tests for
IsUndefinedColumnError covering nil, a wrapped *pq.Error with code 42703, a
different PostgreSQL code, and a non-pq error. Assert only the expected boolean
classification for each case, including wrapped errors, to protect the exported
classifier’s behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: a5c85b26-8a02-4166-9740-65a60cf7c44f

📥 Commits

Reviewing files that changed from the base of the PR and between a59d594 and 6a124b6.

📒 Files selected for processing (7)
  • pkg/db/sql_helpers.go
  • pkg/db/sql_helpers_test.go
  • pkg/db/transaction_middleware.go
  • pkg/services/generic.go
  • pkg/services/generic_test.go
  • test/integration/order_field_mapping_test.go
  • test/integration/search_field_mapping_test.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift-hyperfleet/architecture (manual)
  • openshift-hyperfleet/hyperfleet-api (manual)
  • openshift-hyperfleet/hyperfleet-sentinel (manual)
  • openshift-hyperfleet/hyperfleet-adapter (manual)
  • openshift-hyperfleet/hyperfleet-broker (manual)
💤 Files with no reviewable changes (2)
  • pkg/services/generic_test.go
  • pkg/db/sql_helpers_test.go

Comment thread pkg/db/sql_helpers.go
Comment on lines 732 to +734
var orderPattern = regexp.MustCompile(`^[a-z_][a-z_]*(\s+(asc|desc))?$`)

// ArgsToOrder validates and cleans order arguments against the allowed fields whitelist.
// ArgsToOrder validates and cleans order arguments.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file map ==\n'
fd -a 'sql_helpers.go|.*\.go$' pkg/db || true

printf '\n== relevant ranges in pkg/db/sql_helpers.go ==\n'
nl -ba pkg/db/sql_helpers.go | sed -n '680,840p'

printf '\n== search for getField and order helpers ==\n'
rg -n "func .*getField|orderPattern|ArgsToOrder|ArgsToSearch|regexp.MustCompile|field contract|dotted" pkg/db/sql_helpers.go pkg/db -g '*.go'

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 1517


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== pkg/db/sql_helpers.go around order helpers ==\n'
sed -n '720,820p' pkg/db/sql_helpers.go | cat -n

printf '\n== pkg/db/sql_helpers.go search for getField ==\n'
rg -n "func .*getField|getField\\(|orderPattern|ArgsToOrder|ArgsToSearch|fieldPattern|regexp.MustCompile" pkg/db/sql_helpers.go pkg/db/sql_helpers_test.go -g '*.go'

printf '\n== order/search tests ==\n'
sed -n '1,260p' pkg/db/sql_helpers_test.go | cat -n

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 14295


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== getField implementation ==\n'
sed -n '1,120p' pkg/db/sql_helpers.go | cat -n

printf '\n== ArgsToOrder tests ==\n'
sed -n '940,1115p' pkg/db/sql_helpers_test.go | cat -n

printf '\n== ArgsToOrder call sites ==\n'
rg -n "ArgsToOrder\\(" -g '*.go' .

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 11023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== pkg/services/generic.go around order handling ==\n'
sed -n '100,180p' pkg/services/generic.go | cat -n

printf '\n== any order-field allowlists / mappers ==\n'
rg -n "allowed.*order|order.*allowed|Order.*field|field.*Order|ArgsToOrder|Sort|orderBy|OrderBy" pkg/services pkg/db -g '*.go'

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 4176


Align order-field validation with the existing field grammar (CWE-20). ArgsToOrder only accepts [a-z_][a-z_]*, so digit-bearing names and dotted paths are rejected before the DB layer, even though getField already accepts nested spec.* paths. Reuse the same field parser here, or document that sorting is limited to flat lowercase columns only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/db/sql_helpers.go` around lines 732 - 734, Update ArgsToOrder and its
orderPattern validation to use the same field grammar as getField, allowing
valid digit-bearing names and nested spec.* paths while retaining the existing
direction handling and safety checks; only restrict sorting to flat lowercase
columns if that limitation is explicitly documented.

Comment thread pkg/services/generic.go
Comment on lines +281 to +282
case db.IsUndefinedColumnError(err):
return errors.BadRequest("invalid field in search or order query")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== generic.go around the reported lines =="
sed -n '240,330p' pkg/services/generic.go

echo
echo "== where db.IsUndefinedColumnError is defined/used =="
rg -n "IsUndefinedColumnError|undefined_column|BadRequest\\(\"invalid field in search or order query\"\\)" pkg -S

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 3859


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== db.IsUndefinedColumnError definition =="
sed -n '1,140p' pkg/db/transaction_middleware.go

echo
echo "== search/order query construction in generic service =="
rg -n "search|order|Sort|Order|FieldNameWalk|tslTree|walkFn|BadRequest\\(" pkg/services/generic.go -n -S

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 5714


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== GenericDao interface and Fetch implementations =="
rg -n "type GenericDao|func .*Fetch\\(" pkg -S

echo
echo "== Fetch definitions with surrounding context =="
for f in $(rg -l "func .*Fetch\\(" pkg -S); do
  echo "--- $f ---"
  sed -n '1,240p' "$f"
  echo
done

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 6342


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== buildOrderBy and search pipeline =="
sed -n '120,240p' pkg/services/generic.go

echo
echo "== ArgsToOrder / FieldNameWalk definitions =="
rg -n "func ArgsToOrder|func FieldNameWalk|ExtractConditionQueries|ExtractLabelQueries|IdentWalk" pkg -S

Repository: openshift-hyperfleet/hyperfleet-api

Length of output: 5998


Do not map every undefined_column to 400. (CWE-703) d.Fetch can surface 42703 from a broken static query or schema drift, not just user-supplied search/order fields. Only convert tagged search/order errors to BadRequest; leave the rest as server errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/services/generic.go` around lines 281 - 282, Update the error handling
around d.Fetch and the db.IsUndefinedColumnError(err) case so only errors
explicitly tagged as originating from user-supplied search or order fields
return errors.BadRequest. Propagate untagged undefined-column errors through the
existing server-error path, preserving the distinction between invalid query
input and broken static queries or schema drift.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant