Summary
The app listens to window.postMessage and trusts incoming message data without validating
event.origin or event.source.
As a result, any page that can obtain a window reference to satvis (most practically via iframe
embedding or popup/opener relationship) can send crafted messages like { start: "..." } and force
satvis to call setTime().
This is a client-side integrity issue: it allows unauthorized manipulation of simulation time and pass/
timeline view state.
Affected Version
Observed on branch next, commit 883147e (checked on 2026-03-19).
Affected Code
1. `src/modules/CesiumController.js`
```js
window.addEventListener("message", (e) => {
const pass = e.data;
if ("start" in pass) {
this.setTime(pass.start);
}
});
2. src/modules/util/DescriptionHelper.js (related exposure amplifier)
parent.postMessage(..., "*")
## Vulnerability Type
- Missing origin/source verification for cross-window messaging
- CWE-346 (Origin Validation Error) / CWE-940 (Improper Verification of Source of a Communication
Channel)
Real-World Impact
This does not change backend data or TLE source data, but it does affect real user operations inside
the session:
- Manipulates simulation clock/time window (viewer.clock.currentTime/startTime/stopTime)
- Alters displayed satellite position/trajectory at “current time”
- Affects pass countdown and timeline highlighting
- Can mislead users making observation/planning decisions from the UI
- Can be abused for repeated forced time jumps (UI disruption / soft DoS)
Exploitation Preconditions
Attacker must be able to message the satvis window, e.g.:
- satvis is embedded in attacker-controlled page (iframe), or
- popup/opener relationship exists between attacker page and satvis.
Given the repository includes embedding support (embedded.html) and no frame restrictions are defined
in public/_headers, this is practically reachable in typical deployments unless server-side headers
block framing.
Reproduction (minimal)
- Run satvis locally (e.g. npm run dev, assume http://127.0.0.1:5173).
- Host this attacker page on another origin/port (e.g. http://127.0.0.1:8001):
<!doctype html>
<iframe id="target" src="http://127.0.0.1:5173" width="1200" height="700"></iframe>
Send forged message
- Click the button and observe satvis timeline/time jump.
Expected vs Actual
- Expected: Only trusted sender (intended InfoBox frame) and trusted origin should be allowed to
request time changes.
- Actual: Any sender with window reference can trigger setTime() by sending {start: ...}.
Suggested Fix
In CesiumController.js message handler:
- Validate event.origin against strict allowlist (at minimum window.location.origin).
- Validate event.source equals expected InfoBox frame contentWindow.
- Validate message schema (data object, start string, valid timestamp).
- Ignore invalid/untrusted messages safely.
In DescriptionHelper.js:
- Replace targetOrigin="*" with explicit expected origin.
Optional defense-in-depth:
- If possible, tighten InfoBox iframe sandbox permissions.
Summary
The app listens to
window.postMessageand trusts incoming message data without validatingevent.originorevent.source.As a result, any page that can obtain a window reference to satvis (most practically via iframe
embedding or popup/opener relationship) can send crafted messages like
{ start: "..." }and forcesatvis to call
setTime().This is a client-side integrity issue: it allows unauthorized manipulation of simulation time and pass/
timeline view state.
Affected Version
Observed on branch
next, commit883147e(checked on 2026-03-19).Affected Code
Real-World Impact
This does not change backend data or TLE source data, but it does affect real user operations inside
the session:
Exploitation Preconditions
Attacker must be able to message the satvis window, e.g.:
Given the repository includes embedding support (embedded.html) and no frame restrictions are defined
in public/_headers, this is practically reachable in typical deployments unless server-side headers
block framing.
Reproduction (minimal)
<!doctype html>
<iframe id="target" src="http://127.0.0.1:5173" width="1200" height="700"></iframe> Send forged messageExpected vs Actual
request time changes.
Suggested Fix
In CesiumController.js message handler:
In DescriptionHelper.js:
Optional defense-in-depth: