Repository navigation
fix(geoloc): reject non-numeric bounding box params with a 400 (#2000) - #2003
Conversation
- checkAndGetCoordinatesParams now checks that each coordinate is a finite decimal or exponent number before the range check; a comparison between a non-numeric string and a number is always false, so such values reached Postgres and failed with 22P02, sent back as a 500 - reject empty strings, hexadecimal, NaN, Infinity, overflowing exponents and repeated parameters, naming every offending parameter - covers all eight geoloc endpoints, GET and HEAD alike - document non-numeric coordinates in the 400 of GET /geoloc/entrances
Paul-AUB
left a comment
There was a problem hiding this comment.
Changes requested; two Must Fix findings are attached inline.
Validation: 20 direct service validation assertions passed, the OpenAPI YAML parsed, and the changed JavaScript files passed ESLint with checkout CRLF normalized in memory. The targeted integration run could not start because the local test database refused connections. Additional isolated checks used PostgreSQL 18.6 through PGlite and a temporary Node HTTP server.
…2000) - Return the parsed numbers from checkAndGetCoordinatesParams so the queries never bind a raw string Postgres rejects ('1e-400' underflows, a value padded with a non-breaking space is invalid input) - Require the decimal point before the fractional digits, so a long rejected value no longer backtracks quadratically - Cover underflow, Unicode whitespace and a 15000-digit value
Paul-AUB
left a comment
There was a problem hiding this comment.
Approved on commit 7bdb7a1. The two previous Must Fix findings are addressed, and I found no additional actionable issues in the updated diff or its callers.
Validation: 25 isolated service validation cases passed, including normalized numeric bounds; a 15,001-character rejected input completed in 0.09 ms; the OpenAPI YAML parsed. The targeted integration suite could not start because the local PostgreSQL connection was refused. All current PR CI checks pass.
🤔 What
GeoLocService.checkAndGetCoordinatesParamsnow checks that each ofsw_lat,sw_lng,ne_latandne_lngis a finite number before range-checking it, and answers400naming every non-numeric parameter, e.g.South west latitude value must be a number (value found: {t[0]}).GETandHEAD.assets/swaggerV1.yaml: the400ofGET /geoloc/entrancesnow mentions non-numeric coordinates.Closes #2000
🤷♂️ Why
GETandHEAD /api/v1/geoloc/entrances?sw_lat={t[0]}&…returned 500. The validation only range-checked the values, and a comparison between a non-numeric string and a number is always false, so the value passed and reached Postgres, which rejected it with22P02(invalid input syntax for type double precision). A single 5xx fires the AzureHttp5xx >= 1alert, and the right answer for bad input is a 400.🔍 How
A new
parseCoordinatehelper returns the number to bind, ornullwhen the value is not a coordinate. It accepts a finite number, or a string that, once trimmed, matches decimal or exponent notation (^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$, case-insensitive) and converts to a finite number.Number()alone is not enough: it reads''and' 'as0and accepts0x10, which Postgres rejects. The finiteness check also rejectsNaN,Infinityand1e400, which overflows in Postgres too. A repeated parameter (an array) is rejected as well. The fractional digits require the decimal point, so no two digit runs compete for the same characters and a long rejected value is matched in linear time.checkAndGetCoordinatesParamsreturns the parsed numbers insouthWestBoundandnorthEastBound. Binding the raw string would still fail on valuesNumber()reads but Postgres does not:1e-400underflows (22003), and a value padded with a non-breaking space is invalid input (22P02). They are now bound as0and as the number itself.A non-numeric value skips the range check, so it does not also get a misleading range error. The comment in
validateBoundingBoxAreathat said such values "fail later in Postgres" is updated: they are now rejected earlier.🧪 Testing
test/integration/1_services/GeoLocService.test.jscover rejected values ({t[0]},abc,'',' ',0x10,1,2,NaN,Infinity,1e400, a repeated parameter), accepted values (45,-45.5,+3,.5,5.,1e1,' 12 ', numbers), the parsed numbers returned for1e-400, a non-breaking space, padding and a leading+, a 15000-digit value rejected in under 50 ms, naming of every non-numeric parameter, and the range check on numeric strings.test/integration/4_routes/Geoloc.test.jssend the URL from the issue withGET(400, with the parameter named) andHEAD(400), and check thatsw_lat=1e-400and a value padded with a non-breaking space answer 200. The existing?sw_lat=abctest now also expects a 400.npm run test: 6161 passing, 0 failing.npm run lint: clean.Manual check against a dev server:
should answer
[400]with a message naming all four parameters.📸 Previews
No UI change. Example response body: