Files
gps-denied-onboard/_docs/05_security/static_analysis.md
T
Oleksandr Bezdieniezhnykh ee6606a9c2 [AZ-243] Record security audit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-07 03:40:36 +03:00

2.8 KiB

Static Analysis

Date: 2026-05-07 Scope: Python source, tests, replay harness, tools, compose/config files Result: PASS_WITH_WARNINGS

Findings

ID Severity Category Location Title
S1 Medium Resource / Input Validation src/satellite_service/types.py:67 VPR index JSON is read fully without size limits
S2 Medium Security Misconfiguration docker-compose.yml:7, docker-compose.yml:9, .env.example:5 Development database credentials and exposed port are easy to reuse outside dev

Finding Details

S1: VPR index JSON is read fully without size limits

Location: src/satellite_service/types.py:67

LocalVprIndexPackage.from_json_file() reads the entire configured descriptor package into memory with Path(package_path).read_text() and then parses it with json.loads. The model validates record shape, but there is no file-size limit, descriptor-count limit, or explicit package path trust check at this boundary.

Impact: A malformed or unexpectedly large local descriptor package could exhaust memory or stall startup/readiness on a constrained Jetson target.

Remediation: Add a maximum package size check before reading, cap records and descriptor lengths in the Pydantic model, and ensure callers pass only cache-package paths that have already passed manifest/signature validation.

S2: Development database credentials and exposed port are easy to reuse outside dev

Locations:

  • docker-compose.yml:7
  • docker-compose.yml:9
  • .env.example:5

docker-compose.yml sets POSTGRES_PASSWORD=gpsd and exposes Postgres on 5432:5432. .env.example also embeds gpsd:gpsd in GPSD_DATABASE_URL. These are acceptable for local fixture use only if they are clearly kept out of production, but the default compose file name makes accidental reuse plausible.

Impact: If this compose file is copied into a staging or field environment, the database would run with known credentials and an exposed host port.

Remediation: Move the default password to an ignored local .env, rename or label the compose file as development-only, bind Postgres to 127.0.0.1 where host exposure is required, and add a production compose/deploy template that requires secret-manager sourced credentials.

Negative Checks

  • No SQL string construction or database execute() calls were found in source.
  • No eval, exec, os.system, shell=True, Pickle, marshal, weak hashes, TLS verification bypass, CORS wildcard, or hardcoded production secret patterns were found in source.
  • tools/remove_osd_lines.py uses subprocess.run() with an argument list and no shell; this is not command-injection prone in its current form.
  • Dockerfiles run as a non-root gpsd user.