BookStackApp/BookStack · error · ThemeModuleException

Bad file path found in module ZIP file: {$name}

Error message

Bad file path found in module ZIP file: {$name}

What it means

ThemeModuleException thrown in ThemeModuleZip::extractTo when a ZIP entry's name yields an unsafe target path — FilePathNormalizer::normalize rejects paths attempting traversal (e.g. '../') outside the destination. Input at fault: a malicious or malformed entry name inside the module ZIP.

Source

Thrown at app/Theming/ThemeModuleZip.php:40

            $name = $zip->getNameIndex($i);
            $entryIsDir = str_ends_with($name, "/");
            if ($entryIsDir) {
                continue;
            }

            $stream = $zip->getStreamIndex($i);

            if ($prefix) {
                if (!str_starts_with($name, $prefix) || $name === $prefix) {
                    continue;
                }
                $name = str_replace($prefix, '', $name);
            }

            try {
                $targetPath = $destinationPath . DIRECTORY_SEPARATOR . FilePathNormalizer::normalize($name);
            } catch (\Exception $exception) {
                throw new ThemeModuleException("Bad file path found in module ZIP file: {$name}");
            }

            $targetPathDir = dirname($targetPath);
            if (!is_dir($targetPathDir)) {
                $dirCreated = mkdir($targetPathDir, 0777, true);
                if (!$dirCreated) {
                    throw new ThemeModuleException("Failed to create directory {$targetPathDir} when extracting module files");
                }
            }

            $targetFile = fopen($targetPath, 'w');
            $written = stream_copy_to_stream($stream, $targetFile);
            if (!$written) {
                throw new ThemeModuleException("Failed to write to {$targetPath} when extracting module files");
            }
            fclose($targetFile);
        }

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Reject/re-upload a module ZIP that contains path-traversal entries
  2. Obtain the module ZIP from a trusted source
  3. Inspect the ZIP's entry names for '../' or absolute paths before installing
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at app/Theming/ThemeModuleZip.php:40 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/ccea72bdc0aa34fa. Report an issue: GitHub.