Skip to content

Imported opfs_path is trusted, allowing deletion of any file in the origin's OPFS #18

Description

@BootBlock

A .mpcweb file carries each sample's opfs_path, and the import trusts it verbatim. That path is later passed to deleteFile and readFile, so a shared project file can point the app at any file in its own OPFS — including the database.

The path

Schema (src/core/project/mpcweb.ts):

opfs_path: z.string(),

Inserted unchanged (src/core/project/snapshotService.ts):

opfs_path: sample.opfs_path,

Consumed (src/features/browser/BrowserPanel.tsx, the "Purge unused samples" action):

await deleteFile(sample.opfs_path);

and read in src/core/audio/sampleEditService.ts:

const file = await readFile(row.opfs_path);

remapSnapshot only rewrites this field if it happens to contain an old UUID — an attacker simply omits the id from the path.

Concrete scenario

A shared .mpcweb sets samples[0].opfs_path = "/bangerbox.sqlite3" and gives the sample a name the user will plausibly purge. One purge or delete destroys the entire project database — every project, not just the imported one.

Scope of the impact

Directory escape is blocked: splitOpfsPath in src/core/storage/opfs.ts independently rejects .., . and empty segments, so this is confined to the origin's own OPFS and cannot reach the wider filesystem. That is why this is medium rather than critical — but "wipe the user's entire library" is still the worst outcome the app can produce.

Suggested fix

The writer already derives the real path from samplePath(projectId, newId) using a freshly generated UUID, so the imported value is redundant — the stored row and the actual file agree today only by coincidence. Either:

  1. Ignore the imported opfs_path entirely and recompute it (preferred — removes the trust relationship rather than validating it), or
  2. Constrain it in the schema to the canonical ^/projects/<uuid>/samples/<uuid>\.wav$ shape.

Worth also reviewing whether deleteFile should refuse any path outside /projects/<id>/samples/ and /global_library/ as a defence in depth.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdata-lossCan lose or silently corrupt the user's workimport-exportProject interchange, bounce, and .mpcweb (spec 9.5/9.6)securitySecrets handling, privacy, and security concernsstorageOPFS, SQLite, repositories, and persistence (spec 9)

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions