Skip to content

feat: GitHub-based Plugin Marketplace System#98

Open
r-pedraza wants to merge 24 commits intomasterfrom
feat/plugin-marketplace-system
Open

feat: GitHub-based Plugin Marketplace System#98
r-pedraza wants to merge 24 commits intomasterfrom
feat/plugin-marketplace-system

Conversation

@r-pedraza
Copy link
Contributor

Summary

This PR implements a complete GitHub-based plugin marketplace system for Titan CLI, enabling users to discover, install, and manage plugins directly from the official repository.

Key Features

  • GitHub Registry: Centralized registry.json with plugin metadata (official & community)
  • Project-Level Installation: Plugins install to .titan/plugins/ (project-specific)
  • Dynamic Configuration: JSON Schema-based config wizard on first install
  • Secure Secrets: OS keyring integration via SecretManager
  • Interactive Marketplace: Browse, search, and install with rich UI
  • Plugin Management: Install, uninstall, update (individual or all)
  • Validation: Comprehensive plugin validation (metadata, entry points, dependencies)

New Components

Core Classes:

  • PluginDownloader: Downloads plugins from GitHub registry
  • PluginValidator: Validates plugin structure and metadata
  • ConfigSchemaRenderer: Renders interactive config wizard from JSON Schema

Commands:

  • titan plugins discover - Interactive marketplace browser
  • titan plugins install <name> - Install plugin by name
  • titan plugins uninstall <name> - Remove plugin
  • titan plugins update <name> - Update to latest version
  • titan plugins update --all - Update all plugins

Registry Format:

{
  "plugins": {
    "git": {
      "display_name": "Git Operations",
      "description": "Git client wrapper",
      "category": "official",
      "verified": true,
      "latest_version": "1.0.0",
      "source": "plugins/titan-plugin-git",
      "dependencies": []
    }
  }
}

Architecture Changes

  1. PluginRegistry Enhancements:

    • Discovers both entry points (installed) and local plugins (.titan/plugins/)
    • Loads plugins from project-specific directory
    • Supports dynamic plugin loading without restart
  2. Message Centralization:

    • Added 102 new messages across 3 classes (PluginDownloader, PluginValidator, ConfigSchema)
    • All user-facing strings in messages.py for i18n readiness
  3. Configuration Updates:

    • TitanConfig.set_plugin_config() for saving plugin configs
    • Project-level plugin config merging
    • Respects existing plugin config in .titan/config.toml

Plugin Metadata

All plugins now include plugin.json with:

  • name, version, description
  • category (official/community)
  • dependencies (plugin dependencies)
  • min_titan_version (compatibility check)
  • entry_point (Python import path)
  • configSchema (optional JSON Schema for config)

Testing

  • ✅ 220/220 tests passing
  • ✅ 0 linting warnings
  • ✅ Added comprehensive tests for:
    • Plugin downloader (registry fetch, download, install, uninstall)
    • Plugin validator (metadata, entry points, dependencies)
    • Config schema renderer (wizard, validation, secure storage)

Security

  • Secrets stored in OS keyring (never in config files)
  • Plugin validation before installation
  • Entry point class verification (must inherit from TitanPlugin)
  • Dependency resolution with circular dependency detection

Documentation

  • Updated README.md with marketplace usage
  • Added .gitignore entry for .titan/plugins/
  • Created registry.json with 3 official plugins

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Enhancement (improvement to existing functionality)
  • Documentation update

Changes Made

Core Plugin System

  1. PluginDownloader (plugin_downloader.py):

    • Fetches registry.json from GitHub
    • Downloads full repo ZIP and extracts plugin
    • Installs to .titan/plugins/ (project-level)
    • Handles versioning and updates
  2. PluginValidator (plugin_validator.py):

    • Validates plugin.json structure
    • Checks required fields (name, version, entry_point)
    • Verifies entry point class exists
    • Validates dependencies and compatibility
  3. ConfigSchemaRenderer (config_schema_renderer.py):

    • Renders interactive wizard from JSON Schema
    • Supports all JSON Schema types (string, number, boolean, array, object)
    • Handles validation (pattern, min/max, required)
    • Secure storage for secret fields (x-secret: true)

Commands

  1. Plugin Marketplace Commands (plugins_marketplace.py):

    • install_plugin_from_marketplace() - Full install flow with wizard
    • uninstall_plugin_from_marketplace() - Clean uninstall
    • discover_plugins() - Interactive marketplace browser
    • update_plugin() - Update single or all plugins
  2. Enhanced Plugin Commands (plugins.py):

    • Integrated marketplace commands
    • Updated list to show installed + downloaded plugins

Configuration

  1. TitanConfig Updates (config.py):

    • set_plugin_config() method for saving plugin configs
    • Project-level config merging logic
  2. PluginRegistry Enhancements (plugin_registry.py):

    • discover_local_plugins() for .titan/plugins/
    • Combined discovery (entry points + local)
    • Dynamic plugin loading

Registry & Templates

  1. Plugin Registry (registry.json):

    • Official plugins: git, github, jira
    • Metadata format with categories, versions, descriptions
  2. Plugin Metadata Files:

Messages & Testing

  1. Message Centralization (messages.py):

    • Added 3 message classes with 102 total messages
    • All plugin core modules now use msg.* references
  2. Comprehensive Tests:

How Has This Been Tested?

Unit Tests

  • ✅ All 220 tests passing
  • ✅ Plugin downloader: registry fetch, download, install, uninstall
  • ✅ Plugin validator: metadata validation, entry point checks
  • ✅ Config renderer: wizard flow, validation, secure storage

Manual Testing

  • titan plugins discover - Interactive marketplace works
  • titan plugins install git - Installs with config wizard
  • titan plugins list - Shows installed plugins
  • titan plugins update --all - Updates all plugins
  • titan plugins uninstall git - Clean removal
  • ✅ Plugin configuration persists in .titan/config.toml
  • ✅ Secrets stored in OS keyring

Edge Cases Tested

  • ✅ Installing already-installed plugin (prompts for reinstall)
  • ✅ Missing dependencies (shows error with install commands)
  • ✅ Invalid plugin structure (validation error)
  • ✅ Network errors (graceful error handling)
  • ✅ Cancelled config wizard (plugin installs but not configured)

Checklist

  • My code follows the project's code style guidelines
  • I have performed a self-review of my own code
  • I have added tests that prove my feature works
  • All new and existing tests pass locally
  • I have updated the documentation (README.md, AGENTS.md if needed)
  • My changes generate no new warnings or errors
  • Any dependent changes have been merged and published

Additional Notes

Future Enhancements

  • Plugin versioning with semantic versioning
  • Plugin dependencies graph visualization
  • Marketplace filters (category, verified, popularity)
  • Plugin ratings and reviews
  • Plugin search functionality
  • Auto-update notifications

Breaking Changes

None - all changes are additive and backward-compatible.

Migration Guide

For existing users:

  1. Plugins will continue to work from entry points
  2. New plugins can be installed from marketplace
  3. Existing config in .titan/config.toml is preserved

Co-Authored-By: Claude noreply@anthropic.com

r-pedraza and others added 20 commits January 12, 2026 16:33
- Bump version to 1.0.0
- Remove plugins from core distribution (installed separately via pipx inject)
- Add jinja2 dependency for workflow templates
- Update project metadata (homepage, keywords, classifiers)
- Add release documentation (RELEASE.md)
- Add user installation guide (INSTALLATION.md)

Validation:
- ✅ All 10 automated tests passed
- ✅ pipx installation verified
- ✅ No plugins bundled
- ✅ Package size: 115KB

Co-Authored-By: Claude <noreply@anthropic.com>
- Add PluginDownloader for GitHub registry and plugin installation
- Add PluginValidator for plugin metadata and compatibility validation
- Add marketplace commands (discover, install, uninstall, update)
- Modify PluginRegistry to support local ~/.titan/plugins/ discovery
- Add plugin.json metadata for all existing plugins (git, github, jira)
- Add registry.json for plugin marketplace
- Configure for monorepo workflow (masmovil/titan-cli)

Core modules:
- titan_cli/core/plugins/plugin_downloader.py (NEW)
- titan_cli/core/plugins/plugin_validator.py (NEW)
- titan_cli/core/plugins/exceptions.py (NEW)
- titan_cli/core/plugins/plugin_registry.py (MODIFIED)

Commands:
- titan_cli/commands/plugins_marketplace.py (NEW)
- titan_cli/commands/plugins.py (MODIFIED)

Plugin metadata:
- plugins/*/plugin.json (NEW - git, github, jira)
- registry.json (NEW)

Tests:
- tests/core/plugins/test_plugin_downloader.py (12 tests)
- tests/core/plugins/test_plugin_validator.py (33 tests)
- Total: 45 tests, all passing

Features:
- GitHub-only distribution (no PyPI for plugins)
- Quality control via PR reviews
- Dual discovery (entry_points + local directory)
- Version compatibility checking
- Dependency resolution
- Plugin validation
- Monorepo-friendly design

After merge to master, marketplace will be live at:
https://raw.githubusercontent.com/masmovil/titan-cli/master/registry.json

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ConfigSchemaRenderer for automatic wizard generation
- Support all JSON Schema types (string, boolean, integer, array, object)
- Implement validation (email, uri, pattern, length, range)
- Secret management via OS keyring
- Add TitanConfig.set_plugin_config() method
- Integrate wizard into installation flow
- Add 26 comprehensive tests (71 total passing)
- Update JIRA and GitHub plugins with configSchema

Automatic configuration wizard activates when plugin has configSchema
in plugin.json. Prompts user for all fields with real-time validation.
Secrets stored encrypted in OS keyring, config saved to ~/.titan/config.toml
- Add marketplace option to Plugin Management menu
- Temporarily point to feature branch for testing
- Interactive marketplace accessible from main Titan menu
- Plugins now install to .titan/plugins/ in the current project instead of ~/.titan/plugins/
- PluginDownloader uses project path from TitanConfig
- PluginRegistry configured with project-specific plugin directory
- Updated all marketplace commands to use project-level paths
- Each project can now have its own set of installed plugins
- Tests updated and all 71 tests passing

Co-Authored-By: Claude <noreply@anthropic.com>
MenuItem model requires 'action' field, not 'value'. Fixed marketplace
to use correct field name for plugin selection.

Co-Authored-By: Claude <noreply@anthropic.com>
- Use public properties (active_project_path, project_root) instead of private (_active_project_path, _project_root)
- Add JSONDecodeError and OSError handling in plugin_registry.py for safer plugin.json loading
- All 71 tests still passing

Addresses code review findings for production readiness.

Co-Authored-By: Claude <noreply@anthropic.com>
Centralize all user-facing strings in plugins_marketplace.py to messages.py
for better maintainability and i18n readiness.

Changes:
- Add 73 message constants to messages.py in Plugins class
- Update install_plugin_from_marketplace() to use msg.Plugins.*
- Update uninstall_plugin_from_marketplace() to use msg.Plugins.*
- Update discover_plugins() to use msg.Plugins.*
- Update update_plugin() to use msg.Plugins.*

Message categories added:
- Marketplace (titles, prompts, status)
- Installation (progress messages)
- Plugin info (badges, verification status)
- Dependencies (validation messages)
- Configuration (wizard messages)
- Uninstallation (removal messages)
- Updates (update progress)
- Reinstall (confirmation prompts)
- Errors (standardized error messages)

Benefits:
- Single source of truth for all UI strings
- Consistent messaging across marketplace commands
- Prepared for future internationalization support
- Follows project standards (AGENTS.md)

Co-Authored-By: Claude <noreply@anthropic.com>
The configuration wizard already runs automatically during plugin
installation in install_plugin_from_marketplace(). The additional
prompt in discover_plugins() was redundant and has been removed.

Changes:
- Remove duplicate configuration prompt after installation
- Remove unused marketplace configuration messages
- Add clarifying comment about automatic wizard execution

Benefits:
- Cleaner user flow (no redundant prompts)
- Less code to maintain
- Configuration still happens automatically during installation

Co-Authored-By: Claude <noreply@anthropic.com>
The downloader was looking for 'titan-plugins-{branch}' but the actual
repository is 'titan-cli'. This caused all plugin downloads to fail.

Changes:
- Fix extracted repo directory name from titan-plugins to titan-cli
- Update comment to reflect correct structure

Fixes plugin installation from marketplace.

Co-Authored-By: Claude <noreply@anthropic.com>
GitHub replaces forward slashes with hyphens in ZIP directory names.
Branch 'feat/plugin-marketplace-system' becomes
'titan-cli-feat-plugin-marketplace-system' in the ZIP.

Changes:
- Replace '/' with '-' in branch name before constructing ZIP path
- Add comment explaining GitHub's ZIP naming behavior

This fixes plugin installation when using branches with slashes.

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ask_password() method to support secret field configuration
- Uses ask_text() with password=True for hidden input
- Fixes error during GitHub plugin configuration wizard
- Add .titan/plugins/ to .gitignore (downloaded plugins)

Co-Authored-By: Claude <noreply@anthropic.com>
- Change ask_text calls from message= to prompt=
- Change ask_select to ask_choice with correct signature
- Change ask_confirm from message= to prompt=
- Update tests to match new method signatures
- Fixes configuration wizard errors for all plugins

Relates to JIRA plugin installation error:
"PromptsRenderer.ask_text() got an unexpected keyword argument 'message'"

Co-Authored-By: Claude <noreply@anthropic.com>
- Change ask_confirm from prompt= to question=
- Update tests to match correct signature
- Update CLAUDE.md documentation with correct parameter

Fixes JIRA plugin installation error:
"PromptsRenderer.ask_confirm() got an unexpected keyword argument 'prompt'"

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed bug where plugins appeared multiple times when listing installed plugins.

Root cause: _discover_from_entry_points() used extend() without checking
for duplicates, causing the same plugin to be added multiple times when
discover() was called repeatedly.

Solution: Changed to iterate and check for duplicates before appending,
matching the pattern used in _discover_from_local_plugins().

Before: 12 duplicate entries for 3 plugins
After: Only 3 unique plugins shown

Co-Authored-By: Claude <noreply@anthropic.com>
Updated configuration and documentation for production release:
- Changed REGISTRY_BRANCH from feat/plugin-marketplace-system to master
- Updated README with comprehensive plugin marketplace documentation
- Added installation, management, and available plugins sections

Ready for merge to master branch.

Co-Authored-By: Claude <noreply@anthropic.com>
Addresses critical code review finding: move all user-facing strings from
plugin core modules to centralized messages.py for consistency and future i18n.

Changes:
- Add PluginDownloader, PluginValidator, ConfigSchema message classes to messages.py
- Replace 50+ hardcoded strings in plugin_downloader.py with msg.* references
- Replace 15+ hardcoded strings in plugin_validator.py with msg.* references
- Replace 15+ hardcoded strings in config_schema_renderer.py with msg.* references
- Fix PromptsRenderer parameter naming in plugins_marketplace.py (question= explicit)
- Update test expectations to match new centralized messages
- Fix plugin registry tests to use tmp_path to avoid local plugin interference

This ensures all user-facing strings follow Titan CLI conventions and are
centralized for easy maintenance and future internationalization.

Co-Authored-By: Claude <noreply@anthropic.com>
Remove unused imports and variables identified by ruff linter.

Changes:
- plugins_marketplace.py: Remove unused TableRenderer import, unused category variable
- config_schema_renderer.py: Remove unused Path and TitanConfig imports
- plugin_downloader.py: Remove unused target_version variable
- plugin_validator.py: Remove unused importlib.util and Optional imports

All 220 tests still passing. No functional changes.

Co-Authored-By: Claude <noreply@anthropic.com>
@r-pedraza r-pedraza requested a review from a team January 14, 2026 13:17
@r-pedraza r-pedraza self-assigned this Jan 14, 2026
@osc-wiz-app-masmovil
Copy link

osc-wiz-app-masmovil bot commented Jan 14, 2026

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities -
Data Finding Sensitive Data 1 Info
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations 3 Low 2 Info
SAST Finding SAST Findings 2 Medium 1 Low
Software Management Finding Software Management Findings -
Total 2 Medium 4 Low 3 Info

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Info Sensitive Data Finding

PII

More Details
Attribute Value
Data Classifier PII/Name
Data Classifier ID BUILTIN-125

Sampled Examples

Key Value
author T***n
author T***n
author T***n
git.author T***n
github.author T***n

Rule ID: BUILTIN-125


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

return self._registry_cache

try:
with urlopen(self.registry_url, timeout=10) as response:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium SAST Finding

Insecure URL handling in Python urllib module (CWE-939)

More Details

The Python urllib module allows applications to open URLs and retrieve data from the web. However, if the URL is not a literal value and can be controlled by an attacker, it can lead to security vulnerabilities. The urllib module supports the "file://" scheme, which means an attacker could potentially read arbitrary files on the system if they can control the URL value.

This vulnerability poses a significant risk as it can lead to unauthorized access to sensitive information, data leaks, and potentially even remote code execution, depending on the application's context and privileges. It is crucial to avoid passing user-controlled input directly to the urllib module's functions without proper validation and sanitization.

Attribute Value
Impact Medium
Likelihood Medium

Remediation

To mitigate this vulnerability, it is recommended to either:

  1. Hardcode the URLs being used in the urllib module, ensuring that they are not derived from user input or other untrusted sources.
  2. Use a more secure and modern library like the requests module, which does not support the "file://" scheme by default.

Example using the requests module to issue an HTTPS request:

import requests

# Issue a GET request to https://example.com with a timeout of 10 seconds
response = requests.get('https://example.com', timeout=10)

# Work with the response object
# ...

Rule ID: WS-I011-PYTHON-00053


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate


# Download ZIP
zip_path = temp_dir / "repo.zip"
with urlopen(zip_url, timeout=30) as response:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium SAST Finding

Insecure URL handling in Python urllib module (CWE-939)

More Details

The Python urllib module allows applications to open URLs and retrieve data from the web. However, if the URL is not a literal value and can be controlled by an attacker, it can lead to security vulnerabilities. The urllib module supports the "file://" scheme, which means an attacker could potentially read arbitrary files on the system if they can control the URL value.

This vulnerability poses a significant risk as it can lead to unauthorized access to sensitive information, data leaks, and potentially even remote code execution, depending on the application's context and privileges. It is crucial to avoid passing user-controlled input directly to the urllib module's functions without proper validation and sanitization.

Attribute Value
Impact Medium
Likelihood Medium

Remediation

To mitigate this vulnerability, it is recommended to either:

  1. Hardcode the URLs being used in the urllib module, ensuring that they are not derived from user input or other untrusted sources.
  2. Use a more secure and modern library like the requests module, which does not support the "file://" scheme by default.

Example using the requests module to issue an HTTPS request:

import requests

# Issue a GET request to https://example.com with a timeout of 10 seconds
response = requests.get('https://example.com', timeout=10)

# Work with the response object
# ...

Rule ID: WS-I011-PYTHON-00053


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate


try:
# Import module
module = importlib.import_module(module_path)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low SAST Finding

Arbitrary Code Execution via Insecure Import (CWE-706)

More Details

The importlib.import_module() function in Python allows dynamically importing modules at runtime. If the module name is derived from untrusted user input, an attacker could potentially execute arbitrary code on the system by causing a malicious module to be loaded.

Attribute Value
Impact Medium
Likelihood Low

Remediation

The importlib.import_module() function in Python allows for dynamic code loading, which can be a security risk if the module name is derived from untrusted user input. An attacker could potentially exploit this vulnerability to execute arbitrary code on the system, leading to various security issues such as code injection, data tampering, or unauthorized access.

To fix this issue, avoid using dynamic values in importlib.import_module() or implement a strict whitelist of allowed module names. If dynamic module loading is necessary, validate and sanitize the input to ensure that only trusted and approved modules are loaded.

Code examples:


// VULNERABLE CODE - Directly using user input for module loading
import importlib

user_input = input("Enter module name: ")
module = importlib.import_module(user_input)

// SECURE CODE - Using a whitelist of allowed modules
import importlib

ALLOWED_MODULES = ["module1", "module2", "module3"]

user_input = input("Enter module name: ")
if user_input in ALLOWED_MODULES:
    module = importlib.import_module(user_input)
else:
    print("Module not allowed")

Additional recommendations:

  • Follow the principle of least privilege and only grant the minimum required permissions for module loading.
  • Implement input validation and sanitization techniques to prevent code injection attacks.
  • Consider using a secure coding framework or library that provides built-in protection against code injection vulnerabilities.
  • Adhere to the OWASP Top 10 security guidelines, specifically "A1:2021 - Broken Access Control" and "A3:2021 - Injection."
  • Regularly update and maintain the whitelist of allowed modules to ensure it remains secure and up-to-date.

Rule ID: WS-I013-PYTHON-00176


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

r-pedraza and others added 4 commits January 14, 2026 14:22
…rer tests

Co-Authored-By: Claude <noreply@anthropic.com>
Implements the core backend for the plugin marketplace system:

**MarketplaceClient** (marketplace_client.py):
- HTTP client for fetching plugin registry from GitHub
- Caching mechanism with configurable TTL (5 minutes default)
- Registry validation and error handling
- Support for custom registry URLs via config

**MarketplaceModels** (marketplace_models.py):
- Pydantic models for type-safe marketplace data:
  - PluginMetadata: Plugin information (name, version, description, etc.)
  - PluginRegistry: Complete registry structure
- Comprehensive validation for plugin metadata
- Support for plugin dependencies, tags, and compatibility

**Tests** (test_marketplace.py):
- Unit tests for marketplace client
- Tests for caching, error handling, and validation
- Mock HTTP responses for deterministic testing

This provides the foundation for plugin discovery and installation
from the centralized marketplace registry.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds technical documentation for the Titan CLI plugin architecture:

**PLUGIN_ARCHITECTURE.md**:
- Overview of the plugin system design
- Core components documentation (plugin_base, registry, discovery, loader)
- Plugin lifecycle and initialization flow
- Dependency resolution mechanism
- Workflow integration patterns
- Best practices and security considerations
- References to architecture diagrams

**PLUGIN_CREATION_GUIDE.md**:
- Step-by-step guide for creating plugins
- Two paths: local plugins vs marketplace plugins
- Project structure templates
- Entry point configuration with Poetry
- Client implementation examples
- Workflow step patterns
- Testing guidelines
- Publishing process to marketplace

**Architecture Diagrams** (Mermaid):
- plugin_class_architecture.mmd: Class hierarchy and relationships
- plugin_discovery_initialization.mmd: Discovery and loading flow
- plugin_dependency_resolution.mmd: Dependency resolution algorithm
- plugin_workflow_integration.mmd: Workflow execution patterns

This documentation serves as the primary reference for developers
creating plugins or contributing to the plugin system.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds GitHub Actions workflows and utility scripts for plugin management:

**GitHub Workflows**:

- **publish-plugins.yml**: Automated plugin publishing workflow
  - Triggered on new plugin releases (tags matching plugin-*/v*)
  - Builds and publishes to PyPI
  - Updates marketplace registry automatically
  - Supports multiple plugins in monorepo structure

- **test-plugins.yml**: Plugin testing workflow
  - Runs on PRs affecting plugin code
  - Executes pytest for all modified plugins
  - Ensures plugin quality before merge
  - Matrix strategy for testing multiple plugins

**Scripts**:

- **update_registry.py**: Marketplace registry management
  - Fetches plugin metadata from PyPI
  - Validates plugin compatibility
  - Updates registry.json with new versions
  - Can be run manually or via CI

- **document_agent_standalone.py**: Documentation generator
  - Autonomous agent for generating plugin documentation
  - Uses Claude API to analyze code structure
  - Generates architecture diagrams (Mermaid)
  - Creates comprehensive markdown documentation

- **requirements_agent.txt**: Dependencies for documentation agent
  - anthropic SDK for AI-powered documentation
  - Required for running document_agent_standalone.py

- **README_DOCUMENT_AGENT.md**: Documentation agent usage guide

These tools enable automated plugin lifecycle management from
development through publishing and documentation.

Co-Authored-By: Claude <noreply@anthropic.com>
python-version: '3.11'

- name: Install Poetry
uses: snok/install-poetry@v1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low IaC Finding

Workflow should not use version pinning for third-party actions
on resource jobs.test.steps[2].uses

More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.

Expected

Workflow job 'test' step[2] should pin third-party action to a commit SHA rather than a version tag

Found

Workflow job 'test' step[2] uses version-tagged third-party action: 'snok/install-poetry@v1'

Security Frameworks: wf-id-1, wf-id-175


Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

run: poetry run pytest -v

- name: Upload coverage
uses: codecov/codecov-action@v3

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low IaC Finding

Workflow should not use version pinning for third-party actions
on resource jobs.test.steps[7].uses

More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.

Expected

Workflow job 'test' step[7] should pin third-party action to a commit SHA rather than a version tag

Found

Workflow job 'test' step[7] uses version-tagged third-party action: 'codecov/codecov-action@v3'

Security Frameworks: wf-id-1, wf-id-175


Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

@@ -0,0 +1,98 @@
name: Test Plugins

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Info IaC Finding

Workflow should have permissions limitations
on resource name

More Details
This rule checks that GitHub workflow has an empty permissions block to enforce least privilege. This rule fails when the workflow doesn't have a permissions block or has a non-empty permissions block with `write-all` scope, which can grant excessive permissions to workflow actions. Excessive permissions in GitHub workflows increase the risk surface in case of a compromise, potentially allowing attackers to access sensitive resources or perform unauthorized actions. To prevent this risk, always implement least privilege by explicitly defining an empty permissions block for all workflows.

Expected

GitHub workflow should have empty permissions block

Found

GitHub workflow doesn't have a permissions block defined

Security Frameworks: wf-id-1, wf-id-175


Rule ID: 65570021-8e03-4ccf-bf86-6bcb9fcc7a97


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

@@ -0,0 +1,130 @@
name: Publish Plugins to PyPI

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Info IaC Finding

Workflow should have permissions limitations
on resource name

More Details
This rule checks that GitHub workflow has an empty permissions block to enforce least privilege. This rule fails when the workflow doesn't have a permissions block or has a non-empty permissions block with `write-all` scope, which can grant excessive permissions to workflow actions. Excessive permissions in GitHub workflows increase the risk surface in case of a compromise, potentially allowing attackers to access sensitive resources or perform unauthorized actions. To prevent this risk, always implement least privilege by explicitly defining an empty permissions block for all workflows.

Expected

GitHub workflow should have empty permissions block

Found

GitHub workflow doesn't have a permissions block defined

Security Frameworks: wf-id-1, wf-id-175


Rule ID: 65570021-8e03-4ccf-bf86-6bcb9fcc7a97


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

python-version: '3.11'

- name: Install Poetry
uses: snok/install-poetry@v1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low IaC Finding

Workflow should not use version pinning for third-party actions
on resource jobs.publish.steps[2].uses

More Details
This rule checks that GitHub workflow does not use version pinning on third-party actions. This rule fails when the workflow contains steps that use third-party actions referenced by version tags (like @v1, @v2.3, @v4) instead of specific commits. Using version-tagged actions creates a supply chain security risk, as the version tag could be modified by the action's maintainer to point to malicious code after the calling workflow is created. Even when using specific version tags, the tag could be moved to point to malicious code. To prevent this risk, always pin third-party actions to specific commit SHAs to ensure the exact code being executed is locked and immutable.

Expected

Workflow job 'publish' step[2] should pin third-party action to a commit SHA rather than a version tag

Found

Workflow job 'publish' step[2] uses version-tagged third-party action: 'snok/install-poetry@v1'

Security Frameworks: wf-id-1, wf-id-175


Rule ID: 7d431072-4eef-466b-b469-4b7681d8f9a1


To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant