BUG: POST /assets no input validation for duration — NaN stored when absent #69

Closed
opened 2026-05-25 04:07:41 -04:00 by zgaetano · 0 comments
Owner

Bug

In services/mam-api/src/routes/assets.js:82:

const durationMs = duration ? Math.round(duration * 1000) : null;

If req.body.duration is "" (empty string), JavaScript treats "" as falsy, so it correctly falls to null. But if req.body.duration is 0 (which should mean "zero-length clip"), it's also falsy and becomes null.

More importantly, if duration is an arbitrary non-number type that is truthy (e.g. "abc"), Math.round("abc" * 1000) = NaN, and NaN gets stored into duration_ms as a Postgres NaN value (postgres actually rounds NaN to NULL when the column is BIGINT, but this depends on driver behavior).

Impact

  • A NaN duration stored in the DB can cause issues in JS-side calculations later (e.g., NaN < 5 is false)
  • If the capture service somehow produces duration=0 (possible with a zero-frame recording that wasn't caught by the empty check), the asset gets duration_ms=NULL instead of 0

Location

services/mam-api/src/routes/assets.js:82

Fix

const durationMs = (duration !== undefined && duration !== null && Number.isFinite(Number(duration)))
  ? Math.round(Number(duration) * 1000) 
  : null;
## Bug In `services/mam-api/src/routes/assets.js:82`: ```js const durationMs = duration ? Math.round(duration * 1000) : null; ``` If `req.body.duration` is `""` (empty string), JavaScript treats `""` as falsy, so it correctly falls to `null`. But if `req.body.duration` is `0` (which should mean "zero-length clip"), it's also falsy and becomes `null`. More importantly, if `duration` is an arbitrary non-number type that is truthy (e.g. `"abc"`), `Math.round("abc" * 1000)` = `NaN`, and `NaN` gets stored into `duration_ms` as a Postgres `NaN` value (postgres actually rounds `NaN` to `NULL` when the column is `BIGINT`, but this depends on driver behavior). ## Impact - A `NaN` duration stored in the DB can cause issues in JS-side calculations later (e.g., `NaN < 5` is `false`) - If the capture service somehow produces `duration=0` (possible with a zero-frame recording that wasn't caught by the `empty` check), the asset gets `duration_ms=NULL` instead of `0` ## Location `services/mam-api/src/routes/assets.js:82` ## Fix ```js const durationMs = (duration !== undefined && duration !== null && Number.isFinite(Number(duration))) ? Math.round(Number(duration) * 1000) : null; ```
Sign in to join this conversation.
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: WildDragonLLC/dragonflight#69
No description provided.