From ac3926c7dba5a2435e40e4b3748b36c729416cba Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Thu, 10 Sep 2026 19:56:01 -0700 Subject: [PATCH] fix(earthquakes): reject malformed feature properties --- CHANGELOG.md | 2 ++ docs/CURRENT-STATE.md | 2 ++ src/data/earthquakes.js | 1 + src/data/earthquakes.test.mjs | 13 +++++++++++++ 4 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc58e8fd8..0d2fe2a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Earthquake refreshes validate the complete feed and construct replacement entities before clearing the previous snapshot. Malformed rows and duplicate rendered IDs retain the last good entities, overlays, count and timestamp and report a malformed response; unknown magnitude is excluded from M2.5+ rendering. +Non-object or array-valued properties reject the response instead of being treated as an unknown magnitude. + This changelog records public product changes. For the authoritative description of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md). diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index bfd9683ae..4132fde82 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -4,6 +4,8 @@ Earthquake refreshes validate the complete feed and construct replacement entities before clearing the previous snapshot. Malformed rows and duplicate rendered IDs retain the last good entities, overlays, count and timestamp and report a malformed response; unknown magnitude is excluded from M2.5+ rendering. +Non-object or array-valued properties reject the response instead of being treated as an unknown magnitude. + Updated: August 24, 2026 ## Installations and map-source guidance diff --git a/src/data/earthquakes.js b/src/data/earthquakes.js index 476b72c18..cb4d3ac13 100644 --- a/src/data/earthquakes.js +++ b/src/data/earthquakes.js @@ -130,6 +130,7 @@ export function normalizeEarthquakeSnapshot(geojson) { const coordinates = feature?.geometry?.coordinates; const properties = feature?.properties; if (!Array.isArray(coordinates) || coordinates.length < 2 || !properties + || typeof properties !== 'object' || Array.isArray(properties) || (feature.geometry.type != null && feature.geometry.type !== 'Point')) return null; const [lon, lat, depthKm] = coordinates; const mag = properties.mag; diff --git a/src/data/earthquakes.test.mjs b/src/data/earthquakes.test.mjs index cee572ee3..8119a6dc7 100644 --- a/src/data/earthquakes.test.mjs +++ b/src/data/earthquakes.test.mjs @@ -359,6 +359,19 @@ test('malformed earthquake refresh preserves entities, overlays, count and times assert.equal(await layer.update(viewer), true); const entity = dataSources[0].entities.values[0]; const stats = layer.getStats(); + for (const properties of ['invalid', 123, [], true]) { + const bad = { ...good, id: 'bad-properties', properties }; + for (const features of [[bad], [good, bad]]) { + respond(features); + assert.equal(await layer.update(viewer), false); + assert.equal(dataSources[0].entities.values.length, 1); + assert.equal(dataSources[0].entities.values[0], entity); + assert.equal(layer.getStats().count, stats.count); + assert.equal(layer.getStats().lastUpdate, stats.lastUpdate); + assert.equal(layer.getStats().error, 'Malformed USGS response'); + assert.equal(publications.length, 1); + } + } for (const bad of [null, { ...good, geometry: null }, { ...good, geometry: { type: 'LineString', coordinates: [1, 2] } }, { ...good, geometry: { coordinates: [181, 20] } },