plugin-scanner 2.0.108__tar.gz → 2.0.110__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/PKG-INFO +20 -9
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/README.md +19 -8
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/get-started.md +24 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/testing-matrix.md +10 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/pyproject.toml +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/commands.py +260 -10
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/render.py +117 -51
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/consumer/service.py +9 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +25 -2
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_cli.py +36 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_cli.py +157 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_product_flow.py +11 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_risk.py +20 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime.py +473 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.dockerignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.gitignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/Dockerfile +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/requirements.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.110
|
|
4
4
|
Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
6
6
|
Project-URL: Repository, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
@@ -302,33 +302,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
302
302
|
|
|
303
303
|
```bash
|
|
304
304
|
# Scan a plugin directory
|
|
305
|
-
plugin-scanner ./my-plugin
|
|
305
|
+
plugin-scanner scan ./my-plugin
|
|
306
306
|
|
|
307
307
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
308
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
308
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
309
309
|
|
|
310
310
|
# Scan only Claude package surfaces
|
|
311
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
311
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
312
312
|
|
|
313
313
|
# List supported ecosystems
|
|
314
314
|
plugin-scanner --list-ecosystems
|
|
315
315
|
|
|
316
316
|
# Output JSON
|
|
317
|
-
plugin-scanner ./my-plugin --json
|
|
317
|
+
plugin-scanner scan ./my-plugin --format json
|
|
318
318
|
|
|
319
319
|
# Write a SARIF report for GitHub code scanning
|
|
320
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
320
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
321
321
|
|
|
322
322
|
# Fail CI on findings at or above high severity
|
|
323
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
323
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
324
324
|
|
|
325
325
|
# Require Cisco skill scanning with a strict policy
|
|
326
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
326
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
327
327
|
|
|
328
328
|
# Require optional Cisco MCP static analysis
|
|
329
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
329
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
333
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
334
|
+
|
|
335
|
+
| Need | Command | Output contract |
|
|
336
|
+
| :--- | :--- | :--- |
|
|
337
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
338
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
339
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
340
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
341
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
342
|
+
|
|
332
343
|
## Quality Suite Commands
|
|
333
344
|
|
|
334
345
|
```bash
|
|
@@ -262,33 +262,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
262
262
|
|
|
263
263
|
```bash
|
|
264
264
|
# Scan a plugin directory
|
|
265
|
-
plugin-scanner ./my-plugin
|
|
265
|
+
plugin-scanner scan ./my-plugin
|
|
266
266
|
|
|
267
267
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
268
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
268
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
269
269
|
|
|
270
270
|
# Scan only Claude package surfaces
|
|
271
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
271
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
272
272
|
|
|
273
273
|
# List supported ecosystems
|
|
274
274
|
plugin-scanner --list-ecosystems
|
|
275
275
|
|
|
276
276
|
# Output JSON
|
|
277
|
-
plugin-scanner ./my-plugin --json
|
|
277
|
+
plugin-scanner scan ./my-plugin --format json
|
|
278
278
|
|
|
279
279
|
# Write a SARIF report for GitHub code scanning
|
|
280
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
280
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
281
281
|
|
|
282
282
|
# Fail CI on findings at or above high severity
|
|
283
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
283
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
284
284
|
|
|
285
285
|
# Require Cisco skill scanning with a strict policy
|
|
286
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
286
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
287
287
|
|
|
288
288
|
# Require optional Cisco MCP static analysis
|
|
289
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
289
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
290
290
|
```
|
|
291
291
|
|
|
292
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
293
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
294
|
+
|
|
295
|
+
| Need | Command | Output contract |
|
|
296
|
+
| :--- | :--- | :--- |
|
|
297
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
298
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
299
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
300
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
301
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
302
|
+
|
|
292
303
|
## Quality Suite Commands
|
|
293
304
|
|
|
294
305
|
```bash
|
|
@@ -76,6 +76,30 @@ Use it when you want to protect a harness before local MCP servers, skills, hook
|
|
|
76
76
|
hol-guard device rotate
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
## Which command should I use?
|
|
80
|
+
|
|
81
|
+
| Situation | Command | What it answers |
|
|
82
|
+
| :--- | :--- | :--- |
|
|
83
|
+
| I need the current protection posture | `hol-guard status` | What is Guard watching, is sync connected, and what is the next action? |
|
|
84
|
+
| I need setup or runtime troubleshooting | `hol-guard doctor <harness>` | Why is this harness or Guard runtime not behaving correctly? |
|
|
85
|
+
| A launch was blocked or changed | `hol-guard diff <harness>` | What changed since the last recorded snapshot? |
|
|
86
|
+
| I need to resolve a queued block | `hol-guard approvals` | Which requests are waiting, and how do I approve or deny them? |
|
|
87
|
+
| I need decision history | `hol-guard receipts` | What decisions did Guard record locally? |
|
|
88
|
+
| I need the tracked catalog | `hol-guard inventory` | Which artifacts are currently tracked and present? |
|
|
89
|
+
| I need an exportable evidence artifact | `hol-guard abom` | What local AI-BOM can I attach to an audit or handoff? |
|
|
90
|
+
| I need the chronological log | `hol-guard events` | What happened over time on this machine? |
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
| Symptom | Start here | Then try |
|
|
95
|
+
| :--- | :--- | :--- |
|
|
96
|
+
| Guard did not find my harness | `hol-guard detect --json` | `hol-guard doctor <harness> --json` for adapter-specific warnings |
|
|
97
|
+
| `hol-guard run` paused a launch | `hol-guard diff <harness>` | `hol-guard approvals`, then retry `hol-guard run <harness>` |
|
|
98
|
+
| I approved a prompt and want proof | `hol-guard receipts` | `hol-guard explain <artifact-id>` for the latest receipt and diff context |
|
|
99
|
+
| I need audit or handoff evidence | `hol-guard inventory` | `hol-guard abom --format json` for machine-readable export |
|
|
100
|
+
| I need to understand recent activity | `hol-guard events` | Use `--name <event>` to filter a noisy local timeline |
|
|
101
|
+
| Cloud sync or pairing looks wrong | `hol-guard status` | `hol-guard connect` or `hol-guard sync --json` depending on the status output |
|
|
102
|
+
|
|
79
103
|
## Evidence-first decisions
|
|
80
104
|
|
|
81
105
|
Guard now scores local decisions from structured evidence, not only string heuristics. Each changed artifact carries:
|
|
@@ -10,6 +10,8 @@ Automated coverage in this phase includes:
|
|
|
10
10
|
- consumer-mode JSON contract generation against scanner fixtures
|
|
11
11
|
- local HTTP sync against a live in-process server instead of mocked transport
|
|
12
12
|
- scheduled self-hosted harness smoke through `.github/workflows/harness-smoke.yml`
|
|
13
|
+
- CLI DX contract tests for summary-first `run`, `explain`, `doctor`, `scan`, `lint`, and `verify` output
|
|
14
|
+
- scanner command consistency tests for nonexistent target handling across `scan`, `lint`, `verify`, `doctor`, and `submit`
|
|
13
15
|
|
|
14
16
|
Manual verification should include:
|
|
15
17
|
|
|
@@ -32,6 +34,14 @@ Manual verification should include:
|
|
|
32
34
|
- `hol-guard install codex`
|
|
33
35
|
- `hol-guard run codex --dry-run --default-action allow --json`
|
|
34
36
|
- `hol-guard receipts`
|
|
37
|
+
- `hol-guard explain codex:project:<artifact-name>`
|
|
38
|
+
- `hol-guard diff codex`
|
|
39
|
+
- `hol-guard events`
|
|
40
|
+
- `hol-guard abom`
|
|
41
|
+
- `plugin-scanner scan tests/fixtures/good-plugin --format json`
|
|
42
|
+
- `plugin-scanner lint tests/fixtures/good-plugin --format json`
|
|
43
|
+
- `plugin-scanner verify tests/fixtures/good-plugin --format json`
|
|
44
|
+
- `plugin-scanner doctor tests/fixtures/good-plugin --component mcp --bundle dist/doctor.zip`
|
|
35
45
|
- `codex mcp list`
|
|
36
46
|
- `cursor-agent mcp list`
|
|
37
47
|
- `antigravity --help`
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plugin-scanner"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.110"
|
|
8
8
|
description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hol-guard"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.110"
|
|
8
8
|
description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
{plugin_scanner-2.0.108 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -97,7 +97,7 @@ from ..runtime.secret_file_requests import (
|
|
|
97
97
|
extract_sensitive_tool_action_request,
|
|
98
98
|
is_explicitly_benign_tool_action_request,
|
|
99
99
|
)
|
|
100
|
-
from ..runtime.secret_sensitivity import SecretContentMatch, classify_secret_content
|
|
100
|
+
from ..runtime.secret_sensitivity import SecretContentMatch, classify_secret_content, classify_secret_path
|
|
101
101
|
from ..runtime.surface_server import GuardSurfaceRuntime
|
|
102
102
|
from ..store import GuardStore
|
|
103
103
|
from .approval_commands import add_approval_parser, run_approval_command
|
|
@@ -150,7 +150,15 @@ _GUARD_HELP_GROUPS = (
|
|
|
150
150
|
" bootstrap Detect, install, and launch the approval center\n"
|
|
151
151
|
" install Enable Guard management for a harness\n"
|
|
152
152
|
" uninstall Disable Guard management for a harness\n"
|
|
153
|
-
" update Update hol-guard in the current environment"
|
|
153
|
+
" update Update hol-guard in the current environment\n"
|
|
154
|
+
"\n"
|
|
155
|
+
"Command selection:\n"
|
|
156
|
+
" Use status for current posture and the next safe step\n"
|
|
157
|
+
" Use doctor for setup and runtime probes\n"
|
|
158
|
+
" Use diff for changed artifacts after a blocked launch\n"
|
|
159
|
+
" Use explain for detailed artifact evidence\n"
|
|
160
|
+
" Use approvals for queued decisions and receipts for audit history\n"
|
|
161
|
+
" Use events for the local timeline"
|
|
154
162
|
)
|
|
155
163
|
|
|
156
164
|
|
|
@@ -2991,16 +2999,47 @@ def _runtime_stored_policy_action(
|
|
|
2991
2999
|
def _runtime_artifact_policy_action(config: GuardConfig, artifact: GuardArtifact, harness: str) -> str:
|
|
2992
3000
|
if _prompt_requires_hard_block(artifact):
|
|
2993
3001
|
return "block"
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3002
|
+
canonical_harness = _canonical_harness_name(harness)
|
|
3003
|
+
risk_classes = _runtime_artifact_risk_classes(artifact)
|
|
3004
|
+
has_configured_risk_action = any(
|
|
3005
|
+
_resolve_configured_risk_action(config, risk_class, harness=canonical_harness) for risk_class in risk_classes
|
|
3006
|
+
)
|
|
3007
|
+
if has_configured_risk_action:
|
|
3008
|
+
risk_actions = [
|
|
3009
|
+
_resolve_configured_risk_action(config, risk_class, harness=canonical_harness)
|
|
3010
|
+
or resolve_risk_action(config, risk_class, harness=canonical_harness)
|
|
3011
|
+
for risk_class in risk_classes
|
|
3012
|
+
]
|
|
3013
|
+
resolved_actions = [action for action in risk_actions if action in VALID_GUARD_ACTIONS]
|
|
3014
|
+
if resolved_actions:
|
|
3015
|
+
return max(resolved_actions, key=_guard_action_severity)
|
|
3016
|
+
guard_default_action = _runtime_artifact_guard_default_action(artifact)
|
|
3017
|
+
if guard_default_action is not None:
|
|
3018
|
+
return guard_default_action
|
|
3019
|
+
risk_actions = [resolve_risk_action(config, risk_class, harness=canonical_harness) for risk_class in risk_classes]
|
|
2998
3020
|
resolved_actions = [action for action in risk_actions if action in VALID_GUARD_ACTIONS]
|
|
2999
3021
|
if resolved_actions:
|
|
3000
3022
|
return max(resolved_actions, key=_guard_action_severity)
|
|
3001
3023
|
return SAFE_CHANGED_HASH_ACTION
|
|
3002
3024
|
|
|
3003
3025
|
|
|
3026
|
+
def _resolve_configured_risk_action(config: GuardConfig, risk_class: str, *, harness: str) -> str | None:
|
|
3027
|
+
if config.harness_risk_actions is not None:
|
|
3028
|
+
harness_actions = config.harness_risk_actions.get(harness)
|
|
3029
|
+
if harness_actions is not None and risk_class in harness_actions:
|
|
3030
|
+
return harness_actions[risk_class]
|
|
3031
|
+
if config.risk_actions is not None and risk_class in config.risk_actions:
|
|
3032
|
+
return config.risk_actions[risk_class]
|
|
3033
|
+
return None
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
def _runtime_artifact_guard_default_action(artifact: GuardArtifact) -> str | None:
|
|
3037
|
+
value = artifact.metadata.get("guard_default_action")
|
|
3038
|
+
if value in VALID_GUARD_ACTIONS:
|
|
3039
|
+
return str(value)
|
|
3040
|
+
return None
|
|
3041
|
+
|
|
3042
|
+
|
|
3004
3043
|
def _guard_action_severity(action: str) -> int:
|
|
3005
3044
|
return {
|
|
3006
3045
|
"allow": 0,
|
|
@@ -3977,13 +4016,16 @@ def _codex_post_tool_output_artifact(
|
|
|
3977
4016
|
cwd: Path | None,
|
|
3978
4017
|
) -> GuardArtifact | None:
|
|
3979
4018
|
response_text = _collect_codex_tool_response_text(payload.get("tool_response"))
|
|
3980
|
-
content_matches = classify_secret_content(response_text)
|
|
3981
|
-
if not content_matches:
|
|
3982
|
-
return None
|
|
3983
4019
|
tool_name = _coalesce_string(payload.get("tool_name"), "Bash")
|
|
3984
4020
|
command_text = _codex_post_tool_command_text(payload)
|
|
3985
4021
|
if not command_text:
|
|
3986
4022
|
command_text = tool_name
|
|
4023
|
+
references_local_content = _codex_command_may_read_local_content(command_text, cwd=cwd)
|
|
4024
|
+
content_matches = classify_secret_content(response_text)
|
|
4025
|
+
if not content_matches and references_local_content:
|
|
4026
|
+
content_matches = classify_secret_content(response_text, suppress_samples=False)
|
|
4027
|
+
if not content_matches:
|
|
4028
|
+
return None
|
|
3987
4029
|
if _codex_source_inspection_can_skip_secret_output(
|
|
3988
4030
|
command_text=command_text,
|
|
3989
4031
|
response_text=response_text,
|
|
@@ -4001,6 +4043,10 @@ def _codex_post_tool_output_artifact(
|
|
|
4001
4043
|
sort_keys=True,
|
|
4002
4044
|
).encode("utf-8")
|
|
4003
4045
|
).hexdigest()
|
|
4046
|
+
runtime_default_action = "require-reapproval" if references_local_content else "warn"
|
|
4047
|
+
runtime_request_signals = ["tool output contains credential-looking material"]
|
|
4048
|
+
if references_local_content:
|
|
4049
|
+
runtime_request_signals.append("command references a sensitive local source")
|
|
4004
4050
|
return GuardArtifact(
|
|
4005
4051
|
artifact_id=f"codex:{source_scope}:tool-output:{fingerprint}",
|
|
4006
4052
|
name=f"{tool_name} credential-looking output",
|
|
@@ -4012,10 +4058,11 @@ def _codex_post_tool_output_artifact(
|
|
|
4012
4058
|
"tool_name": tool_name,
|
|
4013
4059
|
"command_text": command_text,
|
|
4014
4060
|
"action_class": "credential exfiltration shell command",
|
|
4061
|
+
"guard_default_action": runtime_default_action,
|
|
4015
4062
|
"request_summary": (
|
|
4016
4063
|
f"Codex tool `{tool_name}` produced credential-looking output while running `{command_text}`."
|
|
4017
4064
|
),
|
|
4018
|
-
"runtime_request_signals":
|
|
4065
|
+
"runtime_request_signals": runtime_request_signals,
|
|
4019
4066
|
"runtime_request_summary": (
|
|
4020
4067
|
"Requests a sensitive native tool action: credential-looking output reached Codex."
|
|
4021
4068
|
),
|
|
@@ -4027,6 +4074,209 @@ def _codex_post_tool_output_artifact(
|
|
|
4027
4074
|
)
|
|
4028
4075
|
|
|
4029
4076
|
|
|
4077
|
+
def _codex_command_references_sensitive_local_source(command_text: str, *, cwd: Path | None) -> bool:
|
|
4078
|
+
if _codex_text_contains_sensitive_path_token(command_text, cwd=cwd):
|
|
4079
|
+
return True
|
|
4080
|
+
try:
|
|
4081
|
+
parts = shlex.split(command_text)
|
|
4082
|
+
except ValueError:
|
|
4083
|
+
return False
|
|
4084
|
+
for part in parts:
|
|
4085
|
+
stripped = part.strip()
|
|
4086
|
+
if not stripped or stripped.startswith("-"):
|
|
4087
|
+
continue
|
|
4088
|
+
if _codex_token_is_url(stripped):
|
|
4089
|
+
continue
|
|
4090
|
+
if classify_secret_path(stripped, cwd=cwd) is not None:
|
|
4091
|
+
return True
|
|
4092
|
+
return False
|
|
4093
|
+
|
|
4094
|
+
|
|
4095
|
+
def _codex_token_is_url(token: str) -> bool:
|
|
4096
|
+
parsed = urllib.parse.urlparse(token)
|
|
4097
|
+
return bool(parsed.scheme and parsed.netloc)
|
|
4098
|
+
|
|
4099
|
+
|
|
4100
|
+
def _codex_text_contains_sensitive_path_token(text: str, *, cwd: Path | None) -> bool:
|
|
4101
|
+
for match in _PROMPT_PATH_TOKEN_PATTERN.finditer(text):
|
|
4102
|
+
if _codex_path_token_is_url_path(text, match.start()):
|
|
4103
|
+
continue
|
|
4104
|
+
if classify_secret_path(match.group(0), cwd=cwd) is not None:
|
|
4105
|
+
return True
|
|
4106
|
+
return False
|
|
4107
|
+
|
|
4108
|
+
|
|
4109
|
+
def _codex_path_token_is_url_path(text: str, start: int) -> bool:
|
|
4110
|
+
prefix = text[:start].lower()
|
|
4111
|
+
last_separator = max(prefix.rfind(separator) for separator in " \t\r\n'\"`<>|;(){}[]")
|
|
4112
|
+
token_prefix = prefix[last_separator + 1 :]
|
|
4113
|
+
if "://" in token_prefix:
|
|
4114
|
+
return True
|
|
4115
|
+
scheme = ""
|
|
4116
|
+
if token_prefix.endswith(":/"):
|
|
4117
|
+
scheme = token_prefix[:-2]
|
|
4118
|
+
elif token_prefix.endswith(":"):
|
|
4119
|
+
scheme = token_prefix[:-1]
|
|
4120
|
+
return _codex_token_prefix_is_url_scheme(scheme)
|
|
4121
|
+
|
|
4122
|
+
|
|
4123
|
+
def _codex_token_prefix_is_url_scheme(scheme: str) -> bool:
|
|
4124
|
+
return bool(scheme) and scheme[0].isalpha() and all(char.isalnum() or char in "+.-" for char in scheme)
|
|
4125
|
+
|
|
4126
|
+
|
|
4127
|
+
def _codex_command_may_read_local_content(command_text: str, *, cwd: Path | None) -> bool:
|
|
4128
|
+
if _codex_command_references_sensitive_local_source(command_text, cwd=cwd):
|
|
4129
|
+
return True
|
|
4130
|
+
if any(marker in command_text for marker in ("$(", "${", "`")):
|
|
4131
|
+
return True
|
|
4132
|
+
pipeline_segments = _split_codex_safe_read_only_pipeline(command_text)
|
|
4133
|
+
if pipeline_segments is not None:
|
|
4134
|
+
return any(
|
|
4135
|
+
_codex_pipeline_segment_may_read_local_content(segment, index=index, cwd=cwd)
|
|
4136
|
+
for index, segment in enumerate(pipeline_segments)
|
|
4137
|
+
)
|
|
4138
|
+
try:
|
|
4139
|
+
parts = _codex_shell_split(command_text)
|
|
4140
|
+
except ValueError:
|
|
4141
|
+
return True
|
|
4142
|
+
return _codex_command_parts_may_read_local_content(parts, cwd=cwd)
|
|
4143
|
+
|
|
4144
|
+
|
|
4145
|
+
def _codex_pipeline_segment_may_read_local_content(segment: str, *, index: int, cwd: Path | None) -> bool:
|
|
4146
|
+
try:
|
|
4147
|
+
parts = _codex_shell_split(segment)
|
|
4148
|
+
except ValueError:
|
|
4149
|
+
return True
|
|
4150
|
+
if not parts:
|
|
4151
|
+
return False
|
|
4152
|
+
if index == 0:
|
|
4153
|
+
return _codex_command_parts_may_read_local_content(parts, cwd=cwd)
|
|
4154
|
+
return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
|
|
4155
|
+
segment, cwd=cwd
|
|
4156
|
+
)
|
|
4157
|
+
|
|
4158
|
+
|
|
4159
|
+
def _codex_command_parts_may_read_local_content(parts: list[str], *, cwd: Path | None) -> bool:
|
|
4160
|
+
for start in _codex_command_start_indexes(parts):
|
|
4161
|
+
previous_token = parts[start - 1] if start > 0 else None
|
|
4162
|
+
segment_parts = _codex_command_segment_parts(parts, start)
|
|
4163
|
+
if previous_token == "|":
|
|
4164
|
+
if _codex_command_sequence_is_read_only_source_inspection(segment_parts, cwd=cwd):
|
|
4165
|
+
return True
|
|
4166
|
+
continue
|
|
4167
|
+
if _codex_command_sequence_starts_with_local_reader(segment_parts, cwd=cwd):
|
|
4168
|
+
return True
|
|
4169
|
+
return False
|
|
4170
|
+
|
|
4171
|
+
|
|
4172
|
+
def _codex_command_start_indexes(parts: list[str]) -> list[int]:
|
|
4173
|
+
starts = [0] if parts else []
|
|
4174
|
+
for index, part in enumerate(parts[:-1]):
|
|
4175
|
+
if part in {"&&", "||", ";", "&", "|", "|&"}:
|
|
4176
|
+
starts.append(index + 1)
|
|
4177
|
+
return starts
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
def _codex_command_segment_parts(parts: list[str], start: int) -> list[str]:
|
|
4181
|
+
end = start
|
|
4182
|
+
while end < len(parts) and parts[end] not in {"&&", "||", ";", "&", "|", "|&"}:
|
|
4183
|
+
end += 1
|
|
4184
|
+
return parts[start:end]
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
def _codex_command_sequence_is_read_only_source_inspection(parts: list[str], *, cwd: Path | None) -> bool:
|
|
4188
|
+
command_parts = _codex_unwrapped_command_parts(parts)
|
|
4189
|
+
if not command_parts:
|
|
4190
|
+
return False
|
|
4191
|
+
segment = shlex.join(command_parts)
|
|
4192
|
+
return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
|
|
4193
|
+
segment, cwd=cwd
|
|
4194
|
+
)
|
|
4195
|
+
|
|
4196
|
+
|
|
4197
|
+
def _codex_command_sequence_starts_with_local_reader(parts: list[str], *, cwd: Path | None) -> bool:
|
|
4198
|
+
command_parts = _codex_unwrapped_command_parts(parts)
|
|
4199
|
+
if not command_parts:
|
|
4200
|
+
return False
|
|
4201
|
+
if _codex_command_parts_are_git_grep(command_parts):
|
|
4202
|
+
return True
|
|
4203
|
+
return _codex_command_part_is_local_reader(command_parts, 0, cwd=cwd)
|
|
4204
|
+
|
|
4205
|
+
|
|
4206
|
+
def _codex_command_parts_are_git_grep(parts: list[str]) -> bool:
|
|
4207
|
+
return bool(parts) and Path(parts[0]).name.lower() == "git" and _git_grep_search_args(parts[1:]) is not None
|
|
4208
|
+
|
|
4209
|
+
|
|
4210
|
+
def _codex_unwrapped_command_parts(parts: list[str]) -> list[str]:
|
|
4211
|
+
remaining = parts
|
|
4212
|
+
while remaining:
|
|
4213
|
+
executable = Path(remaining[0]).name.lower()
|
|
4214
|
+
if executable == "command":
|
|
4215
|
+
remaining = _codex_strip_command_wrapper(remaining[1:])
|
|
4216
|
+
continue
|
|
4217
|
+
if executable == "env":
|
|
4218
|
+
remaining = _codex_strip_env_wrapper(remaining[1:])
|
|
4219
|
+
continue
|
|
4220
|
+
return remaining
|
|
4221
|
+
return []
|
|
4222
|
+
|
|
4223
|
+
|
|
4224
|
+
def _codex_strip_command_wrapper(parts: list[str]) -> list[str]:
|
|
4225
|
+
index = 0
|
|
4226
|
+
while index < len(parts) and parts[index] in {"-p", "-v", "-V"}:
|
|
4227
|
+
index += 1
|
|
4228
|
+
if index < len(parts) and parts[index] == "--":
|
|
4229
|
+
index += 1
|
|
4230
|
+
return parts[index:]
|
|
4231
|
+
|
|
4232
|
+
|
|
4233
|
+
def _codex_strip_env_wrapper(parts: list[str]) -> list[str]:
|
|
4234
|
+
index = 0
|
|
4235
|
+
while index < len(parts):
|
|
4236
|
+
part = parts[index]
|
|
4237
|
+
if part == "--":
|
|
4238
|
+
return parts[index + 1 :]
|
|
4239
|
+
if part in {"-i", "-0", "--ignore-environment", "--null"}:
|
|
4240
|
+
index += 1
|
|
4241
|
+
continue
|
|
4242
|
+
if part in {"-u", "--unset", "-C", "--chdir", "-S", "--split-string"}:
|
|
4243
|
+
index += 2
|
|
4244
|
+
continue
|
|
4245
|
+
if part.startswith(("--unset=", "--chdir=", "--split-string=")):
|
|
4246
|
+
index += 1
|
|
4247
|
+
continue
|
|
4248
|
+
if part.startswith("-"):
|
|
4249
|
+
index += 1
|
|
4250
|
+
continue
|
|
4251
|
+
if "=" in part and not part.startswith("="):
|
|
4252
|
+
index += 1
|
|
4253
|
+
continue
|
|
4254
|
+
return parts[index:]
|
|
4255
|
+
return []
|
|
4256
|
+
|
|
4257
|
+
|
|
4258
|
+
def _codex_shell_split(command_text: str) -> list[str]:
|
|
4259
|
+
lexer = shlex.shlex(command_text, posix=True, punctuation_chars=True)
|
|
4260
|
+
lexer.whitespace_split = True
|
|
4261
|
+
lexer.commenters = ""
|
|
4262
|
+
return list(lexer)
|
|
4263
|
+
|
|
4264
|
+
|
|
4265
|
+
def _codex_command_part_is_local_reader(parts: list[str], index: int, *, cwd: Path | None) -> bool:
|
|
4266
|
+
local_read_commands = {"cat", "grep", "head", "rg", "sed", "tail"}
|
|
4267
|
+
executable = Path(parts[index]).name.lower()
|
|
4268
|
+
if executable not in local_read_commands:
|
|
4269
|
+
return False
|
|
4270
|
+
if index == 0:
|
|
4271
|
+
return True
|
|
4272
|
+
if parts[index - 1] == "|":
|
|
4273
|
+
segment = shlex.join(parts[index:])
|
|
4274
|
+
return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
|
|
4275
|
+
segment, cwd=cwd
|
|
4276
|
+
)
|
|
4277
|
+
return parts[index - 1] in {"&&", "||", ";", "&", "|&"}
|
|
4278
|
+
|
|
4279
|
+
|
|
4030
4280
|
def _codex_post_tool_command_is_read_only_source_inspection(
|
|
4031
4281
|
*,
|
|
4032
4282
|
payload: dict[str, object],
|