plugin-scanner 2.0.83__tar.gz → 2.0.84__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 (333) hide show
  1. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/commands.py +31 -4
  5. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +57 -15
  6. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/version.py +1 -1
  7. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_runtime.py +131 -0
  8. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_mcp_security.py +124 -0
  9. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.clusterfuzzlite/Dockerfile +0 -0
  10. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.clusterfuzzlite/build.sh +0 -0
  11. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.clusterfuzzlite/project.yaml +0 -0
  12. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  13. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.dockerignore +0 -0
  14. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/CODEOWNERS +0 -0
  15. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  16. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  17. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  18. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/dependabot.yml +0 -0
  19. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/ci.yml +0 -0
  20. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/codeql.yml +0 -0
  21. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/dependabot-uv-lock.yml +0 -0
  22. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/fuzz.yml +0 -0
  23. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/harness-smoke.yml +0 -0
  24. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/publish.yml +0 -0
  25. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.github/workflows/scorecard.yml +0 -0
  26. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.gitignore +0 -0
  27. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/.pre-commit-hooks.yaml +0 -0
  28. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/CONTRIBUTING.md +0 -0
  29. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/Dockerfile +0 -0
  30. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/LICENSE +0 -0
  31. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/README.md +0 -0
  32. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/SECURITY.md +0 -0
  33. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/index.html +0 -0
  34. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/package.json +0 -0
  35. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/pnpm-lock.yaml +0 -0
  36. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/apple-touch-icon.png +0 -0
  37. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  38. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Whole.png +0 -0
  39. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/favicon-16x16.png +0 -0
  40. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/favicon-32x32.png +0 -0
  41. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/public/favicon.ico +0 -0
  42. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/app.tsx +0 -0
  43. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/approval-center-layout.tsx +0 -0
  44. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/approval-center-primitives.tsx +0 -0
  45. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/approval-center-utils.ts +0 -0
  46. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/fleet-workspace.tsx +0 -0
  47. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/guard-api.ts +0 -0
  48. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/guard-demo.ts +0 -0
  49. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/guard-types.ts +0 -0
  50. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/main.tsx +0 -0
  51. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/receipts-workspace.tsx +0 -0
  52. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/runtime-overview.tsx +0 -0
  53. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/settings-workspace.tsx +0 -0
  54. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/styles.css +0 -0
  55. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/src/vite-env.d.ts +0 -0
  56. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/tsconfig.json +0 -0
  57. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/dashboard/vite.config.ts +0 -0
  58. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docker-requirements.txt +0 -0
  59. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/approval-audit.md +0 -0
  60. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/architecture.md +0 -0
  61. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/get-started.md +0 -0
  62. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/harness-support.md +0 -0
  63. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/local-vs-cloud.md +0 -0
  64. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/guard/testing-matrix.md +0 -0
  65. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/trust/mcp-trust-draft.md +0 -0
  66. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/trust/plugin-trust-draft.md +0 -0
  67. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/docs/trust/skill-trust-local.md +0 -0
  68. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/fuzzers/manifest_fuzzer.py +0 -0
  69. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/requirements.txt +0 -0
  70. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/schemas/plugin-quality.v1.json +0 -0
  71. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/schemas/scan-result.v1.json +0 -0
  72. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/schemas/verify-result.v1.json +0 -0
  73. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/__init__.py +0 -0
  74. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/action_runner.py +0 -0
  75. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  76. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  77. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  78. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/claude.py +0 -0
  79. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  80. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  81. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  82. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  83. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  84. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  85. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  86. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  87. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  88. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/security.py +0 -0
  89. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  90. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli.py +0 -0
  91. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli_ui.py +0 -0
  92. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/config.py +0 -0
  93. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  94. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  95. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  96. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  97. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  98. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  99. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  100. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  101. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  102. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/github_reporting.py +0 -0
  103. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  104. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  105. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  106. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  107. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  108. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  109. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  110. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  111. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  112. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  113. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  114. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  115. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  116. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  117. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  118. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  119. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  120. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  121. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  122. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  123. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  124. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  125. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  126. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  127. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  128. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  129. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  130. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/config.py +0 -0
  131. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  132. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  133. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  134. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  135. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  136. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  137. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  138. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  139. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  140. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  141. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  142. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  143. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  144. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  145. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  146. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  147. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/incident.py +0 -0
  148. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  149. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  150. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/models.py +0 -0
  151. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  152. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  153. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/protect.py +0 -0
  154. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  155. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  156. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  157. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  158. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  159. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  160. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  161. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/risk.py +0 -0
  162. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  163. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  164. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  165. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  166. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  167. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  168. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  169. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  170. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/shims.py +0 -0
  171. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store.py +0 -0
  172. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  173. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  174. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/types.py +0 -0
  175. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  176. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  177. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  178. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  179. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/models.py +0 -0
  180. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/path_support.py +0 -0
  181. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/policy.py +0 -0
  182. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  183. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/repo_detect.py +0 -0
  184. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/reporting.py +0 -0
  185. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  186. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/registry.py +0 -0
  187. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/specs.py +0 -0
  188. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/scanner.py +0 -0
  189. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/submission.py +0 -0
  190. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/suppressions.py +0 -0
  191. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  192. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  193. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  194. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_models.py +0 -0
  195. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  196. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  197. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  198. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_specs.py +0 -0
  199. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/verification.py +0 -0
  200. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/__init__.py +0 -0
  201. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/conftest.py +0 -0
  202. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/__init__.py +0 -0
  203. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  204. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  205. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/secrets.js +0 -0
  206. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  207. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  208. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/README.md +0 -0
  209. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  210. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  211. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  212. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/evil.js +0 -0
  213. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/inject.js +0 -0
  214. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  215. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  216. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/README.md +0 -0
  217. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  218. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  219. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  220. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  221. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codexignore +0 -0
  222. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/LICENSE +0 -0
  223. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/README.md +0 -0
  224. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  225. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  226. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  227. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  228. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  229. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  230. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  231. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  232. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  233. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  234. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  235. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  236. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  237. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  238. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  239. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  240. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  241. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  242. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  243. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  244. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/mcp-canary-server.py +0 -0
  245. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  246. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  247. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/mit-license/LICENSE +0 -0
  248. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  250. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  251. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  252. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  253. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  254. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  255. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  256. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  257. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  258. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  259. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  260. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  261. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  262. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  263. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  264. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  265. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  266. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/LICENSE +0 -0
  267. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/README.md +0 -0
  268. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  269. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  270. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  271. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  272. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  273. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  274. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  275. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  276. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test-trust-scoring.py +0 -0
  277. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test-trust-specs.py +0 -0
  278. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_action_runner.py +0 -0
  279. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_best_practices.py +0 -0
  280. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_cisco_install_surfaces.py +0 -0
  281. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_cli.py +0 -0
  282. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_code_quality.py +0 -0
  283. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_config.py +0 -0
  284. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_coverage_remaining.py +0 -0
  285. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_ecosystems.py +0 -0
  286. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_edge_cases.py +0 -0
  287. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_final_coverage.py +0 -0
  288. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_approvals.py +0 -0
  289. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_bootstrap.py +0 -0
  290. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_capabilities.py +0 -0
  291. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_claude_adapter.py +0 -0
  292. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_cli.py +0 -0
  293. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_codex_e2e.py +0 -0
  294. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_codex_install.py +0 -0
  295. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_codex_proxy.py +0 -0
  296. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_config_paths.py +0 -0
  297. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_connect_flow.py +0 -0
  298. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_consumer_mode.py +0 -0
  299. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_copilot_adapter.py +0 -0
  300. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_copilot_proxy.py +0 -0
  301. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_daemon_manager.py +0 -0
  302. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_event_schema_v1.py +0 -0
  303. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_events.py +0 -0
  304. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_launch_env.py +0 -0
  305. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_opencode_proxy.py +0 -0
  306. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_product_flow.py +0 -0
  307. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_protect.py +0 -0
  308. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_render.py +0 -0
  309. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_risk.py +0 -0
  310. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_store_migrations.py +0 -0
  311. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_surface_server.py +0 -0
  312. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_guard_verdicts.py +0 -0
  313. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_hermes_adapter.py +0 -0
  314. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_integration.py +0 -0
  315. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_lint_fixes.py +0 -0
  316. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_live_cisco_smoke.py +0 -0
  317. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_manifest.py +0 -0
  318. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_marketplace.py +0 -0
  319. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_operational_security.py +0 -0
  320. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_policy.py +0 -0
  321. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_quality_artifact.py +0 -0
  322. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_rule_registry.py +0 -0
  323. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_scanner.py +0 -0
  324. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_schema_contracts.py +0 -0
  325. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_security.py +0 -0
  326. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_security_ops.py +0 -0
  327. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_skill_security.py +0 -0
  328. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_submission.py +0 -0
  329. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_trust_scoring.py +0 -0
  330. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_trust_specs.py +0 -0
  331. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_verification.py +0 -0
  332. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/tests/test_versioning.py +0 -0
  333. {plugin_scanner-2.0.83 → plugin_scanner-2.0.84}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.83
3
+ Version: 2.0.84
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.83"
7
+ version = "2.0.84"
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.83"
7
+ version = "2.0.84"
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"
@@ -3816,7 +3816,13 @@ _CODEX_SEARCH_OPTION_VALUE_FLAGS = frozenset(
3816
3816
  _CODEX_SEARCH_OPTION_VALUE_FLAGS_BY_EXECUTABLE = {
3817
3817
  "rg": frozenset({"-T"}),
3818
3818
  }
3819
- _CODEX_SEARCH_UNSAFE_FLAGS = frozenset({"--pre"})
3819
+ _CODEX_SEARCH_UNSAFE_FLAGS = frozenset({"--dereference-recursive", "--follow", "--pre"})
3820
+ _CODEX_SEARCH_UNSAFE_SHORT_FLAGS_BY_EXECUTABLE = {
3821
+ "egrep": frozenset({"R"}),
3822
+ "fgrep": frozenset({"R"}),
3823
+ "grep": frozenset({"R"}),
3824
+ "rg": frozenset({"L"}),
3825
+ }
3820
3826
  _CODEX_GIT_GLOBAL_VALUE_FLAGS = frozenset(
3821
3827
  {"-c", "--config-env", "--exec-path", "--git-dir", "--work-tree", "--namespace"}
3822
3828
  )
@@ -3988,6 +3994,7 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
3988
3994
  positional: list[str] = []
3989
3995
  skip_next = False
3990
3996
  pattern_from_option = False
3997
+ after_option_terminator = False
3991
3998
  option_value_flags = _CODEX_SEARCH_OPTION_VALUE_FLAGS | _CODEX_SEARCH_OPTION_VALUE_FLAGS_BY_EXECUTABLE.get(
3992
3999
  executable, frozenset()
3993
4000
  )
@@ -3995,7 +4002,13 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
3995
4002
  if skip_next:
3996
4003
  skip_next = False
3997
4004
  continue
3998
- if arg in _CODEX_SEARCH_UNSAFE_FLAGS or any(arg.startswith(f"{flag}=") for flag in _CODEX_SEARCH_UNSAFE_FLAGS):
4005
+ if after_option_terminator:
4006
+ positional.append(arg)
4007
+ continue
4008
+ if arg == "--":
4009
+ after_option_terminator = True
4010
+ continue
4011
+ if _codex_search_arg_is_unsafe(arg, executable=executable, option_value_flags=option_value_flags):
3999
4012
  return False
4000
4013
  if arg in _CODEX_SEARCH_PATTERN_VALUE_FLAGS:
4001
4014
  pattern_from_option = True
@@ -4012,8 +4025,6 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
4012
4025
  continue
4013
4026
  if any(arg.startswith(f"{flag}=") for flag in option_value_flags):
4014
4027
  continue
4015
- if arg == "--":
4016
- continue
4017
4028
  if arg.startswith("-"):
4018
4029
  continue
4019
4030
  positional.append(arg)
@@ -4026,6 +4037,22 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
4026
4037
  return bool(targets) and all(_codex_search_target_is_source_like(target, cwd=cwd) for target in targets)
4027
4038
 
4028
4039
 
4040
+ def _codex_search_arg_is_unsafe(arg: str, *, executable: str, option_value_flags: frozenset[str]) -> bool:
4041
+ if arg in _CODEX_SEARCH_UNSAFE_FLAGS:
4042
+ return True
4043
+ if any(arg.startswith(f"{flag}=") for flag in _CODEX_SEARCH_UNSAFE_FLAGS):
4044
+ return True
4045
+ if not arg.startswith("-") or arg.startswith("--"):
4046
+ return False
4047
+ unsafe_short_flags = _CODEX_SEARCH_UNSAFE_SHORT_FLAGS_BY_EXECUTABLE.get(executable, frozenset())
4048
+ for flag in arg[1:]:
4049
+ if flag in unsafe_short_flags:
4050
+ return True
4051
+ if f"-{flag}" in option_value_flags:
4052
+ return False
4053
+ return False
4054
+
4055
+
4029
4056
  def _codex_search_target_is_source_like(target: str, *, cwd: Path | None) -> bool:
4030
4057
  stripped = target.strip().strip("'\"")
4031
4058
  if not stripped:
@@ -47,6 +47,13 @@ class CiscoMcpScanSummary:
47
47
  scan_mode: str = "static"
48
48
 
49
49
 
50
+ @dataclass(frozen=True, slots=True)
51
+ class _StaticScanTarget:
52
+ read_path: Path
53
+ tool_name: str
54
+ content_type: str
55
+
56
+
50
57
  def _empty_counts() -> dict[str, int]:
51
58
  return {severity.value: 0 for severity in Severity}
52
59
 
@@ -235,15 +242,24 @@ def _normalize_finding(plugin_dir: Path, file_path: Path, finding: object) -> Fi
235
242
  )
