hasura/graphql-engine · warning
plugin name %q not allowed
Error message
plugin name %q not allowed
What it means
LoadPluginByName rejects the requested plugin name via IsSafePluginName before touching the filesystem. This is a path-traversal guard: names containing slashes, '..' segments, absolute paths, or characters outside the allowed pattern are refused so they cannot escape the plugins index directory.
Source
Thrown at cli/plugins/scanner.go:83
}
files, err := c.findPluginManifestFiles(indexDir)
if err != nil {
return nil, errors.E(op, fmt.Errorf("failed to scan plugins in index directory: %w", err))
}
return c.LoadPlugins(files), nil
}
// LoadPluginByName loads a plugins index file by its name. When plugin
// file not found, it returns an error that can be checked with stderrors.Is(err, fs.ErrNotExist).
func (c *Config) LoadPluginByName(pluginName string) (*PluginVersions, error) {
var op errors.Op = "plugins.Config.LoadPluginByName"
c.Logger.Debugf("loading plugin %s", pluginName)
if !IsSafePluginName(pluginName) {
return nil, errors.E(op, fmt.Errorf("plugin name %q not allowed", pluginName))
}
files, err := c.findPluginManifestFiles(c.Paths.IndexPluginsPath())
if err != nil {
return nil, errors.E(op, fmt.Errorf("failed to scan plugins in index directory: %w", err))
}
ps := c.LoadPlugins(files, pluginName)
if _, ok := ps[pluginName]; !ok {
return nil, errors.E(op, os.ErrNotExist)
}
return ps[pluginName], nil
}
func (c *Config) LoadPlugins(files []string, pluginName ...string) Plugins {
c.Logger.Debugf("loading plugins")
View on GitHub (pinned to 724551b9ae)
Solutions
- Sanitize/validate the name with plugins.IsSafePluginName before calling the API
- Strip path separators and '..' segments from user input, or reject such input at the boundary
- Use the exact plugin name shown by `plugin list` (usually lowercase alphanumeric with dashes)
Example fix
// before
p, err := cfg.GetPlugin(r.URL.Query().Get("name")) // "../etc/passwd" -> error
// after
name := r.URL.Query().Get("name")
if !plugins.IsSafePluginName(name) {
http.Error(w, "invalid plugin name", http.StatusBadRequest)
return
}
p, err := cfg.GetPlugin(name) Defensive patterns
Strategy: validation
Validate before calling
if !plugins.IsSafePluginName(name) { return fmt.Errorf("invalid plugin name: %q", name) } Type guard
func isValidPluginName(s string) bool {
if s == "" || len(s) > 100 { return false }
if strings.ContainsAny(s, "/\\") || strings.Contains(s, "..") { return false }
for _, r := range s {
if !(r >= 'a' && r <= 'z' || r >= '0' && r <= '9' || r == '-') { return false }
}
return true
} Prevention
- Validate plugin names at the input boundary (CLI args, HTTP params) before passing to plugin APIs
- Use the exact name reported by plugin list
- Never construct names by concatenating user input with paths
When it happens
Trigger: Calling Config.GetPlugin or Config.Upgrade with a name like "../secrets", "/etc/passwd", "foo/bar", an empty string, or any name failing the safe-name regex.
Common situations: User-supplied plugin names passed unvalidated from a script or web form; typos including path separators; programmatically constructed names that accidentally include a leading './' or Windows-style backslashes.
Related errors
- can't move, move target %v is not a subpath from=%q, to=%q
- can't move, move target %v is out of bounds from=%q, to=%q
- the fullPath %q does not extend the sub-fullPath %q: %w
- cannot create metadata files: %w
- failed to get the matching platform for plugin %s: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/92dc5e46cf64a2ad.
Report an issue: GitHub.