Skip to content

Untrusted postMessage can change simulation time (missing origin/source validation in CesiumController) #98

@Fuzz0X

Description

@Fuzz0X

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.:

  1. satvis is embedded in attacker-controlled page (iframe), or
  2. 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)

  1. Run satvis locally (e.g. npm run dev, assume http://127.0.0.1:5173).
  2. 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
  1. 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:

  1. Validate event.origin against strict allowlist (at minimum window.location.origin).
  2. Validate event.source equals expected InfoBox frame contentWindow.
  3. Validate message schema (data object, start string, valid timestamp).
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions