security(plugins): add cryptographic signature verification#29
Open
DeryFerd wants to merge 1 commit into
Open
Conversation
- Add plugin_signer module with GPG-based signature verification - Integrate signature verification into plugin install workflow - Support for trusted keyring (plugins/trusted_keys.asc) - Configurable via PLUGIN_SIGNATURE_REQUIRED setting - Graceful fallback when GPG unavailable or keys not configured - Comprehensive unit tests with 18 test cases - Helper functions for plugin developers to sign plugins
jeffrysurya
pushed a commit
to jeffrysurya/evonic
that referenced
this pull request
May 20, 2026
- Add IDs to Connect (#btn-connect) and Disconnect (#btn-disconnect) buttons - In applyWorkplaceData(): toggle buttons based on status (connected -> hide Connect, show Disconnect) - In refreshStatus(): update button state based on data.status - In connectWorkplace()/disconnectWorkplace(): replace setTimeout(refreshStatus) with setTimeout(loadWorkplace) - Fix SSE event name: home_status_changed -> workplace_status_changed
jeffrysurya
pushed a commit
to jeffrysurya/evonic
that referenced
this pull request
May 20, 2026
…ent scans (anvie#29) _find_agent_for_session() iterates ALL agents and calls has_session() for each one — an O(N) scan with N SQL queries. This method is called from 16 different call sites in the same mixin, and many of them are invoked for the same session_id within a single request (e.g., get_session_with_details + get_summary + add_chat_message). Add @functools.lru_cache(maxsize=256) so that repeated lookups for the same session_id hit the cache instead of re-scanning every agent DB. Cache info from synthetic test: 5 agents, 3 distinct session lookups -> 2 cache hits, 3 misses (1 per unique session_id). For a real request with 5+ calls to the same session, this eliminates 80%+ of the redundant agent scans.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Plugins run arbitrary Python code via
setup.pywith full system privileges. Right now, any zip file that passes basic validation (size limits, path traversal checks, file type whitelist) can be installed. There's no cryptographic verification that the plugin came from a trusted source or hasn't been tampered with.This is the highest-risk attack surface I found during the security audit. A malicious plugin could exfiltrate data, backdoor the system, or escalate privileges. Supply chain attacks are real—we've seen them with npm, PyPI, and other package ecosystems.
What This PR Does
Adds GPG-based signature verification for plugins. When signature verification is enabled, plugins must include a detached GPG signature (
.sigor.ascfile) that's verified against a trusted keyring before installation.New files:
backend/plugin_signer.py— Signature verification logic using GPG subprocess callsunit_tests/test_plugin_signer.py— 18 test cases covering verification, key management, and edge casesModified files:
backend/zip_validator.py— Added optional signature verification stepbackend/plugin_lifecycle.py— Integrated verification intoinstall_plugin()workflowHow It Works
Setup (one-time):
plugins/trusted_keys.ascPLUGIN_SIGNATURE_REQUIRED=truein environment or databasePlugin installation:
gpg --detach-sign --armor -o plugin.sig plugin.zipGraceful fallback:
PLUGIN_SIGNATURE_REQUIRED=false, verification is disabledWhy GPG?
GPG is widely available, well-understood, and already used by many package managers (apt, yum, Homebrew). It's not perfect, but it's a reasonable choice for this use case. The implementation is isolated enough that we could swap in a different signing mechanism later if needed.
Testing
All 18 unit tests pass. The tests mock GPG subprocess calls to avoid requiring GPG during CI, but I also manually tested with real GPG:
What This Doesn't Do
This PR is focused on one thing: preventing unsigned or tampered plugins from being installed when verification is enabled.
Migration Path
For existing deployments:
PLUGIN_SIGNATURE_REQUIRED=trueFor plugin developers:
.sigfile alongside the zip