236
243
 
237
244
 
238
- def _collect_static_targets(plugin_dir: Path) -> tuple[Path, ...]:
245
+ def _collect_static_targets(plugin_dir: Path) -> tuple[_StaticScanTarget, ...]:
239
246
  config_path = plugin_dir / ".mcp.json"
240
- if not config_path.is_file():
247
+ resolved_config_path = _safe_resolved_static_target(plugin_dir, config_path)
248
+ if resolved_config_path is None:
241
249
  return ()
242
250
 
243
- targets: list[Path] = []
251
+ targets: list[_StaticScanTarget] = []
252
+ seen_targets: set[Path] = set()
244
253
  try:
245
- if config_path.stat().st_size <= _MAX_TARGET_SIZE_BYTES:
246
- targets.append(config_path)
254
+ if resolved_config_path.stat().st_size <= _MAX_TARGET_SIZE_BYTES:
255
+ targets.append(
256
+ _StaticScanTarget(
257
+ read_path=resolved_config_path,
258
+ tool_name=config_path.name,
259
+ content_type="mcp-config",
260
+ )
261
+ )
262
+ seen_targets.add(resolved_config_path)
247
263
  except OSError:
248
264
  pass
249
265
  for root, dirs, files in os.walk(plugin_dir, topdown=True):
