Fix nil access bugs found in security/bug audit

- TerrainProfileWorker: guard pos1/pos2 nil before accessing lat/lon,
  mark unavailable if missing instead of crashing
- Propagation analysis: guard pos1 nil in compute_factors
- contact_path_points: return [] instead of [{nil, nil}] on missing coords
- JS elevation hook: null check canvas before getContext
This commit is contained in:
Graham McIntire 2026-04-02 12:38:49 -05:00
parent 1cf92b2166
commit 1da1cbed43
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
4 changed files with 26 additions and 12 deletions

View file

@ -90,6 +90,7 @@ export const ElevationProfile = {
} }
const canvas = this.el.querySelector("canvas") const canvas = this.el.querySelector("canvas")
if (!canvas) return
const ctx = canvas.getContext("2d") const ctx = canvas.getContext("2d")
this.chart = new Chart(ctx, { this.chart = new Chart(ctx, {

View file

@ -153,12 +153,17 @@ defmodule Microwaveprop.Radio do
lat2 = pos2["lat"] lat2 = pos2["lat"]
lon2 = pos2["lon"] || pos2["lng"] lon2 = pos2["lon"] || pos2["lng"]
if lat1 && lon1 && lat2 && lon2 do cond do
mid_lat = (lat1 + lat2) / 2 lat1 && lon1 && lat2 && lon2 ->
mid_lon = (lon1 + lon2) / 2 mid_lat = (lat1 + lat2) / 2
[{lat1, lon1}, {mid_lat, mid_lon}, {lat2, lon2}] mid_lon = (lon1 + lon2) / 2
else [{lat1, lon1}, {mid_lat, mid_lon}, {lat2, lon2}]
[{lat1, lon1}]
lat1 && lon1 ->
[{lat1, lon1}]
true ->
[]
end end
end end

View file

@ -19,12 +19,13 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
:ok :ok
else else
contact = Radio.get_contact!(qso_id) contact = Radio.get_contact!(qso_id)
lat1 = contact.pos1["lat"]
lon1 = contact.pos1["lon"] || contact.pos1["lng"] with %{"lat" => lat1} <- contact.pos1,
lat2 = contact.pos2["lat"] lon1 when is_number(lon1) <- contact.pos1["lon"] || contact.pos1["lng"],
lon2 = contact.pos2["lon"] || contact.pos2["lng"] %{"lat" => lat2} <- contact.pos2,
dist_km = Decimal.to_float(contact.distance_km) lon2 when is_number(lon2) <- contact.pos2["lon"] || contact.pos2["lng"] do
freq_ghz = Decimal.to_float(contact.band) / 1000 dist_km = Decimal.to_float(contact.distance_km || Decimal.new(0))
freq_ghz = Decimal.to_float(contact.band) / 1000
# Look up HRRR refractivity gradient for dynamic k-factor # Look up HRRR refractivity gradient for dynamic k-factor
k = lookup_k_factor(contact) k = lookup_k_factor(contact)
@ -69,6 +70,11 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do
{:error, reason} -> {:error, reason} ->
{:error, reason} {:error, reason}
end end
else
_ ->
Radio.set_enrichment_status!([qso_id], :terrain_status, :unavailable)
:ok
end
end end
end end

View file

@ -1105,6 +1105,8 @@ defmodule MicrowavepropWeb.ContactLive.Show do
{nil, [], nil} {nil, [], nil}
end end
defp compute_factors(_hrrr, %{pos1: nil}, _band_config), do: {nil, [], nil}
defp compute_factors(hrrr, contact, band_config) do defp compute_factors(hrrr, contact, band_config) do
lon = contact.pos1["lon"] || contact.pos1["lng"] lon = contact.pos1["lon"] || contact.pos1["lng"]
temp_c = hrrr.surface_temp_c temp_c = hrrr.surface_temp_c