{"record":{"id":"cb0fb4fe8c5f91dd","repo":"hasura/graphql-engine","slug":"the-fullpath-q-does-not-extend-the-sub-fullpath","errorCode":null,"errorMessage":"the fullPath %q does not extend the sub-fullPath %q: %w","messagePattern":"the fullPath %q does not extend the sub-fullPath %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/plugins/plugins.go","lineNumber":340,"sourceCode":"\t\t\tfmt.Errorf(\"failed to get the absolute fullPath of %q: %w\", installDir, err),\n\t\t)\n\t}\n\n\tfullPath := filepath.Join(installDir, filepath.FromSlash(platform.Bin))\n\n\tpathAbs, err := filepath.Abs(fullPath)\n\tif err != nil {\n\t\treturn errors.E(\n\t\t\top,\n\t\t\tfmt.Errorf(\"failed to get the absolute fullPath of %q: %w\", fullPath, err),\n\t\t)\n\t}\n\n\tif _, ok := IsSubPath(subPathAbs, pathAbs); !ok {\n\t\tif err != nil {\n\t\t\treturn errors.E(\n\t\t\t\top,\n\t\t\t\tfmt.Errorf(\n\t\t\t\t\t\"the fullPath %q does not extend the sub-fullPath %q: %w\",\n\t\t\t\t\tfullPath,\n\t\t\t\t\tinstallDir,\n\t\t\t\t\terr,\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\n\t\treturn nil\n\t}\n\n\terr = createOrUpdateLink(binDir, fullPath, plugin.Name)\n\tif err != nil {\n\t\treturn errors.E(op, fmt.Errorf(\"failed to link installed plugin: %w\", err))\n\t}\n\n\treturn nil\n}","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/plugins/plugins.go#L322-L358","documentation":"Emitted when the resolved plugin binary path (installDir joined with platform.Bin) does not lie inside the plugin's installation directory, as verified by IsSubPath. This is a path-traversal guard: a plugin spec whose bin field escapes the install dir (e.g. ../../evil) or is absolute would otherwise let the installer link an arbitrary executable into the bin directory.","triggerScenarios":"Config.Install or Config.Upgrade of a plugin whose spec declares platform.Bin as an absolute path or one containing ../ segments that resolve outside PluginVersionInstallPath(name, version). Note the guard is inverted/buggy (err is nil at this point) so the %w wraps a nil error.","commonSituations":"Installing a third-party/malicious plugin index with a crafted bin field; a plugin spec authored on Windows with backslashes that defeat the FromSlash+Join containment check; hand-edited local plugin manifests.","solutions":["Inspect the plugin spec's platforms[].bin — it must be a plain relative path under the archive root","Reinstall from the official plugin index or a trusted source","If you maintain the spec, change bin to a relative path like bin/myplugin and re-publish","If the path looks valid, report the bug — the check can also misfire on Windows path separators and wraps a nil error"],"exampleFix":"// before (plugin spec)\n\"platforms\": [{\"bin\": \"../../usr/bin/tailshell\"}]\n// after\n\"platforms\": [{\"bin\": \"bin/tailshell-linux-amd64\"}]","handlingStrategy":"validation","validationCode":"installDir := paths.PluginVersionInstallPath(p.Name, p.Version)\nbin := filepath.Join(installDir, filepath.FromSlash(p.Bin))\nif _, ok := plugins.IsSubPath(installDir, bin); !ok {\n    return fmt.Errorf(\"plugin %s bin escapes install dir\", p.Name)\n}","typeGuard":null,"tryCatchPattern":"if err := plugins.Install(p, platform); err != nil {\n    if strings.Contains(err.Error(), \"does not extend the sub-fullPath\") {\n        // reject/migrate this plugin spec; do not trust its bin field\n    }\n}","preventionTips":["Only install plugins from trusted indexes","Audit third-party plugin specs for absolute or ../-containing bin paths"],"tags":["security","path-traversal","plugin-install","plugin-spec"],"backgroundTag":"path-traversal-blocked","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}