@@ -175,6 +175,15 @@ class Api
175175 'STRICT_TYPING ' => true ,
176176 'AUTH_STRATEGY_DISPATCHER ' => 'off ' ,
177177 'KYTE_ACTIVITY_LOG_MAX_FIELD_BYTES ' => 16384 ,
178+ // Pagination guardrails (KYTE-#190). KYTE_MAX_PAGE_SIZE clamps a
179+ // client-supplied X-Kyte-Page-Size (industry norm ~100). When a list
180+ // request carries no page index it would otherwise return every row;
181+ // KYTE_MAX_UNBOUNDED_ROWS is a generous backstop so it can't pull a
182+ // whole large table (measure the truncation log, then tighten toward
183+ // paginate-by-default). Controller-layer only — internal Model::retrieve
184+ // stays unbounded. Both overridable per install in config.php.
185+ 'KYTE_MAX_PAGE_SIZE ' => 100 ,
186+ 'KYTE_MAX_UNBOUNDED_ROWS ' => 10000 ,
178187 ];
179188
180189 /**
@@ -369,6 +378,27 @@ public static function addKyteAttributes(&$modeldef) {
369378 ];
370379 }
371380
381+ /**
382+ * Clamp a requested page size to a sane range (KYTE-#190 pagination
383+ * guardrail): capped at $max, and falling back to $default for a
384+ * non-positive value. Pure/static for unit testing.
385+ *
386+ * @param mixed $requested Raw client-supplied page size
387+ * @param int $max Hard maximum (KYTE_MAX_PAGE_SIZE)
388+ * @param int $default Fallback when the request is non-positive
389+ * @return int
390+ */
391+ public static function clampPageSize ($ requested , $ max , $ default ) {
392+ $ requested = intval ($ requested );
393+ if ($ requested < 1 ) {
394+ return intval ($ default );
395+ }
396+ if ($ requested > $ max ) {
397+ return intval ($ max );
398+ }
399+ return $ requested ;
400+ }
401+
372402 /**
373403 * Sets database credentials to the default database.
374404 */
@@ -1040,8 +1070,15 @@ private function validateRequest()
10401070 }
10411071 }
10421072
1043- // set page size
1044- $ this ->page_size = isset ($ _SERVER ['HTTP_X_KYTE_PAGE_SIZE ' ]) ? intval ($ _SERVER ['HTTP_X_KYTE_PAGE_SIZE ' ]) : PAGE_SIZE ;
1073+ // set page size — pagination guardrail (KYTE-#190): clamp a client-
1074+ // supplied X-Kyte-Page-Size to KYTE_MAX_PAGE_SIZE (falling back to the
1075+ // default for a non-positive value) so no request can demand an
1076+ // oversized page.
1077+ $ this ->page_size = self ::clampPageSize (
1078+ isset ($ _SERVER ['HTTP_X_KYTE_PAGE_SIZE ' ]) ? $ _SERVER ['HTTP_X_KYTE_PAGE_SIZE ' ] : 0 ,
1079+ KYTE_MAX_PAGE_SIZE ,
1080+ PAGE_SIZE
1081+ );
10451082 // get page num from header
10461083 $ this ->page_num = isset ($ _SERVER ['HTTP_X_KYTE_PAGE_IDX ' ]) ? intval ($ _SERVER ['HTTP_X_KYTE_PAGE_IDX ' ]) : 0 ;
10471084
0 commit comments