{"record":{"id":"b1262ca7905c9d7c","repo":"flarum/framework","slug":"importing-s-is-not-allowed","errorCode":null,"errorMessage":"Importing \"%s\" is not allowed.","messagePattern":"Importing \"(.+?)\" is not allowed\\.","errorType":"exception","errorClass":"Less_Exception_Parser","httpStatus":null,"severity":"error","filePath":"framework/core/src/Frontend/Compiler/LessCompiler.php","lineNumber":121,"sourceCode":"                continue;\n            }\n\n            $root = realpath($dir);\n\n            if ($root === false) {\n                continue;\n            }\n\n            $resolved = realpath($root.'/'.ltrim($path, '/\\\\'));\n\n            // realpath() has followed `..` and any symlink, so a path that\n            // still starts with the directory really is inside it.\n            if ($resolved !== false && str_starts_with($resolved, $root.DIRECTORY_SEPARATOR)) {\n                return [$resolved, null];\n            }\n        }\n\n        throw new Less_Exception_Parser(\n            sprintf('Importing \"%s\" is not allowed.', $path)\n        );\n    }\n\n    /**\n     * @throws \\Less_Exception_Parser\n     */\n    protected function compile(array $sources): string\n    {\n        if (! count($sources)) {\n            return '';\n        }\n\n        if (! empty($this->settings->get('custom_less_error'))) {\n            unset($sources['custom_less']);\n        }\n\n        $maxNestingLevel = ini_get('xdebug.max_nesting_level');","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/Frontend/Compiler/LessCompiler.php#L103-L139","documentation":"LessCompiler::containImports throws Less_Exception_Parser with 'Importing \"%s\" is not allowed.' when compiled LESS contains an @import whose resolved path escapes the permitted import root directory. Flarum sandboxes LESS imports to prevent arbitrary file reads during stylesheet compilation.","triggerScenarios":"A theme or extension LESS file contains @import with an absolute path, ../ traversal out of the allowed directory, or a path that cannot be resolved inside the root; triggered during frontend asset compilation (compile).","commonSituations":"Themes ported from standalone LESS projects importing external files; extensions shipping LESS with @import '../../shared/variables.less' after directory restructuring; custom styles attempting to import system files (blocked as a security measure).","solutions":["Change the @import to a relative path that resolves inside the allowed import root (the extension/theme's LESS directory).","Copy the imported file into the compiling package's directory and import it by filename.","Remove the @import and inline the needed variables/mixins, or have the extension register the LESS as a separate asset instead."],"exampleFix":"// before\n@import \"../../../../core/less/variables.less\";\n\n// after: copy variables.less next to this file\n@import \"variables.less\";","handlingStrategy":"validation","validationCode":"// before shipping LESS, verify imports resolve inside the package\nforeach (extractImports($less) as $path) {\n  $resolved = realpath(dirname($lessFile) . '/' . $path);\n  if ($resolved === false || !str_starts_with($resolved, $importRoot . DIRECTORY_SEPARATOR)) {\n    throw new RuntimeException(\"Import escapes root: $path\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n    $assets->makeCss()->commit();\n} catch (Less_Exception_Parser $e) {\n    // check the import path named in the message and fix it\n}","preventionTips":["Use relative imports that stay within the theme/extension's LESS directory.","Never use absolute paths or ../ traversal in shipped LESS.","Compile assets in CI so bad imports are caught before deployment.","Inline shared variables instead of cross-package imports."],"tags":["flarum","less","import","path-traversal","compile"],"backgroundTag":"path-traversal-blocked","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}