@@ -253,15 +269,40 @@ def _collect_static_targets(plugin_dir: Path) -> tuple[Path, ...]:
253
269
  file_path = current_dir / file_name
254
270
  if file_path == config_path or file_path.suffix.lower() not in _SOURCE_SUFFIXES:
255
271
  continue
272
+ resolved_file_path = _safe_resolved_static_target(plugin_dir, file_path)
273
+ if resolved_file_path is None or resolved_file_path in seen_targets:
274
+ continue
256
275
  try:
257
- if file_path.stat().st_size > _MAX_TARGET_SIZE_BYTES:
276
+ if resolved_file_path.stat().st_size > _MAX_TARGET_SIZE_BYTES:
258
277
  continue
259
278
  except OSError:
260
279
  continue
261
- targets.append(file_path)
280
+ targets.append(
281
+ _StaticScanTarget(
282
+ read_path=resolved_file_path,
283
+ tool_name=resolved_file_path.name,
284
+ content_type="mcp-source",
285
+ )
286
+ )
287
+ seen_targets.add(resolved_file_path)
262
288
  return tuple(targets)
263
289
 
264
290
 
291
+ def _safe_resolved_static_target(plugin_dir: Path, target: Path) -> Path | None:
292
+ try:
293
+ resolved_root = plugin_dir.resolve(strict=True)
294
+ resolved_target = target.resolve(strict=True)
295
+ if not resolved_target.is_file():
296
+ return None
297
+ except (OSError, RuntimeError):
298
+ return None
299
+ try:
300
+ resolved_target.relative_to(resolved_root)
301
+ except ValueError:
302
+ return None
303
+ return resolved_target
304
+
305
+
265
306
  def _run_awaitable(awaitable: Awaitable[T]) -> T:
266
307
  try:
267
308
  asyncio.get_running_loop()
@@ -288,40 +329,41 @@ def _run_awaitable(awaitable: Awaitable[T]) -> T:
288
329
 
289
330
 
290
331
  async def _scan_targets(
291
- plugin_dir: Path, targets: tuple[Path, ...], analyzer: object
332
+ plugin_dir: Path, targets: tuple[_StaticScanTarget, ...], analyzer: object
292
333
  ) -> tuple[tuple[Finding, ...], int]:
293
334
  findings: list[Finding] = []
294
335
  targets_scanned = 0
295
336
  for target in targets:
296
337
  try:
297
- content = target.read_text(encoding="utf-8", errors="ignore")
338
+ content = target.read_path.read_text(encoding="utf-8", errors="ignore")
298
339
  except OSError:
299
340
  continue
300
- content_type = "mcp-config" if target.name == ".mcp.json" else "mcp-source"
301
341
  external_findings = await analyzer.analyze(
302
342
  content,
303
343
  {
304
- "tool_name": target.name,
305
- "content_type": content_type,
306
- "file_path": str(target),
344
+ "tool_name": target.tool_name,
345
+ "content_type": target.content_type,
346
+ "file_path": str(target.read_path),
307
347
  },
308
348
  )
309
349
  targets_scanned += 1
310
350
  for finding in external_findings:
311
- findings.append(_normalize_finding(plugin_dir, target, finding))
351
+ findings.append(_normalize_finding(plugin_dir, target.read_path, finding))
312
352
  return tuple(findings), targets_scanned
313
353
 
314
354
 
315
355
  def run_cisco_mcp_scan(plugin_dir: Path, mode: str = "auto") -> CiscoMcpScanSummary:
316
356
  """Run Cisco MCP scanner static analysis when available."""
317
357
 
358
+ config_path = plugin_dir / ".mcp.json"
359
+
318
360
  if mode == "off":
319
361
  return _build_summary(
320
362
  status=CiscoIntegrationStatus.SKIPPED,
321
363
  message="Cisco MCP scanning disabled by configuration.",
322
364
  )
323
365
 
324
- if not (plugin_dir / ".mcp.json").is_file():
366
+ if _safe_resolved_static_target(plugin_dir, config_path) is None:
325
367
  return _build_summary(
326
368
  status=CiscoIntegrationStatus.SKIPPED,
327
369
  message="No .mcp.json found; Cisco MCP scan skipped.",
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for tool version."""
2
2
 
3
- __version__ = "2.0.83"
3
+ __version__ = "2.0.84"
@@ -541,6 +541,137 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
541
541
  assert output["recorded"] is True
542
542
  assert "approval_requests" not in output
543
543
 
544
+ def test_codex_post_tool_use_allows_short_option_value_payloads(
545
+ self,
546
+ monkeypatch,
547
+ tmp_path,
548
+ capsys,
549
+ ) -> None:
550
+ home_dir = tmp_path / "home"
551
+ workspace_dir = tmp_path / "workspace"
552
+ _build_guard_fixture(home_dir, workspace_dir)
553
+ event = {
554
+ "event": "PostToolUse",
555
+ "tool_name": "Bash",
556
+ "tool_input": {"command": "rg -gLICENSE TOKEN src"},
557
+ "tool_response": {
558
+ "stdout": "src/config.ts:1:const auth_token = process.env.TOKEN",
559
+ },
560
+ "source_scope": "project",
561
+ }
562
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
563
+
564
+ rc = main(
565
+ [
566
+ "guard",
567
+ "hook",
568
+ "--home",
569
+ str(home_dir),
570
+ "--workspace",
571
+ str(workspace_dir),
572
+ "--harness",
573
+ "codex",
574
+ "--json",
575
+ ]
576
+ )
577
+ output = json.loads(capsys.readouterr().out)
578
+
579
+ assert rc == 0
580
+ assert output["recorded"] is True
581
+ assert "approval_requests" not in output
582
+
583
+ def test_codex_post_tool_use_allows_double_dash_terminated_literal_pattern(
584
+ self,
585
+ monkeypatch,
586
+ tmp_path,
587
+ capsys,
588
+ ) -> None:
589
+ home_dir = tmp_path / "home"
590
+ workspace_dir = tmp_path / "workspace"
591
+ _build_guard_fixture(home_dir, workspace_dir)
592
+ event = {
593
+ "event": "PostToolUse",
594
+ "tool_name": "Bash",
595
+ "tool_input": {"command": "rg -- --follow src"},
596
+ "tool_response": {
597
+ "stdout": "src/config.ts:1:const auth_token = process.env.TOKEN",
598
+ },
599
+ "source_scope": "project",
600
+ }
601
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
602
+
603
+ rc = main(
604
+ [
605
+ "guard",
606
+ "hook",
607
+ "--home",
608
+ str(home_dir),
609
+ "--workspace",
610
+ str(workspace_dir),
611
+ "--harness",
612
+ "codex",
613
+ "--json",
614
+ ]
615
+ )
616
+ output = json.loads(capsys.readouterr().out)
617
+
618
+ assert rc == 0
619
+ assert output["recorded"] is True
620
+ assert "approval_requests" not in output
621
+
622
+ @pytest.mark.parametrize(
623
+ "command",
624
+ (
625
+ "rg --follow TOKEN src",
626
+ "rg -L TOKEN src",
627
+ "grep -R TOKEN src",
628
+ ),
629
+ )
630
+ def test_codex_post_tool_use_blocks_symlink_following_source_search_flags(
631
+ self,
632
+ monkeypatch,
633
+ tmp_path,
634
+ capsys,
635
+ command: str,
636
+ ) -> None:
637
+ home_dir = tmp_path / "home"
638
+ workspace_dir = tmp_path / "workspace"
639
+ _build_guard_fixture(home_dir, workspace_dir)
640
+ secret_file = home_dir / ".aws" / "credentials"
641
+ _write_text(secret_file, "auth_token=outside-secret\n")
642
+ src_dir = workspace_dir / "src"
643
+ src_dir.mkdir()
644
+ (src_dir / "config.ts").symlink_to(secret_file)
645
+ event = {
646
+ "event": "PostToolUse",
647
+ "tool_name": "Bash",
648
+ "tool_input": {"command": command},
649
+ "tool_response": {
650
+ "stdout": "src/config.ts:1:auth_token=outside-secret",
651
+ },
652
+ "source_scope": "project",
653
+ }
654
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
655
+
656
+ rc = main(
657
+ [
658
+ "guard",
659
+ "hook",
660
+ "--home",
661
+ str(home_dir),
662
+ "--workspace",
663
+ str(workspace_dir),
664
+ "--harness",
665
+ "codex",
666
+ "--json",
667
+ ]
668
+ )
669
+ output = json.loads(capsys.readouterr().out)
670
+
671
+ assert rc == 1
672
+ assert output["artifact_type"] == "tool_action_request"
673
+ assert output["approval_requests"]
674
+
544
675
  def test_codex_post_tool_use_allows_ripgrep_type_not_source_search(
545
676
  self,
546
677
  monkeypatch,
@@ -103,6 +103,130 @@ def test_scan_includes_dist_descendants(monkeypatch, tmp_path: Path) -> None:
103
103
  assert any(path.endswith("dist/server.js") for path in analyzed_paths)
104
104
 
105
105
 
106
+ def test_scan_skips_source_symlink_resolving_outside_plugin_root(monkeypatch, tmp_path: Path) -> None:
107
+ plugin_dir = tmp_path / "plugin"
108
+ _write_plugin(plugin_dir)
109
+ outside_secret = tmp_path / "outside.py"
110
+ outside_secret.write_text("auth_token = 'outside-secret'\n", encoding="utf-8")
111
+ (plugin_dir / "leak.py").symlink_to(outside_secret)
112
+ analyzed_paths: list[str] = []
113
+ analyzed_contents: list[str] = []
114
+
115
+ class RecordingYaraAnalyzer:
116
+ def __init__(self, *args: object, **kwargs: object) -> None:
117
+ return None
118
+
119
+ async def analyze(self, content: str, context: dict[str, Any] | None = None) -> list[FakeCiscoFinding]:
120
+ analyzed_paths.append(str((context or {}).get("file_path", "")))
121
+ analyzed_contents.append(content)
122
+ return []
123
+
124
+ monkeypatch.setattr(
125
+ "codex_plugin_scanner.integrations.cisco_mcp_scanner._load_mcp_scanner_components",
126
+ lambda: {"YaraAnalyzer": RecordingYaraAnalyzer},
127
+ )
128
+
129
+ summary = run_cisco_mcp_scan(plugin_dir, mode="on")
130
+
131
+ assert summary.status == CiscoIntegrationStatus.ENABLED
132
+ assert summary.targets_scanned == 2
133
+ assert str(plugin_dir / "leak.py") not in analyzed_paths
134
+ assert all("outside-secret" not in content for content in analyzed_contents)
135
+
136
+
137
+ def test_scan_skips_symlinked_mcp_config_outside_plugin_root(monkeypatch, tmp_path: Path) -> None:
138
+ plugin_dir = tmp_path / "plugin"
139
+ _write_plugin(plugin_dir)
140
+ (plugin_dir / ".mcp.json").unlink()
141
+ outside_config = tmp_path / "outside-mcp.json"
142
+ outside_config.write_text(
143
+ json.dumps({"mcpServers": {"outside": {"command": "python", "args": ["secret.py"]}}}),
144
+ encoding="utf-8",
145
+ )
146
+ (plugin_dir / ".mcp.json").symlink_to(outside_config)
147
+ loader_state = {"called": False}
148
+
149
+ class RecordingYaraAnalyzer:
150
+ def __init__(self, *args: object, **kwargs: object) -> None:
151
+ return None
152
+
153
+ def _loader() -> dict[str, type[RecordingYaraAnalyzer]]:
154
+ loader_state["called"] = True
155
+ return {"YaraAnalyzer": RecordingYaraAnalyzer}
156
+
157
+ monkeypatch.setattr(
158
+ "codex_plugin_scanner.integrations.cisco_mcp_scanner._load_mcp_scanner_components",
159
+ _loader,
160
+ )
161
+
162
+ summary = run_cisco_mcp_scan(plugin_dir, mode="on")
163
+
164
+ assert summary.status == CiscoIntegrationStatus.SKIPPED
165
+ assert loader_state["called"] is False
166
+
167
+
168
+ def test_scan_resolves_in_root_symlink_targets_before_analysis(monkeypatch, tmp_path: Path) -> None:
169
+ plugin_dir = tmp_path / "plugin"
170
+ _write_plugin(plugin_dir)
171
+ real_source = plugin_dir / "real.py"
172
+ real_source.write_text("print('real')\n", encoding="utf-8")
173
+ (plugin_dir / "link.py").symlink_to(real_source)
174
+ analyzed_paths: list[str] = []
175
+
176
+ class RecordingYaraAnalyzer:
177
+ def __init__(self, *args: object, **kwargs: object) -> None:
178
+ return None
179
+
180
+ async def analyze(self, content: str, context: dict[str, Any] | None = None) -> list[FakeCiscoFinding]:
181
+ analyzed_paths.append(str((context or {}).get("file_path", "")))
182
+ return []
183
+
184
+ monkeypatch.setattr(
185
+ "codex_plugin_scanner.integrations.cisco_mcp_scanner._load_mcp_scanner_components",
186
+ lambda: {"YaraAnalyzer": RecordingYaraAnalyzer},
187
+ )
188
+
189
+ summary = run_cisco_mcp_scan(plugin_dir, mode="on")
190
+
191
+ assert summary.status == CiscoIntegrationStatus.ENABLED
192
+ assert summary.targets_scanned == 3
193
+ assert str(real_source.resolve()) in analyzed_paths
194
+ assert str(plugin_dir / "link.py") not in analyzed_paths
195
+
196
+
197
+ def test_scan_preserves_symlinked_mcp_config_identity(monkeypatch, tmp_path: Path) -> None:
198
+ plugin_dir = tmp_path / "plugin"
199
+ _write_plugin(plugin_dir)
200
+ real_config = plugin_dir / "configs" / "base.json"
201
+ real_config.parent.mkdir()
202
+ real_config.write_text(
203
+ json.dumps({"mcpServers": {"demo": {"command": "python", "args": ["server.py"]}}}),
204
+ encoding="utf-8",
205
+ )
206
+ (plugin_dir / ".mcp.json").unlink()
207
+ (plugin_dir / ".mcp.json").symlink_to(real_config)
208
+ analyzed_contexts: list[dict[str, Any]] = []
209
+
210
+ class RecordingYaraAnalyzer:
211
+ def __init__(self, *args: object, **kwargs: object) -> None:
212
+ return None
213
+
214
+ async def analyze(self, content: str, context: dict[str, Any] | None = None) -> list[FakeCiscoFinding]:
215
+ analyzed_contexts.append(dict(context or {}))
216
+ return []
217
+
218
+ monkeypatch.setattr(
219
+ "codex_plugin_scanner.integrations.cisco_mcp_scanner._load_mcp_scanner_components",
220
+ lambda: {"YaraAnalyzer": RecordingYaraAnalyzer},
221
+ )
222
+
223
+ summary = run_cisco_mcp_scan(plugin_dir, mode="on")
224
+
225
+ assert summary.status == CiscoIntegrationStatus.ENABLED
226
+ assert analyzed_contexts[0]["tool_name"] == ".mcp.json"
227
+ assert analyzed_contexts[0]["content_type"] == "mcp-config"
228
+
229
+
106
230
  def test_mcp_security_auto_mode_unavailable_is_not_applicable(monkeypatch, tmp_path: Path) -> None:
107
231
  plugin_dir = tmp_path / "plugin"
108
232
  _write_plugin(plugin_dir)
File without changes