Skip to content

Apps: validate Windows profile dir names and reject reserved app IDs at install (M/L)#801

Open
Rigidity wants to merge 1 commit into
appsfrom
fix/apps-id-storage-validation
Open

Apps: validate Windows profile dir names and reject reserved app IDs at install (M/L)#801
Rigidity wants to merge 1 commit into
appsfrom
fix/apps-id-storage-validation

Conversation

@Rigidity

@Rigidity Rigidity commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Part of the security review follow-ups for #785 (Medium/Low severity, identity & storage validation theme). Targets the apps mirror branch.

Findings addressed

M: WindowsProfile.directory_name used without validation (types/storage.rs, lifecycle/storage.rs)
The directory name stored in the database is joined onto the app data dir and passed to remove_dir_all during storage cleanup (and used as the webview data_directory on Windows). A tampered row like ".." or "..\\evil" could traverse out of the profiles directory and delete arbitrary data. Deserialization now rejects anything that isn't a single safe path segment (ASCII alphanumeric plus -/_), which covers every DB-load path while still accepting the legitimate profile-<uuid> and builtin-profile-<id> names.

L: reserved __sage_test_ / system IDs aren't rejected at install (lifecycle/install.rs)
Apps with the __sage_test_ prefix bypass the sandbox launch gate (sandbox/gate.rs), so an installed app must never be able to claim a reserved ID. Today the zip/url ID generators can't produce one (slugification strips underscores), but that was a coincidence rather than an invariant. Installs now explicitly reject IDs with the __sage_test_ / __sage_runtime_ prefixes or that exactly match a builtin system app ID.

Notes

  • Unit tests cover accepted/rejected directory names (via serde round-trip) and reserved-ID rejection.
  • cargo clippy --all-targets and the new unit tests pass locally; relying on CI for the full build.

Note

Medium Risk
Changes guard install identity and filesystem paths used during storage cleanup—important security boundaries, but scoped validation with tests and no broad behavior refactors.

Overview
Hardens app install and persisted Windows storage handling from security review follow-ups.

Install path: Before registering a new app, ensure_installable_app_id rejects IDs with the __sage_test_ or __sage_runtime_ prefixes and any ID that matches a builtin system app (e.g. task-manager). That closes a gap where reserved IDs could bypass sandbox launch rules or impersonate built-ins, even if current slug generators never produced those IDs.

Windows profiles: SageAppStorage::WindowsProfile now deserializes directory_name through validation that only allows a single safe segment (ASCII alphanumeric plus -/_). Tampered DB values like .. or paths with separators fail at load time, since those names are joined under app data and used for cleanup (remove_dir_all) and webview data dirs.

RUNTIME_ID_PREFIX is exported from builtin app constants for the install check. Unit tests cover reserved-ID rejection/acceptance and serde behavior for profile names.

Reviewed by Cursor Bugbot for commit 95d5ea3. Bugbot is set up for automated code reviews on this repo. Configure here.

Windows profile directory names loaded from the database are now
validated on deserialize (single safe path segment only), so a tampered
storage row like ".." can no longer traverse out of the profiles
directory when it is later joined and passed to remove_dir_all during
storage cleanup.

Installs now structurally reject app IDs that use the reserved
__sage_test_ / __sage_runtime_ prefixes or collide with builtin system
app IDs, instead of relying on the ID generators never producing them.
Sandbox-test IDs in particular bypass the launch gate, so an installed
app must never be able to claim one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant