Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/security-guidance/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ name: security-guidance
version: "0.1.0"
description: "Append security warnings to file-write tool results when the new content contains known-dangerous patterns (pickle.load, yaml.load, eval(, os.system, dangerouslySetInnerHTML, verify=False, ECB, XXE, GitHub Actions injection, ...). 25 regex/substring rules forked from Anthropic's claude-plugins-official under Apache-2.0. Non-blocking — the file is written and the warning rides back to the model in the next turn so it can self-correct."
author: "Anthropic (patterns, Apache-2.0) / NousResearch (Hermes plugin port)"
hooks:
provides_hooks:
- transform_tool_result
- pre_tool_call
23 changes: 22 additions & 1 deletion tests/plugins/test_security_guidance_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,34 @@ def test_blocks_in_block_mode_on_dangerous_pattern(self, monkeypatch):
# ---------------------------------------------------------------------------

class TestPluginDiscovery:
def test_manifest_declares_registered_hooks(self):
"""Manifest metadata must use the field consumed by plugin discovery."""
import yaml

plugin_dir = _repo_root() / "plugins" / "security-guidance"
manifest = yaml.safe_load(
(plugin_dir / "plugin.yaml").read_text(encoding="utf-8")
)
mod = _load_plugin_init()
registered = []

class HookContext:
def register_hook(self, name, _callback):
registered.append(name)

mod.register(HookContext())
assert set(manifest["provides_hooks"]) == set(registered)
assert "hooks" not in manifest

def test_loads_via_plugin_manager(self, _isolate_env, monkeypatch):
"""End-to-end: enable in config.yaml and verify the PluginManager
picks it up via the standard discovery path."""
import yaml

config = {"plugins": {"enabled": ["security-guidance"]}}
(_isolate_env / "config.yaml").write_text(yaml.safe_dump(config))
(_isolate_env / "config.yaml").write_text(
yaml.safe_dump(config), encoding="utf-8"
)

# Wipe any cached plugin state from earlier tests in this worker.
for k in list(sys.modules):
Expand Down