plugin-scanner 2.0.90__tar.gz → 2.0.91__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.
Files changed (337) hide show
  1. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/get-started.md +12 -0
  3. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/harness-support.md +5 -0
  4. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/testing-matrix.md +12 -0
  5. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/pyproject.toml +1 -1
  6. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/pyproject.toml.bak +1 -1
  7. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/__init__.py +2 -0
  8. plugin_scanner-2.0.91/src/codex_plugin_scanner/guard/adapters/openclaw.py +183 -0
  9. plugin_scanner-2.0.91/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +286 -0
  10. plugin_scanner-2.0.91/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +396 -0
  11. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/version.py +1 -1
  12. plugin_scanner-2.0.91/tests/test_openclaw_adapter.py +369 -0
  13. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.clusterfuzzlite/Dockerfile +0 -0
  14. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.clusterfuzzlite/build.sh +0 -0
  15. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.clusterfuzzlite/project.yaml +0 -0
  16. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  17. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.dockerignore +0 -0
  18. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/CODEOWNERS +0 -0
  19. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  20. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  21. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  22. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/dependabot.yml +0 -0
  23. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/ci.yml +0 -0
  24. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/codeql.yml +0 -0
  25. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/dependabot-uv-lock.yml +0 -0
  26. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/fuzz.yml +0 -0
  27. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/harness-smoke.yml +0 -0
  28. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/publish.yml +0 -0
  29. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.github/workflows/scorecard.yml +0 -0
  30. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.gitignore +0 -0
  31. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/.pre-commit-hooks.yaml +0 -0
  32. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/CONTRIBUTING.md +0 -0
  33. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/Dockerfile +0 -0
  34. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/LICENSE +0 -0
  35. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/README.md +0 -0
  36. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/SECURITY.md +0 -0
  37. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/index.html +0 -0
  38. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/package.json +0 -0
  39. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/pnpm-lock.yaml +0 -0
  40. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/apple-touch-icon.png +0 -0
  41. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  42. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/brand/Logo_Whole.png +0 -0
  43. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/favicon-16x16.png +0 -0
  44. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/favicon-32x32.png +0 -0
  45. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/public/favicon.ico +0 -0
  46. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/app.tsx +0 -0
  47. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/approval-center-layout.tsx +0 -0
  48. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/approval-center-primitives.tsx +0 -0
  49. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/approval-center-utils.ts +0 -0
  50. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/fleet-workspace.tsx +0 -0
  51. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/guard-api.ts +0 -0
  52. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/guard-demo.ts +0 -0
  53. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/guard-types.ts +0 -0
  54. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/main.tsx +0 -0
  55. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/receipts-workspace.tsx +0 -0
  56. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/runtime-overview.tsx +0 -0
  57. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/settings-workspace.tsx +0 -0
  58. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/styles.css +0 -0
  59. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/src/vite-env.d.ts +0 -0
  60. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/tsconfig.json +0 -0
  61. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/dashboard/vite.config.ts +0 -0
  62. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docker-requirements.txt +0 -0
  63. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/approval-audit.md +0 -0
  64. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/architecture.md +0 -0
  65. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/guard/local-vs-cloud.md +0 -0
  66. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/trust/mcp-trust-draft.md +0 -0
  67. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/trust/plugin-trust-draft.md +0 -0
  68. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/docs/trust/skill-trust-local.md +0 -0
  69. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/fuzzers/manifest_fuzzer.py +0 -0
  70. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/requirements.txt +0 -0
  71. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/schemas/plugin-quality.v1.json +0 -0
  72. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/schemas/scan-result.v1.json +0 -0
  73. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/schemas/verify-result.v1.json +0 -0
  74. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/__init__.py +0 -0
  75. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/action_runner.py +0 -0
  76. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  77. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  78. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  79. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/claude.py +0 -0
  80. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  81. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  82. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  83. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  84. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  85. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  86. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  87. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  88. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  89. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/security.py +0 -0
  90. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  91. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/cli.py +0 -0
  92. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/cli_ui.py +0 -0
  93. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/config.py +0 -0
  94. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  95. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  96. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  97. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  98. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  99. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  100. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  101. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  102. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  103. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/github_reporting.py +0 -0
  104. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  105. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  106. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  107. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  108. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  109. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  110. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  111. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  112. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  113. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  114. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  115. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  116. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  117. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  118. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  119. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  120. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  121. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  122. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  123. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/commands.py +0 -0
  124. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  125. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  126. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  127. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  128. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  129. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  130. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  131. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/config.py +0 -0
  132. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  133. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  134. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  135. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  136. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  137. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  138. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  139. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  140. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  141. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  142. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  143. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  144. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  145. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  146. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  147. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  148. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/incident.py +0 -0
  149. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  150. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  151. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/models.py +0 -0
  152. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  153. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  154. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/protect.py +0 -0
  155. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  156. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  157. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  158. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  159. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  160. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  161. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  162. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/risk.py +0 -0
  163. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  164. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  165. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  166. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  167. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  168. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  169. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  170. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  171. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/shims.py +0 -0
  172. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/store.py +0 -0
  173. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  174. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  175. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/guard/types.py +0 -0
  176. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  177. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  178. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  179. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  180. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  181. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/models.py +0 -0
  182. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/path_support.py +0 -0
  183. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/policy.py +0 -0
  184. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  185. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/repo_detect.py +0 -0
  186. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/reporting.py +0 -0
  187. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  188. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/rules/registry.py +0 -0
  189. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/rules/specs.py +0 -0
  190. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/scanner.py +0 -0
  191. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/submission.py +0 -0
  192. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/suppressions.py +0 -0
  193. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  194. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  195. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  196. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_models.py +0 -0
  197. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  198. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  199. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  200. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/trust_specs.py +0 -0
  201. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/src/codex_plugin_scanner/verification.py +0 -0
  202. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/__init__.py +0 -0
  203. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/conftest.py +0 -0
  204. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/__init__.py +0 -0
  205. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  206. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  207. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/bad-plugin/secrets.js +0 -0
  208. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  209. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  210. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/README.md +0 -0
  211. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  212. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  213. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  214. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/code-quality-bad/evil.js +0 -0
  215. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/code-quality-bad/inject.js +0 -0
  216. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  217. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  218. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/README.md +0 -0
  219. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  220. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  221. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  222. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  223. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/.codexignore +0 -0
  224. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/LICENSE +0 -0
  225. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/README.md +0 -0
  226. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  227. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  228. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  229. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  230. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  231. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  232. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  233. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  234. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  235. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  236. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  237. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  238. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  239. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  240. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  241. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  242. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  243. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  244. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  245. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  246. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/mcp-canary-server.py +0 -0
  247. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  248. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/mit-license/LICENSE +0 -0
  250. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  251. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  252. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  253. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  254. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  255. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  256. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  257. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  258. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  259. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  260. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  261. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  262. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  263. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  264. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  265. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  266. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  267. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  268. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/LICENSE +0 -0
  269. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/README.md +0 -0
  270. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  271. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  272. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  273. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  274. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  275. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  276. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  277. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  278. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test-trust-scoring.py +0 -0
  279. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test-trust-specs.py +0 -0
  280. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_action_runner.py +0 -0
  281. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_best_practices.py +0 -0
  282. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_cisco_install_surfaces.py +0 -0
  283. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_cli.py +0 -0
  284. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_code_quality.py +0 -0
  285. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_config.py +0 -0
  286. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_coverage_remaining.py +0 -0
  287. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_ecosystems.py +0 -0
  288. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_edge_cases.py +0 -0
  289. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_final_coverage.py +0 -0
  290. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_approvals.py +0 -0
  291. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_bootstrap.py +0 -0
  292. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_capabilities.py +0 -0
  293. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_claude_adapter.py +0 -0
  294. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_cli.py +0 -0
  295. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_codex_e2e.py +0 -0
  296. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_codex_install.py +0 -0
  297. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_codex_proxy.py +0 -0
  298. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_config_paths.py +0 -0
  299. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_connect_flow.py +0 -0
  300. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_consumer_mode.py +0 -0
  301. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_copilot_adapter.py +0 -0
  302. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_copilot_proxy.py +0 -0
  303. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_daemon_manager.py +0 -0
  304. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_event_schema_v1.py +0 -0
  305. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_events.py +0 -0
  306. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_launch_env.py +0 -0
  307. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_opencode_proxy.py +0 -0
  308. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_product_flow.py +0 -0
  309. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_protect.py +0 -0
  310. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_render.py +0 -0
  311. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_risk.py +0 -0
  312. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_runtime.py +0 -0
  313. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_store_migrations.py +0 -0
  314. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_surface_server.py +0 -0
  315. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_guard_verdicts.py +0 -0
  316. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_hermes_adapter.py +0 -0
  317. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_integration.py +0 -0
  318. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_lint_fixes.py +0 -0
  319. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_live_cisco_smoke.py +0 -0
  320. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_manifest.py +0 -0
  321. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_marketplace.py +0 -0
  322. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_mcp_security.py +0 -0
  323. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_operational_security.py +0 -0
  324. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_policy.py +0 -0
  325. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_quality_artifact.py +0 -0
  326. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_rule_registry.py +0 -0
  327. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_scanner.py +0 -0
  328. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_schema_contracts.py +0 -0
  329. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_security.py +0 -0
  330. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_security_ops.py +0 -0
  331. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_skill_security.py +0 -0
  332. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_submission.py +0 -0
  333. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_trust_scoring.py +0 -0
  334. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_trust_specs.py +0 -0
  335. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_verification.py +0 -0
  336. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/tests/test_versioning.py +0 -0
  337. {plugin_scanner-2.0.90 → plugin_scanner-2.0.91}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.90
3
+ Version: 2.0.91
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
@@ -163,6 +163,15 @@ Hermes gets the normal Guard shim plus a Guard-owned bundle at `<guard-home>/her
163
163
  Guard injects the managed overlay paths through `HERMES_GUARD_MCP_OVERLAY_PATH` and `HERMES_GUARD_PRETOOL_PATH` when
164
164
  you launch Hermes through Guard.
165
165
 
166
+ OpenClaw gets the normal Guard shim plus a Guard-owned bundle at `<guard-home>/openclaw/` with:
167
+
168
+ - `overlay.json`
169
+ - `pretool-hook.json`
170
+ - `manifest.json`
171
+
172
+ Guard injects the managed overlay paths through `OPENCLAW_GUARD_OVERLAY_PATH` and `OPENCLAW_GUARD_PRETOOL_PATH` when
173
+ you launch OpenClaw through Guard. It does not mutate `~/.openclaw/openclaw.json`.
174
+
166
175
  ## Harness approval model
167
176
 
168
177
  Guard uses three approval tiers:
@@ -189,6 +198,9 @@ Current strategy:
189
198
  - `hermes`
190
199
  prefers the managed Hermes same-channel path when Guard owns the overlay bundle, falls back to the approval center,
191
200
  and keeps browser auto-open off for blocked requests
201
+ - `openclaw`
202
+ scans OpenClaw gateway config, channel posture, MCP servers, workspace skills, user skills, and OpenClaw-owned skills,
203
+ then prefers native-or-center delivery once the managed overlay bundle exists
192
204
  - `gemini`
193
205
  scans `.gemini/settings.json`, extension manifests, hooks, MCP registrations, and Gemini skill directories before
194
206
  launch, then routes blocked changes to the approval center
@@ -42,6 +42,11 @@ Current Guard support in this repo:
42
42
  - supports `hol-guard hermes bootstrap` and a Guard-managed Hermes overlay bundle under Guard home
43
43
  - rewrites managed Hermes MCP entries through Guard’s existing proxy path and uses native-or-center delivery when the managed bundle is present
44
44
  - blocks sensitive file reads and Docker-sensitive native pre-tool actions through the existing Guard hook path
45
+ - `openclaw`
46
+ - detects `~/.openclaw/openclaw.json`, gateway posture, channels, MCP servers, workspace skills, user skills, and OpenClaw-owned skills
47
+ - supports a Guard-managed OpenClaw overlay bundle under Guard home without mutating user OpenClaw config
48
+ - flags open DM channel posture and remote MCP endpoints before launch so chat-originated agent work can be reviewed
49
+ - uses native-or-center delivery when the managed bundle is present and keeps browser auto-open off for blocked requests
45
50
  - `opencode`
46
51
  - detects global and project config, MCP servers, config-defined commands, markdown commands, npm plugins, local
47
52
  plugin files, and OpenCode-compatible skill directories
@@ -20,7 +20,9 @@ Manual verification should include:
20
20
  - `hol-guard detect antigravity --json`
21
21
  - `hol-guard detect gemini --json`
22
22
  - `hol-guard detect opencode --json`
23
+ - `hol-guard detect openclaw --json`
23
24
  - `hol-guard install opencode --json`
25
+ - `hol-guard install openclaw --json`
24
26
  - `hol-guard update --dry-run --json`
25
27
  - `hol-guard run cursor --dry-run --default-action allow --json`
26
28
  - `hol-guard run gemini --dry-run --default-action allow --json`
@@ -36,6 +38,7 @@ Manual verification should include:
36
38
  - `gemini --help`
37
39
  - `opencode --help`
38
40
  - `opencode run --help`
41
+ - `openclaw --help`
39
42
 
40
43
  First-party canaries for local manual validation:
41
44
 
@@ -53,6 +56,15 @@ real `opencode` binary:
53
56
  - a blocked prompt request queues an approval
54
57
  - approving that request lets Guard hand off to `opencode run --dir <workspace> ...`
55
58
 
59
+ OpenClaw manual validation should include one isolated local gateway config where you prove all of the following against
60
+ the real `openclaw` binary:
61
+
62
+ - an open DM policy with wildcard senders is surfaced as a channel risk
63
+ - a remote MCP endpoint is surfaced as a network risk
64
+ - a newly added workspace skill blocks before launch when policy requires reapproval
65
+ - `hol-guard install openclaw` creates the managed overlay and pre-tool bundle under Guard home
66
+ - approving a blocked OpenClaw request resolves through native-or-center delivery without mutating user config
67
+
56
68
  Nightly release-bar coverage should include:
57
69
 
58
70
  - Codex on a self-hosted Linux runner
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.90"
7
+ version = "2.0.91"
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.90"
7
+ version = "2.0.91"
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"
@@ -10,6 +10,7 @@ from .copilot import CopilotHarnessAdapter
10
10
  from .cursor import CursorHarnessAdapter
11
11
  from .gemini import GeminiHarnessAdapter
12
12
  from .hermes import HermesHarnessAdapter
13
+ from .openclaw import OpenClawHarnessAdapter
13
14
  from .opencode import OpenCodeHarnessAdapter
14
15
 
15
16
  ADAPTERS: tuple[HarnessAdapter, ...] = (
@@ -20,6 +21,7 @@ ADAPTERS: tuple[HarnessAdapter, ...] = (
20
21
  AntigravityHarnessAdapter(),
21
22
  GeminiHarnessAdapter(),
22
23
  HermesHarnessAdapter(),
24
+ OpenClawHarnessAdapter(),
23
25
  OpenCodeHarnessAdapter(),
24
26
  )
25
27
 
@@ -0,0 +1,183 @@
1
+ """OpenClaw harness adapter."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+ from ..models import GuardArtifact, HarnessDetection
9
+ from ..shims import install_guard_shim, remove_guard_shim
10
+ from .base import (
11
+ HarnessAdapter,
12
+ HarnessContext,
13
+ _command_available,
14
+ _ensure_path_within_root,
15
+ _json_payload,
16
+ _run_command_probe,
17
+ )
18
+ from .openclaw_config import load_config
19
+ from .openclaw_support import (
20
+ config_artifacts,
21
+ config_path,
22
+ install_state,
23
+ managed_root,
24
+ overlay_payload,
25
+ pretool_payload,
26
+ skill_artifacts,
27
+ )
28
+
29
+ _OPENCLAW_MANAGED_APPROVAL_TIER = "native-or-center"
30
+ _OPENCLAW_MANAGED_PROMPT_CHANNEL = "native"
31
+
32
+
33
+ class OpenClawHarnessAdapter(HarnessAdapter):
34
+ """Discover OpenClaw gateway config, channels, MCP servers, and skills."""
35
+
36
+ harness = "openclaw"
37
+ executable = "openclaw"
38
+ approval_tier = "approval-center"
39
+ approval_summary = (
40
+ "Guard can scan OpenClaw gateway config, channels, skills, and MCP servers before agent sessions run."
41
+ )
42
+ fallback_hint = "Connect OpenClaw through the Guard-managed overlay or resolve requests in the approval center."
43
+ approval_prompt_channel = "native-fallback"
44
+ approval_auto_open_browser = False
45
+
46
+ def policy_path(self, context: HarnessContext) -> Path:
47
+ return config_path(context)
48
+
49
+ def detect(self, context: HarnessContext) -> HarnessDetection:
50
+ path = config_path(context)
51
+ payload = load_config(path)
52
+ found_paths: list[str] = []
53
+ artifacts: list[GuardArtifact] = []
54
+ if payload:
55
+ found_paths.append(str(path))
56
+ artifacts.extend(config_artifacts(context, path, payload))
57
+ artifacts.extend(skill_artifacts(context, payload, found_paths))
58
+ return HarnessDetection(
59
+ harness=self.harness,
60
+ installed=bool(found_paths) or _command_available(self.executable),
61
+ command_available=_command_available(self.executable),
62
+ config_paths=tuple(found_paths),
63
+ artifacts=tuple(artifacts),
64
+ )
65
+
66
+ def install(self, context: HarnessContext) -> dict[str, object]:
67
+ shim_manifest = install_guard_shim(self.harness, context)
68
+ root = managed_root(context)
69
+ manifest_path = root / "manifest.json"
70
+ overlay_path = root / "overlay.json"
71
+ pretool_path = root / "pretool-hook.json"
72
+ root.mkdir(parents=True, exist_ok=True)
73
+ existing_manifest = _json_payload(manifest_path)
74
+ state = install_state(
75
+ existing_manifest=existing_manifest,
76
+ overlay_path=overlay_path,
77
+ pretool_path=pretool_path,
78
+ )
79
+ detection = self.detect(context)
80
+ overlay_path.write_text(json.dumps(overlay_payload(detection), indent=2) + "\n", encoding="utf-8")
81
+ pretool_path.write_text(json.dumps(pretool_payload(context=context), indent=2) + "\n", encoding="utf-8")
82
+ manifest = {
83
+ "harness": self.harness,
84
+ "active": True,
85
+ "config_path": str(overlay_path),
86
+ **shim_manifest,
87
+ "install_state": state,
88
+ "managed_root": str(root),
89
+ "managed_manifest_path": str(manifest_path),
90
+ "managed_overlay_path": str(overlay_path),
91
+ "pretool_hook_path": str(pretool_path),
92
+ "capabilities": {
93
+ "same_channel": True,
94
+ "pretool": True,
95
+ "channel_posture": True,
96
+ "mcp_proxy": True,
97
+ },
98
+ "config_paths": list(detection.config_paths),
99
+ "artifact_count": len(detection.artifacts),
100
+ "notes": [
101
+ "Guard generated an OpenClaw overlay bundle for gateway posture and pre-tool protection.",
102
+ *[str(note) for note in shim_manifest.get("notes", [])],
103
+ ],
104
+ }
105
+ manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
106
+ return manifest
107
+
108
+ def uninstall(self, context: HarnessContext) -> dict[str, object]:
109
+ shim_manifest = remove_guard_shim(self.harness, context)
110
+ root = managed_root(context)
111
+ manifest = _json_payload(root / "manifest.json")
112
+ removed_paths: list[str] = []
113
+ for key in ("managed_manifest_path", "managed_overlay_path", "pretool_hook_path"):
114
+ value = manifest.get(key)
115
+ if not isinstance(value, str) or not value:
116
+ continue
117
+ path = Path(value)
118
+ _ensure_path_within_root(root, path, label=key)
119
+ if path.exists():
120
+ path.unlink()
121
+ removed_paths.append(str(path))
122
+ return {
123
+ "harness": self.harness,
124
+ "active": False,
125
+ "config_path": str(root / "overlay.json"),
126
+ **shim_manifest,
127
+ "removed_paths": removed_paths,
128
+ "notes": [
129
+ "Guard removed the managed OpenClaw overlay bundle and kept user OpenClaw config untouched.",
130
+ *[str(note) for note in shim_manifest.get("notes", [])],
131
+ ],
132
+ }
133
+
134
+ def launch_environment(self, context: HarnessContext) -> dict[str, str]:
135
+ manifest = _json_payload(managed_root(context) / "manifest.json")
136
+ overlay_path = manifest.get("managed_overlay_path")
137
+ pretool_path = manifest.get("pretool_hook_path")
138
+ if not isinstance(overlay_path, str) or not isinstance(pretool_path, str):
139
+ return {}
140
+ return {
141
+ "OPENCLAW_GUARD_OVERLAY_PATH": overlay_path,
142
+ "OPENCLAW_GUARD_PRETOOL_PATH": pretool_path,
143
+ "OPENCLAW_GUARD_CHANNEL_POSTURE": "enabled",
144
+ }
145
+
146
+ def runtime_probe(self, context: HarnessContext) -> dict[str, object] | None:
147
+ manifest = _json_payload(managed_root(context) / "manifest.json")
148
+ overlay_path = manifest.get("managed_overlay_path")
149
+ pretool_path = manifest.get("pretool_hook_path")
150
+ return {
151
+ "command": _run_command_probe([self.executable, "--help"]) if _command_available(self.executable) else None,
152
+ "managed_install_present": bool(manifest),
153
+ "managed_install_ready": (
154
+ isinstance(overlay_path, str)
155
+ and Path(overlay_path).exists()
156
+ and isinstance(pretool_path, str)
157
+ and Path(pretool_path).exists()
158
+ ),
159
+ }
160
+
161
+ def approval_flow(self, *, managed_install: dict[str, object] | None = None) -> dict[str, object]:
162
+ manifest = managed_install.get("manifest") if isinstance(managed_install, dict) else None
163
+ capabilities = manifest.get("capabilities") if isinstance(manifest, dict) else None
164
+ same_channel = isinstance(capabilities, dict) and bool(capabilities.get("same_channel"))
165
+ if same_channel:
166
+ return {
167
+ "tier": _OPENCLAW_MANAGED_APPROVAL_TIER,
168
+ "summary": (
169
+ "Guard uses OpenClaw native agent/channel delivery first and falls back to the approval center."
170
+ ),
171
+ "fallback_hint": "Use the Guard approval center if OpenClaw cannot surface the pending request inline.",
172
+ "prompt_channel": _OPENCLAW_MANAGED_PROMPT_CHANNEL,
173
+ "auto_open_browser": False,
174
+ }
175
+ return {
176
+ "tier": "approval-center",
177
+ "summary": "Guard keeps OpenClaw approvals in the local approval center without forcing a browser open.",
178
+ "fallback_hint": (
179
+ "Resolve pending OpenClaw requests from the Guard approval center or `hol-guard approvals`."
180
+ ),
181
+ "prompt_channel": "native-fallback",
182
+ "auto_open_browser": False,
183
+ }
@@ -0,0 +1,286 @@
1
+ """OpenClaw configuration loading helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ from pathlib import Path
8
+
9
+ _MAX_INCLUDE_DEPTH = 8
10
+ _CONFIG_SUFFIXES = {".json", ".json5", ".yaml", ".yml"}
11
+
12
+
13
+ def load_config(path: Path) -> dict[str, object]:
14
+ return _load_config(path, seen=set(), depth=0)
15
+
16
+
17
+ def _load_config(path: Path, *, seen: set[Path], depth: int) -> dict[str, object]:
18
+ if depth > _MAX_INCLUDE_DEPTH:
19
+ return {}
20
+ try:
21
+ resolved_path = path.resolve()
22
+ except (OSError, RuntimeError):
23
+ return {}
24
+ if resolved_path in seen:
25
+ return {}
26
+ try:
27
+ raw = resolved_path.read_text(encoding="utf-8")
28
+ except (OSError, UnicodeDecodeError):
29
+ return {}
30
+ payload = _parse_config_payload(raw)
31
+ if not isinstance(payload, dict):
32
+ return {}
33
+ return _resolve_includes(resolved_path, payload, seen={*seen, resolved_path}, depth=depth)
34
+
35
+
36
+ def _resolve_includes(path: Path, payload: dict[str, object], *, seen: set[Path], depth: int) -> dict[str, object]:
37
+ include_value = payload.get("$include")
38
+ include_paths = _include_paths(path.parent, include_value)
39
+ merged: dict[str, object] = {}
40
+ for include_path in include_paths:
41
+ included_payload = _load_config(include_path, seen=seen, depth=depth + 1)
42
+ merged = _deep_merge(merged, included_payload)
43
+ local_payload = {key: value for key, value in payload.items() if key != "$include"}
44
+ return _deep_merge(merged, local_payload)
45
+
46
+
47
+ def _include_paths(base_dir: Path, value: object) -> tuple[Path, ...]:
48
+ values = value if isinstance(value, list) else [value]
49
+ paths: list[Path] = []
50
+ for item in values:
51
+ if not isinstance(item, str) or not item.strip():
52
+ continue
53
+ candidate = Path(item.strip()).expanduser()
54
+ path = candidate if candidate.is_absolute() else base_dir / candidate
55
+ if path.suffix.lower() in _CONFIG_SUFFIXES:
56
+ paths.append(path)
57
+ return tuple(paths)
58
+
59
+
60
+ def _deep_merge(base: dict[str, object], overlay: dict[str, object]) -> dict[str, object]:
61
+ result = dict(base)
62
+ for key, value in overlay.items():
63
+ existing = result.get(key)
64
+ if isinstance(existing, dict) and isinstance(value, dict):
65
+ result[key] = _deep_merge(existing, value)
66
+ else:
67
+ result[key] = value
68
+ return result
69
+
70
+
71
+ def _parse_config_payload(raw: str) -> object:
72
+ try:
73
+ return json.loads(raw)
74
+ except json.JSONDecodeError:
75
+ pass
76
+ stripped = _strip_json_comments(raw)
77
+ normalized = _strip_trailing_json_commas(stripped)
78
+ try:
79
+ return json.loads(normalized)
80
+ except json.JSONDecodeError:
81
+ pass
82
+ json5_normalized = _strip_trailing_json_commas(
83
+ _convert_single_quoted_strings(_quote_unquoted_object_keys(stripped))
84
+ )
85
+ try:
86
+ return json.loads(json5_normalized)
87
+ except json.JSONDecodeError:
88
+ return {}
89
+
90
+
91
+ def _strip_json_comments(text: str) -> str:
92
+ output: list[str] = []
93
+ quote: str | None = None
94
+ escape = False
95
+ in_line_comment = False
96
+ in_block_comment = False
97
+ index = 0
98
+ while index < len(text):
99
+ char = text[index]
100
+ next_char = text[index + 1] if index + 1 < len(text) else ""
101
+ if in_line_comment:
102
+ if char == "\n":
103
+ in_line_comment = False
104
+ output.append(char)
105
+ index += 1
106
+ continue
107
+ if in_block_comment:
108
+ if char == "*" and next_char == "/":
109
+ in_block_comment = False
110
+ index += 2
111
+ continue
112
+ if char == "\n":
113
+ output.append(char)
114
+ index += 1
115
+ continue
116
+ if quote is not None:
117
+ output.append(char)
118
+ if escape:
119
+ escape = False
120
+ elif char == "\\":
121
+ escape = True
122
+ elif char == quote:
123
+ quote = None
124
+ index += 1
125
+ continue
126
+ if char in {"'", '"'}:
127
+ quote = char
128
+ output.append(char)
129
+ index += 1
130
+ continue
131
+ if char == "/" and next_char == "/":
132
+ in_line_comment = True
133
+ index += 2
134
+ continue
135
+ if char == "/" and next_char == "*":
136
+ in_block_comment = True
137
+ index += 2
138
+ continue
139
+ output.append(char)
140
+ index += 1
141
+ return "".join(output)
142
+
143
+
144
+ def _strip_trailing_json_commas(text: str) -> str:
145
+ output: list[str] = []
146
+ quote: str | None = None
147
+ escape = False
148
+ index = 0
149
+ while index < len(text):
150
+ char = text[index]
151
+ if quote is not None:
152
+ output.append(char)
153
+ if escape:
154
+ escape = False
155
+ elif char == "\\":
156
+ escape = True
157
+ elif char == quote:
158
+ quote = None
159
+ index += 1
160
+ continue
161
+ if char in {"'", '"'}:
162
+ quote = char
163
+ output.append(char)
164
+ index += 1
165
+ continue
166
+ if char == ",":
167
+ lookahead = index + 1
168
+ while lookahead < len(text) and text[lookahead] in " \t\r\n":
169
+ lookahead += 1
170
+ if lookahead < len(text) and text[lookahead] in "}]":
171
+ index += 1
172
+ continue
173
+ output.append(char)
174
+ index += 1
175
+ return "".join(output)
176
+
177
+
178
+ def _quote_unquoted_object_keys(text: str) -> str:
179
+ output: list[str] = []
180
+ quote: str | None = None
181
+ escape = False
182
+ expecting_key = False
183
+ index = 0
184
+ while index < len(text):
185
+ char = text[index]
186
+ if quote is not None:
187
+ output.append(char)
188
+ if escape:
189
+ escape = False
190
+ elif char == "\\":
191
+ escape = True
192
+ elif char == quote:
193
+ quote = None
194
+ index += 1
195
+ continue
196
+ if char in {"'", '"'}:
197
+ quote = char
198
+ output.append(char)
199
+ index += 1
200
+ continue
201
+ if char in "{,":
202
+ expecting_key = True
203
+ output.append(char)
204
+ index += 1
205
+ continue
206
+ if expecting_key and char.isspace():
207
+ output.append(char)
208
+ index += 1
209
+ continue
210
+ if expecting_key and _starts_identifier(char):
211
+ match = re.match(r"[A-Za-z_$][A-Za-z0-9_$-]*", text[index:])
212
+ if match is not None:
213
+ key = match.group(0)
214
+ lookahead = index + len(key)
215
+ while lookahead < len(text) and text[lookahead].isspace():
216
+ lookahead += 1
217
+ if lookahead < len(text) and text[lookahead] == ":":
218
+ output.append(json.dumps(key))
219
+ index += len(key)
220
+ expecting_key = False
221
+ continue
222
+ expecting_key = False
223
+ output.append(char)
224
+ index += 1
225
+ return "".join(output)
226
+
227
+
228
+ def _convert_single_quoted_strings(text: str) -> str:
229
+ output: list[str] = []
230
+ quote: str | None = None
231
+ escape = False
232
+ index = 0
233
+ while index < len(text):
234
+ char = text[index]
235
+ if quote == "'":
236
+ if escape:
237
+ _append_single_quote_escape(output, char)
238
+ escape = False
239
+ elif char == "\\":
240
+ escape = True
241
+ elif char == "'":
242
+ quote = None
243
+ output.append('"')
244
+ elif char == '"':
245
+ output.append('\\"')
246
+ else:
247
+ output.append(char)
248
+ index += 1
249
+ continue
250
+ if quote == '"':
251
+ output.append(char)
252
+ if escape:
253
+ escape = False
254
+ elif char == "\\":
255
+ escape = True
256
+ elif char == '"':
257
+ quote = None
258
+ index += 1
259
+ continue
260
+ if char == "'":
261
+ quote = "'"
262
+ output.append('"')
263
+ index += 1
264
+ continue
265
+ if char == '"':
266
+ quote = '"'
267
+ output.append(char)
268
+ index += 1
269
+ return "".join(output)
270
+
271
+
272
+ def _append_single_quote_escape(output: list[str], char: str) -> None:
273
+ if char == "'":
274
+ output.append("'")
275
+ elif char == '"':
276
+ output.append('\\"')
277
+ elif char == "\\":
278
+ output.append("\\\\")
279
+ elif char in {"b", "f", "n", "r", "t", "/"}:
280
+ output.append(f"\\{char}")
281
+ else:
282
+ output.append(char)
283
+
284
+
285
+ def _starts_identifier(char: str) -> bool:
286
+ return char.isalpha() or char in {"_", "$"}