Skip to content

Path traversal writes a blob resource outside the project folder via resource metadata #9259

Open

Description

@carfeii

Summary

Affected versions: confirmed on commit 1de9199bb0bc0c9db3cc51fc3155db8955a25e10

When "moving resources to local", a blob-URL resource's local destination path is taken from project-controlled resource metadata and used directly to build a filesystem path with no check that it stays inside the project folder, allowing a crafted project to write a downloaded resource outside its own folder.

Details

newIDE/app/src/ProjectsStorage/LocalFileStorageProvider/LocalFileResourceMover.js:

if (isBlobURL(resourceFile)) {
  try {
    const {
      localFilePath,
      extension,
    } = parseLocalFilePathOrExtensionFromMetadata(resource);
    const downloadedFilePath = localFilePath
      ? path.resolve(projectPath, localFilePath)
      : generateUnusedFilepathFromResourceName(
          baseAssetsPath,
          downloadedFilePaths,
          resource.getName(),
          extension || ''
        );

    await fs.ensureDir(baseAssetsPath);
    await fs.ensureDir(path.dirname(downloadedFilePath));
    await downloadBlobToLocalFile(resourceFile, downloadedFilePath);
    ...

localFilePath comes from parseLocalFilePathOrExtensionFromMetadata(resource), which reads it out of the resource's own metadata, part of the project's content. There is no check that path.resolve(projectPath, localFilePath) stays within projectPath before fs.ensureDir(path.dirname(downloadedFilePath)) creates the destination directory and downloadBlobToLocalFile writes the fetched blob content there.

A resource whose metadata sets localFilePath to something like ../../../../some/file resolves outside the project folder entirely, so the downloaded content lands wherever that traversal points.

Steps To Reproduce

(available upon request)

Impact

A crafted or modified project, when its resources are moved to local storage (a normal part of the local-file workflow), can write attacker-chosen content to an attacker-chosen path outside the project folder, on the filesystem of whoever opens that project.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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