Skip to content

HYPERFLEET-1241 - fix: pagination parameter validation#232

Open
ldornele wants to merge 1 commit into
openshift-hyperfleet:mainfrom
ldornele:HYPERFLEET-1241
Open

HYPERFLEET-1241 - fix: pagination parameter validation#232
ldornele wants to merge 1 commit into
openshift-hyperfleet:mainfrom
ldornele:HYPERFLEET-1241

Conversation

@ldornele

Copy link
Copy Markdown
Contributor

Summary

Fixes pagination and ordering query parameter validation issues identified in code review.

Changes

  • Fix: Implement missing order parameter validation (asc/desc only)
  • Fix: Use int64 parsing for pageSize (was platform-dependent)
  • Fix: Trim whitespace when applying order direction to prevent malformed orderBy
  • Tests: Added validation and behavior tests for order parameter
  • Docs: Updated api-resources.md with ordering behavior examples

Testing

✅ All unit tests passing
✅ Added test coverage for order parameter edge cases

Related

  • Issue: HYPERFLEET-1241

@openshift-ci openshift-ci Bot requested review from jsell-rh and kuudori June 22, 2026 01:39
@openshift-ci

openshift-ci Bot commented Jun 22, 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 ldornele 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 Jun 22, 2026

Copy link
Copy Markdown
📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Added strict validation for pagination and ordering query parameters; invalid values now return 400 Bad Request with RFC 9457 Problem Details format instead of being silently ignored.
    • Enforced maximum page size limit of 100 entries.
  • Documentation

    • Updated API documentation with explicit pagination constraints, defaults, and ordering behavior rules.

Walkthrough

NewListArguments in pkg/services/types.go changes its signature from *ListArguments to (*ListArguments, *errors.ServiceError). It now validates page as a positive integer, pageSize within a new MaxPageSize constant (100), and order as strictly asc or desc, returning a 400 Bad Request ServiceError with RFC 9457 format on any violation. It also applies the order direction to orderBy fields that have no explicit direction suffix. All seven List/ListByOwner handlers are updated to capture and propagate this error. Tests and API documentation are updated to reflect the new constraints and ordering semantics.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


CWE-20 (Improper Input Validation) — the core fix. The prior silent clamp/ignore on page, pageSize, and order inputs was an input validation gap. Confirm strconv.Atoi parse failures on page and size are now fully covered in TestNewListArguments_Validation — non-numeric strings, empty strings, and negative values all warrant explicit cases.

CWE-703 (Improper Check or Handling of Exceptional Conditions) — verify applyFieldFilter in framework.go (range_96b610c27c9e): the returned error is *errors.ServiceError, but confirm the caller of applyFieldFilter properly converts it to an HTTP response and does not swallow it.

Supply chain / interface contract: the NewListArguments signature break is a compile-time contract change. Confirm no additional call sites exist (e.g., in Sentinel, Adapter, or Broker packages) that were not updated — a missed site would panic at runtime, not compile time, only if the old single-return pattern is retained via a wrapper.

Ordering injectionorder direction is appended to orderBy field strings. Confirm downstream SQL/query builders that consume ListArguments.OrderBy treat the direction suffix as a whitelist, not a raw string interpolation (CWE-89).

🚥 Pre-merge checks | ✅ 9 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
No Injection Vectors ⚠️ Warning CWE-20 Input Validation: Empty orderBy tokens (e.g., orderBy=name,,id&order=asc) bypass filtering and generate malformed SQL fragments. pkg/services/types.go line 102 uses strings.Split without fil... Implement review-proposed fix: replace strings.Split with strings.Fields, skip empty tokens with continue, and rebuild normalized []string to prevent malformed SQL ORDER BY clauses.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately describes the main change: fixing pagination parameter validation (order, pageSize, whitespace handling).
Description check ✅ Passed Description directly relates to the changeset, detailing order validation, pageSize parsing, whitespace handling, and test coverage additions.
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 statements (slog, log, logr, zap, fmt.Print*) found in any modified non-test files. Error messages only expose non-sensitive pagination/ordering parameters.
No Hardcoded Secrets ✅ Passed No hardcoded secrets, API keys, tokens, passwords, private keys, or embedded credentials found across 10 modified files. All test data uses acceptable placeholder/fixture values.
No Weak Cryptography ✅ Passed No weak cryptographic primitives, custom crypto implementations, or non-constant-time secret comparisons detected. PR modifies only pagination/ordering validation logic with no crypto operations.
No Privileged Containers ✅ Passed No Kubernetes manifests, Helm templates, or Dockerfiles are modified in this PR. All changes are Go source code and documentation for pagination/ordering parameter validation fixes.
No Pii Or Sensitive Data In Logs ✅ Passed No logging statements in modified code expose PII, credentials, session IDs, or raw request/response bodies. Error messages safely log only query parameter values (page/size numbers, order directio...

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@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

🤖 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 `@docs/api-resources.md`:
- Around line 688-691: The documented default value for the `orderBy` parameter
in the API resources table shows `created_time`, but the actual runtime default
from `NewListArguments` is `created_time desc`. Update the `orderBy` row in the
documentation table to change the default value from `created_time` to
`created_time desc` to align the documentation with the actual implementation
behavior.

In `@pkg/services/types.go`:
- Around line 111-120: The orderBy field processing loop in the section where
listArgs.OrderBy is modified does not filter out empty tokens, allowing
malformed entries like " asc" to be created when empty values are passed (e.g.,
"name,,created_time"). Add a validation check after trimming each field to skip
empty tokens and prevent them from being processed with the order direction
applied. Specifically, after creating trimmedField via strings.TrimSpace, check
if the length is zero and continue to the next iteration if so, ensuring only
non-empty fields receive the direction suffix.
🪄 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: 11340d16-364f-4c4c-ae7e-44e94e0e0cfd

📥 Commits

Reviewing files that changed from the base of the PR and between 24ec42b and 19669a7.

📒 Files selected for processing (10)
  • docs/api-resources.md
  • pkg/handlers/cluster.go
  • pkg/handlers/cluster_nodepools.go
  • pkg/handlers/cluster_status.go
  • pkg/handlers/framework.go
  • pkg/handlers/node_pool.go
  • pkg/handlers/nodepool_status.go
  • pkg/handlers/resource_handler.go
  • pkg/services/types.go
  • pkg/services/types_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)

Comment thread docs/api-resources.md
Comment on lines +688 to 691
| `page` | integer (int32)| No | `1` | Must be >= 1 |
| `pageSize` | integer (int32)| No | `20` | Must be between 1 and 100 |
| `orderBy` | string | No | `created_time` | Field name(s), optionally with direction |
| `order` | string | No | - | Must be `asc` or `desc` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align documented orderBy default with runtime value.

The table says default orderBy is created_time, but NewListArguments defaults to created_time desc. This mismatch can cause client-side expectation drift.

🤖 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 `@docs/api-resources.md` around lines 688 - 691, The documented default value
for the `orderBy` parameter in the API resources table shows `created_time`, but
the actual runtime default from `NewListArguments` is `created_time desc`.
Update the `orderBy` row in the documentation table to change the default value
from `created_time` to `created_time desc` to align the documentation with the
actual implementation behavior.

Comment thread pkg/services/types.go
Comment on lines +111 to +120
// Apply order direction to all orderBy fields that don't already have a direction
for i, field := range listArgs.OrderBy {
trimmedField := strings.TrimSpace(field)
parts := strings.Split(trimmedField, " ")
if len(parts) == 1 {
// Field has no direction specified, apply the order parameter
listArgs.OrderBy[i] = trimmedField + " " + v
}
// If field already has direction (e.g., "name asc"), leave it unchanged
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject empty orderBy tokens before applying order (CWE-20).

orderBy=name,,created_time&order=asc currently produces an invalid entry (" asc"), because empty tokens are not filtered before direction injection. That can propagate malformed sort clauses downstream.

Proposed fix
 	// Validate and apply order parameter (asc/desc direction)
 	if v := strings.Trim(params.Get("order"), " "); v != "" {
 		if v != "asc" && v != "desc" {
 			return nil, errors.New(
 				errors.CodeValidationFormat,
 				"Invalid order parameter: must be 'asc' or 'desc', got '%s'",
 				v,
 			)
 		}
-		// Apply order direction to all orderBy fields that don't already have a direction
-		for i, field := range listArgs.OrderBy {
-			trimmedField := strings.TrimSpace(field)
-			parts := strings.Split(trimmedField, " ")
-			if len(parts) == 1 {
-				// Field has no direction specified, apply the order parameter
-				listArgs.OrderBy[i] = trimmedField + " " + v
-			}
-			// If field already has direction (e.g., "name asc"), leave it unchanged
-		}
+		// Apply order direction to fields without explicit direction and skip empty tokens.
+		normalized := make([]string, 0, len(listArgs.OrderBy))
+		for _, field := range listArgs.OrderBy {
+			trimmedField := strings.TrimSpace(field)
+			if trimmedField == "" {
+				continue
+			}
+			parts := strings.Fields(trimmedField)
+			if len(parts) == 1 {
+				normalized = append(normalized, parts[0]+" "+v)
+				continue
+			}
+			normalized = append(normalized, strings.Join(parts, " "))
+		}
+		listArgs.OrderBy = normalized
 	}

As per coding guidelines, “Validate input at system boundaries (HTTP handlers, CLI parsers, webhook receivers).”

🤖 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/types.go` around lines 111 - 120, The orderBy field processing
loop in the section where listArgs.OrderBy is modified does not filter out empty
tokens, allowing malformed entries like " asc" to be created when empty values
are passed (e.g., "name,,created_time"). Add a validation check after trimming
each field to skip empty tokens and prevent them from being processed with the
order direction applied. Specifically, after creating trimmedField via
strings.TrimSpace, check if the length is zero and continue to the next
iteration if so, ensuring only non-empty fields receive the direction suffix.

Source: Coding guidelines

@openshift-ci

openshift-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown

@ldornele: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/lint 19669a7 link true /test lint

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@hyperfleet-ci-bot

Copy link
Copy Markdown

Risk Score: 2 — risk/medium

Signal Detail Points
PR size 378 lines (>200) +1
Sensitive paths none +0
Test coverage Missing tests for: pkg/handlers +1

Computed by hyperfleet-risk-scorer

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant