fix(store): hide and refuse registry entries that aren't plugins

The skin filters went with the skin system, but a custom registry can still
list "type": "skin" entries, and installing one as a plugin would unpack it
into the plugins directory. PluginStoreManager.is_plugin_entry() (a missing
type means plugin) now hides non-plugin entries from the store and
custom-registry listings, and install refuses them, in the route with a
clear 400 and in _install_plugin_impl for any other caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-23 13:21:03 -04:00
co-authored by Claude Opus 5.5
parent 8c0f1966cf
commit 6ffff88038
3 changed files with 109 additions and 1 deletions
+15 -1
View File
@@ -1296,6 +1296,17 @@ def install_plugin():
plugin_id = data['plugin_id']
branch = data.get('branch') # Optional branch parameter
# A registry entry that isn't a plugin (a custom registry can still
# list old "type": "skin" entries) gets a clear refusal, not a failed
# install.
try:
registry_entry = api_v3.plugin_store_manager.get_registry_info(plugin_id)
except Exception:
registry_entry = None
if isinstance(registry_entry, dict) and not api_v3.plugin_store_manager.is_plugin_entry(registry_entry):
return jsonify({'status': 'error',
'message': f"{plugin_id} is a {registry_entry.get('type')!r} entry, not a plugin"}), 400
# Install the plugin
# Log the plugins directory being used for debugging
plugins_dir = api_v3.plugin_store_manager.plugins_dir
@@ -1498,7 +1509,8 @@ def get_registry_from_url():
if registry:
return jsonify({
'status': 'success',
'plugins': registry.get('plugins', []),
'plugins': [p for p in registry.get('plugins', [])
if api_v3.plugin_store_manager.is_plugin_entry(p)],
'registry_url': repo_url
})
else:
@@ -1613,6 +1625,8 @@ def list_plugin_store():
# Format plugins for the web interface
formatted_plugins = []
for plugin in plugins:
if not api_v3.plugin_store_manager.is_plugin_entry(plugin):
continue
formatted_plugins.append({
'id': plugin.get('id'),
'name': plugin.get('name'),