plugin-scanner 2.0.89__tar.gz → 2.0.90__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.89 → plugin_scanner-2.0.90}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/commands.py +344 -10
  5. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/version.py +1 -1
  6. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_runtime.py +323 -0
  7. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.clusterfuzzlite/Dockerfile +0 -0
  8. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.clusterfuzzlite/build.sh +0 -0
  9. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.clusterfuzzlite/project.yaml +0 -0
  10. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  11. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.dockerignore +0 -0
  12. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/CODEOWNERS +0 -0
  13. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  14. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  15. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  16. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/dependabot.yml +0 -0
  17. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/ci.yml +0 -0
  18. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/codeql.yml +0 -0
  19. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/dependabot-uv-lock.yml +0 -0
  20. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/fuzz.yml +0 -0
  21. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/harness-smoke.yml +0 -0
  22. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/publish.yml +0 -0
  23. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.github/workflows/scorecard.yml +0 -0
  24. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.gitignore +0 -0
  25. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/.pre-commit-hooks.yaml +0 -0
  26. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/CONTRIBUTING.md +0 -0
  27. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/Dockerfile +0 -0
  28. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/LICENSE +0 -0
  29. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/README.md +0 -0
  30. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/SECURITY.md +0 -0
  31. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/index.html +0 -0
  32. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/package.json +0 -0
  33. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/pnpm-lock.yaml +0 -0
  34. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/apple-touch-icon.png +0 -0
  35. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  36. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/brand/Logo_Whole.png +0 -0
  37. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/favicon-16x16.png +0 -0
  38. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/favicon-32x32.png +0 -0
  39. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/public/favicon.ico +0 -0
  40. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/app.tsx +0 -0
  41. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/approval-center-layout.tsx +0 -0
  42. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/approval-center-primitives.tsx +0 -0
  43. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/approval-center-utils.ts +0 -0
  44. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/fleet-workspace.tsx +0 -0
  45. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/guard-api.ts +0 -0
  46. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/guard-demo.ts +0 -0
  47. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/guard-types.ts +0 -0
  48. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/main.tsx +0 -0
  49. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/receipts-workspace.tsx +0 -0
  50. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/runtime-overview.tsx +0 -0
  51. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/settings-workspace.tsx +0 -0
  52. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/styles.css +0 -0
  53. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/src/vite-env.d.ts +0 -0
  54. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/tsconfig.json +0 -0
  55. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/dashboard/vite.config.ts +0 -0
  56. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docker-requirements.txt +0 -0
  57. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/approval-audit.md +0 -0
  58. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/architecture.md +0 -0
  59. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/get-started.md +0 -0
  60. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/harness-support.md +0 -0
  61. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/local-vs-cloud.md +0 -0
  62. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/guard/testing-matrix.md +0 -0
  63. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/trust/mcp-trust-draft.md +0 -0
  64. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/trust/plugin-trust-draft.md +0 -0
  65. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/docs/trust/skill-trust-local.md +0 -0
  66. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/fuzzers/manifest_fuzzer.py +0 -0
  67. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/requirements.txt +0 -0
  68. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/schemas/plugin-quality.v1.json +0 -0
  69. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/schemas/scan-result.v1.json +0 -0
  70. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/schemas/verify-result.v1.json +0 -0
  71. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/__init__.py +0 -0
  72. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/action_runner.py +0 -0
  73. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  74. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  75. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  76. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/claude.py +0 -0
  77. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  78. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  79. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  80. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  81. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  82. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  83. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  84. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  85. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  86. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/security.py +0 -0
  87. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  88. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/cli.py +0 -0
  89. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/cli_ui.py +0 -0
  90. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/config.py +0 -0
  91. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  92. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  93. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  94. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  95. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  96. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  97. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  98. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  99. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  100. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/github_reporting.py +0 -0
  101. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  102. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  103. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  104. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  105. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  106. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  107. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  108. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  109. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  110. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  111. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  112. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  113. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  114. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  115. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  116. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  117. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  118. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  119. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  120. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  121. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  122. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  123. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  124. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  125. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  126. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  127. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  128. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/config.py +0 -0
  129. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  130. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  131. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  132. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  133. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  134. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  135. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  136. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  137. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  138. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  139. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  140. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  141. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  142. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  143. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  144. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  145. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/incident.py +0 -0
  146. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  147. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  148. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/models.py +0 -0
  149. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  150. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  151. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/protect.py +0 -0
  152. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  153. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  154. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  155. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  156. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  157. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  158. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  159. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/risk.py +0 -0
  160. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  161. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  162. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  163. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  164. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  165. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  166. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  167. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  168. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/shims.py +0 -0
  169. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/store.py +0 -0
  170. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  171. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  172. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/guard/types.py +0 -0
  173. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  174. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  175. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  176. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  177. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  178. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/models.py +0 -0
  179. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/path_support.py +0 -0
  180. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/policy.py +0 -0
  181. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  182. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/repo_detect.py +0 -0
  183. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/reporting.py +0 -0
  184. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  185. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/rules/registry.py +0 -0
  186. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/rules/specs.py +0 -0
  187. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/scanner.py +0 -0
  188. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/submission.py +0 -0
  189. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/suppressions.py +0 -0
  190. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  191. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  192. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  193. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_models.py +0 -0
  194. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  195. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  196. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  197. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/trust_specs.py +0 -0
  198. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/src/codex_plugin_scanner/verification.py +0 -0
  199. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/__init__.py +0 -0
  200. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/conftest.py +0 -0
  201. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/__init__.py +0 -0
  202. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  203. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  204. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/bad-plugin/secrets.js +0 -0
  205. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  206. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  207. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/README.md +0 -0
  208. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  209. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  210. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  211. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/code-quality-bad/evil.js +0 -0
  212. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/code-quality-bad/inject.js +0 -0
  213. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  214. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  215. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/README.md +0 -0
  216. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  217. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  218. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  219. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  220. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/.codexignore +0 -0
  221. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/LICENSE +0 -0
  222. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/README.md +0 -0
  223. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  224. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  225. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  226. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  227. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  228. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  229. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  230. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  231. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  232. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  233. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  234. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  235. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  236. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  237. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  238. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  239. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  240. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  241. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  242. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  243. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/mcp-canary-server.py +0 -0
  244. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  245. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  246. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/mit-license/LICENSE +0 -0
  247. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  248. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  249. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  250. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  251. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  252. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  253. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  254. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  255. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  256. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  257. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  258. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  259. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  260. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  261. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  262. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  263. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  264. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  265. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/LICENSE +0 -0
  266. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/README.md +0 -0
  267. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  268. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  269. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  270. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  271. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  272. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  273. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  274. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  275. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test-trust-scoring.py +0 -0
  276. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test-trust-specs.py +0 -0
  277. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_action_runner.py +0 -0
  278. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_best_practices.py +0 -0
  279. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_cisco_install_surfaces.py +0 -0
  280. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_cli.py +0 -0
  281. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_code_quality.py +0 -0
  282. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_config.py +0 -0
  283. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_coverage_remaining.py +0 -0
  284. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_ecosystems.py +0 -0
  285. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_edge_cases.py +0 -0
  286. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_final_coverage.py +0 -0
  287. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_approvals.py +0 -0
  288. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_bootstrap.py +0 -0
  289. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_capabilities.py +0 -0
  290. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_claude_adapter.py +0 -0
  291. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_cli.py +0 -0
  292. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_codex_e2e.py +0 -0
  293. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_codex_install.py +0 -0
  294. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_codex_proxy.py +0 -0
  295. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_config_paths.py +0 -0
  296. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_connect_flow.py +0 -0
  297. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_consumer_mode.py +0 -0
  298. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_copilot_adapter.py +0 -0
  299. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_copilot_proxy.py +0 -0
  300. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_daemon_manager.py +0 -0
  301. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_event_schema_v1.py +0 -0
  302. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_events.py +0 -0
  303. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_launch_env.py +0 -0
  304. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_opencode_proxy.py +0 -0
  305. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_product_flow.py +0 -0
  306. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_protect.py +0 -0
  307. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_render.py +0 -0
  308. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_risk.py +0 -0
  309. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_store_migrations.py +0 -0
  310. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_surface_server.py +0 -0
  311. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_guard_verdicts.py +0 -0
  312. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_hermes_adapter.py +0 -0
  313. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_integration.py +0 -0
  314. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_lint_fixes.py +0 -0
  315. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_live_cisco_smoke.py +0 -0
  316. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_manifest.py +0 -0
  317. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_marketplace.py +0 -0
  318. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_mcp_security.py +0 -0
  319. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_operational_security.py +0 -0
  320. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_policy.py +0 -0
  321. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_quality_artifact.py +0 -0
  322. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_rule_registry.py +0 -0
  323. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_scanner.py +0 -0
  324. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_schema_contracts.py +0 -0
  325. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_security.py +0 -0
  326. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_security_ops.py +0 -0
  327. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_skill_security.py +0 -0
  328. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_submission.py +0 -0
  329. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_trust_scoring.py +0 -0
  330. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_trust_specs.py +0 -0
  331. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_verification.py +0 -0
  332. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/tests/test_versioning.py +0 -0
  333. {plugin_scanner-2.0.89 → plugin_scanner-2.0.90}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.89
3
+ Version: 2.0.90
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.89"
7
+ version = "2.0.90"
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.89"
7
+ version = "2.0.90"
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"
@@ -3751,6 +3751,8 @@ def _hook_runtime_artifact(
3751
3751
  )
3752
3752
  if output_artifact is not None:
3753
3753
  return output_artifact
3754
+ if _codex_post_tool_command_is_read_only_source_inspection(payload=payload, cwd=workspace):
3755
+ return None
3754
3756
  if event_name == "UserPromptSubmit":
3755
3757
  prompt_text = payload.get("prompt")
3756
3758
  if isinstance(prompt_text, str) and prompt_text.strip():
@@ -3840,15 +3842,10 @@ def _codex_post_tool_output_artifact(
3840
3842
  if not response_text or _CODEX_SECRET_OUTPUT_PATTERN.search(response_text) is None:
3841
3843
  return None
3842
3844
  tool_name = _coalesce_string(payload.get("tool_name"), "Bash")
3843
- tool_input = payload.get("tool_input")
3844
- command_text = ""
3845
- if isinstance(tool_input, dict):
3846
- command = tool_input.get("command")
3847
- if isinstance(command, str):
3848
- command_text = command.strip()
3845
+ command_text = _codex_post_tool_command_text(payload)
3849
3846
  if not command_text:
3850
3847
  command_text = tool_name
3851
- if _codex_command_is_read_only_source_search(command_text, cwd=cwd):
3848
+ if _codex_command_is_read_only_source_inspection(command_text, cwd=cwd):
3852
3849
  return None
3853
3850
  fingerprint = hashlib.sha256(
3854
3851
  json.dumps(
@@ -3886,7 +3883,27 @@ def _codex_post_tool_output_artifact(
3886
3883
  )
3887
3884
 
3888
3885
 
3886
+ def _codex_post_tool_command_is_read_only_source_inspection(
3887
+ *,
3888
+ payload: dict[str, object],
3889
+ cwd: Path | None,
3890
+ ) -> bool:
3891
+ command_text = _codex_post_tool_command_text(payload)
3892
+ return bool(command_text) and _codex_command_is_read_only_source_inspection(command_text, cwd=cwd)
3893
+
3894
+
3895
+ def _codex_post_tool_command_text(payload: dict[str, object]) -> str:
3896
+ tool_input = payload.get("tool_input")
3897
+ if isinstance(tool_input, dict):
3898
+ command = tool_input.get("command")
3899
+ if isinstance(command, str):
3900
+ return command.strip()
3901
+ return ""
3902
+
3903
+
3889
3904
  _CODEX_READ_ONLY_SEARCH_COMMANDS = frozenset({"rg", "grep", "egrep", "fgrep"})
3905
+ _CODEX_READ_ONLY_VIEW_COMMANDS = frozenset({"cat", "head", "tail", "sed"})
3906
+ _CODEX_READ_ONLY_PIPE_FILTERS = frozenset({"head", "tail"})
3890
3907
  _CODEX_READ_ONLY_SEARCH_WRAPPERS = frozenset({"bash", "sh", "zsh"})
3891
3908
  _CODEX_SEARCH_PATTERN_VALUE_FLAGS = frozenset({"-e", "--regexp", "-f", "--file"})
3892
3909
  _CODEX_SEARCH_OPTION_VALUE_FLAGS = frozenset(
@@ -3966,6 +3983,202 @@ _CODEX_SENSITIVE_SEARCH_BASENAMES = frozenset(
3966
3983
  "id_rsa",
3967
3984
  }
3968
3985
  )
3986
+ _CODEX_SED_PRINT_SCRIPT_PATTERN = re.compile(r"^\s*(?:\$|\d+)?(?:\s*,\s*(?:\$|\d+))?p\s*$")
3987
+
3988
+
3989
+ def _codex_command_is_read_only_source_inspection(command_text: str, *, cwd: Path | None) -> bool:
3990
+ command = command_text.strip()
3991
+ if not command:
3992
+ return False
3993
+ if _codex_command_has_unquoted_glob_metachar(command):
3994
+ return False
3995
+ segments = _split_codex_safe_read_only_pipeline(command)
3996
+ if segments is None:
3997
+ return _codex_command_is_read_only_source_search(command, cwd=cwd) or _codex_command_is_read_only_source_view(
3998
+ command, cwd=cwd
3999
+ )
4000
+ if not segments:
4001
+ return False
4002
+ first_segment, *filter_segments = segments
4003
+ if not (
4004
+ _codex_command_is_read_only_source_search(first_segment, cwd=cwd)
4005
+ or _codex_command_is_read_only_source_view(first_segment, cwd=cwd)
4006
+ ):
4007
+ return False
4008
+ return all(_codex_command_is_bounded_read_only_filter(segment) for segment in filter_segments)
4009
+
4010
+
4011
+ def _codex_command_has_unquoted_glob_metachar(command: str) -> bool:
4012
+ quote: str | None = None
4013
+ escaped = False
4014
+ for char in command:
4015
+ if escaped:
4016
+ escaped = False
4017
+ continue
4018
+ if char == "\\":
4019
+ escaped = True
4020
+ continue
4021
+ if quote is not None:
4022
+ if char == quote:
4023
+ quote = None
4024
+ continue
4025
+ if char in {"'", '"'}:
4026
+ quote = char
4027
+ continue
4028
+ if char in {"*", "?", "[", "]", "{", "}"}:
4029
+ return True
4030
+ return False
4031
+
4032
+
4033
+ def _split_codex_safe_read_only_pipeline(command: str) -> list[str] | None:
4034
+ segments: list[str] = []
4035
+ current: list[str] = []
4036
+ quote: str | None = None
4037
+ escaped = False
4038
+ for char in command:
4039
+ if escaped:
4040
+ current.append(char)
4041
+ escaped = False
4042
+ continue
4043
+ if char == "\\":
4044
+ current.append(char)
4045
+ escaped = True
4046
+ continue
4047
+ if quote is not None:
4048
+ current.append(char)
4049
+ if char == quote:
4050
+ quote = None
4051
+ elif quote == '"' and (char == "`" or char == "$"):
4052
+ return None
4053
+ continue
4054
+ if char in {"'", '"'}:
4055
+ current.append(char)
4056
+ quote = char
4057
+ continue
4058
+ if char in {"\n", "\r", "&", ";", "<", "`"}:
4059
+ return None
4060
+ if char == "$":
4061
+ return None
4062
+ if char == "|":
4063
+ segment = "".join(current).strip()
4064
+ if not segment:
4065
+ return None
4066
+ stripped_segment = _strip_codex_safe_stderr_discard(segment)
4067
+ if stripped_segment is None:
4068
+ return None
4069
+ segments.append(stripped_segment)
4070
+ current = []
4071
+ continue
4072
+ current.append(char)
4073
+ segment = "".join(current).strip()
4074
+ if not segments:
4075
+ return None
4076
+ if not segment:
4077
+ return None
4078
+ stripped_segment = _strip_codex_safe_stderr_discard(segment)
4079
+ if stripped_segment is None:
4080
+ return None
4081
+ segments.append(stripped_segment)
4082
+ return segments
4083
+
4084
+
4085
+ def _strip_codex_safe_stderr_discard(segment: str) -> str | None:
4086
+ cleaned_segment = _remove_codex_safe_stderr_discard(segment)
4087
+ if cleaned_segment is None:
4088
+ return None
4089
+ try:
4090
+ parts = shlex.split(cleaned_segment)
4091
+ except ValueError:
4092
+ return None
4093
+ if not parts:
4094
+ return None
4095
+ if _codex_command_uses_untrusted_search_binary(parts[0]):
4096
+ return None
4097
+ return shlex.join(parts)
4098
+
4099
+
4100
+ def _remove_codex_safe_stderr_discard(segment: str) -> str | None:
4101
+ cleaned: list[str] = []
4102
+ quote: str | None = None
4103
+ escaped = False
4104
+ index = 0
4105
+ while index < len(segment):
4106
+ char = segment[index]
4107
+ if escaped:
4108
+ cleaned.append(char)
4109
+ escaped = False
4110
+ index += 1
4111
+ continue
4112
+ if char == "\\":
4113
+ cleaned.append(char)
4114
+ escaped = True
4115
+ index += 1
4116
+ continue
4117
+ if quote is not None:
4118
+ cleaned.append(char)
4119
+ if char == quote:
4120
+ quote = None
4121
+ index += 1
4122
+ continue
4123
+ if char in {"'", '"'}:
4124
+ cleaned.append(char)
4125
+ quote = char
4126
+ index += 1
4127
+ continue
4128
+ if segment.startswith("2>", index):
4129
+ after_redirect = index + 2
4130
+ while after_redirect < len(segment) and segment[after_redirect].isspace():
4131
+ after_redirect += 1
4132
+ if segment.startswith("/dev/null", after_redirect):
4133
+ after_target = after_redirect + len("/dev/null")
4134
+ if after_target == len(segment) or segment[after_target].isspace():
4135
+ index = after_target
4136
+ continue
4137
+ return None
4138
+ if char == ">":
4139
+ return None
4140
+ cleaned.append(char)
4141
+ index += 1
4142
+ return "".join(cleaned).strip()
4143
+
4144
+
4145
+ def _codex_command_is_bounded_read_only_filter(command_text: str) -> bool:
4146
+ try:
4147
+ parts = shlex.split(command_text)
4148
+ except ValueError:
4149
+ return False
4150
+ if not parts:
4151
+ return False
4152
+ if _codex_command_uses_untrusted_search_binary(parts[0]):
4153
+ return False
4154
+ executable = Path(parts[0]).name
4155
+ if executable not in _CODEX_READ_ONLY_PIPE_FILTERS:
4156
+ return False
4157
+ return _codex_head_tail_args_are_bounded_filter(parts[1:])
4158
+
4159
+
4160
+ def _codex_command_is_read_only_source_view(command_text: str, *, cwd: Path | None) -> bool:
4161
+ command = command_text.strip()
4162
+ if not command:
4163
+ return False
4164
+ if _codex_command_has_unquoted_shell_control(command):
4165
+ return False
4166
+ try:
4167
+ parts = shlex.split(command)
4168
+ except ValueError:
4169
+ return False
4170
+ if not parts:
4171
+ return False
4172
+ if _codex_command_uses_untrusted_search_binary(parts[0]):
4173
+ return False
4174
+ executable = Path(parts[0]).name
4175
+ if executable not in _CODEX_READ_ONLY_VIEW_COMMANDS:
4176
+ return False
4177
+ if executable == "sed":
4178
+ return _codex_sed_targets_are_read_only_source_like(parts[1:], cwd=cwd)
4179
+ if executable in {"head", "tail"}:
4180
+ return _codex_head_tail_targets_are_source_like(parts[1:], cwd=cwd)
4181
+ return _codex_cat_targets_are_source_like(parts[1:], cwd=cwd)
3969
4182
 
3970
4183
 
3971
4184
  def _codex_command_is_read_only_source_search(command_text: str, *, cwd: Path | None) -> bool:
@@ -4002,6 +4215,125 @@ def _codex_command_uses_untrusted_search_binary(executable_token: str) -> bool:
4002
4215
  return executable_token.startswith(".") or "/" in executable_token or "\\" in executable_token
4003
4216
 
4004
4217
 
4218
+ def _codex_cat_targets_are_source_like(args: list[str], *, cwd: Path | None) -> bool:
4219
+ targets: list[str] = []
4220
+ after_option_terminator = False
4221
+ for arg in args:
4222
+ if after_option_terminator:
4223
+ targets.append(arg)
4224
+ continue
4225
+ if arg == "--":
4226
+ after_option_terminator = True
4227
+ continue
4228
+ if arg == "-":
4229
+ return False
4230
+ if arg.startswith("-"):
4231
+ continue
4232
+ targets.append(arg)
4233
+ return bool(targets) and all(_codex_search_target_is_source_like(target, cwd=cwd) for target in targets)
4234
+
4235
+
4236
+ def _codex_head_tail_args_are_bounded_filter(args: list[str]) -> bool:
4237
+ targets, valid, skip_next = _parse_codex_head_tail_args(args)
4238
+ return valid and not skip_next and not targets
4239
+
4240
+
4241
+ def _codex_head_tail_targets_are_source_like(args: list[str], *, cwd: Path | None) -> bool:
4242
+ targets, valid, skip_next = _parse_codex_head_tail_args(args)
4243
+ return (
4244
+ valid
4245
+ and not skip_next
4246
+ and bool(targets)
4247
+ and all(_codex_search_target_is_source_like(target, cwd=cwd) for target in targets)
4248
+ )
4249
+
4250
+
4251
+ def _parse_codex_head_tail_args(args: list[str]) -> tuple[list[str], bool, bool]:
4252
+ targets: list[str] = []
4253
+ skip_next = False
4254
+ after_option_terminator = False
4255
+ for arg in args:
4256
+ if skip_next:
4257
+ skip_next = False
4258
+ if not _codex_count_arg_is_bounded(arg):
4259
+ return [], False, False
4260
+ continue
4261
+ if after_option_terminator:
4262
+ targets.append(arg)
4263
+ continue
4264
+ if arg == "--":
4265
+ after_option_terminator = True
4266
+ continue
4267
+ if arg in {"-n", "--lines", "-c", "--bytes"}:
4268
+ skip_next = True
4269
+ continue
4270
+ if arg.startswith("--lines=") or arg.startswith("--bytes="):
4271
+ _, value = arg.split("=", 1)
4272
+ if not _codex_count_arg_is_bounded(value):
4273
+ return [], False, False
4274
+ continue
4275
+ if re.fullmatch(r"-\d{1,6}", arg):
4276
+ continue
4277
+ if arg == "-":
4278
+ return [], False, False
4279
+ if arg.startswith("-"):
4280
+ return [], False, False
4281
+ targets.append(arg)
4282
+ return targets, True, skip_next
4283
+
4284
+
4285
+ def _codex_sed_targets_are_read_only_source_like(args: list[str], *, cwd: Path | None) -> bool:
4286
+ scripts: list[str] = []
4287
+ targets: list[str] = []
4288
+ skip_next_script = False
4289
+ after_option_terminator = False
4290
+ saw_print_suppression = False
4291
+ for arg in args:
4292
+ if skip_next_script:
4293
+ skip_next_script = False
4294
+ scripts.append(arg)
4295
+ continue
4296
+ if after_option_terminator:
4297
+ targets.append(arg)
4298
+ continue
4299
+ if arg == "--":
4300
+ after_option_terminator = True
4301
+ continue
4302
+ if arg in {"-i", "--in-place"} or arg.startswith(("-i", "--in-place=")):
4303
+ return False
4304
+ if arg == "-n" or arg == "--quiet" or arg == "--silent":
4305
+ saw_print_suppression = True
4306
+ continue
4307
+ if arg == "-e" or arg == "--expression":
4308
+ skip_next_script = True
4309
+ continue
4310
+ if arg.startswith("-e") and len(arg) > 2:
4311
+ scripts.append(arg[2:])
4312
+ continue
4313
+ if arg.startswith("--expression="):
4314
+ _, script = arg.split("=", 1)
4315
+ scripts.append(script)
4316
+ continue
4317
+ if arg.startswith("-"):
4318
+ return False
4319
+ if not scripts:
4320
+ scripts.append(arg)
4321
+ continue
4322
+ targets.append(arg)
4323
+ if skip_next_script or not scripts or not targets:
4324
+ return False
4325
+ if not saw_print_suppression:
4326
+ return False
4327
+ if not all(_CODEX_SED_PRINT_SCRIPT_PATTERN.fullmatch(script.strip()) for script in scripts):
4328
+ return False
4329
+ return all(_codex_search_target_is_source_like(target, cwd=cwd) for target in targets)
4330
+
4331
+
4332
+ def _codex_count_arg_is_bounded(value: str) -> bool:
4333
+ normalized = value.strip()
4334
+ return bool(re.fullmatch(r"\d{1,6}", normalized))
4335
+
4336
+
4005
4337
  def _git_grep_search_args(args: list[str]) -> list[str] | None:
4006
4338
  index = 0
4007
4339
  while index < len(args):
@@ -4051,7 +4383,7 @@ def _shell_wrapper_script_index(parts: list[str]) -> int | None:
4051
4383
  def _codex_command_has_unquoted_shell_control(command: str) -> bool:
4052
4384
  quote: str | None = None
4053
4385
  escaped = False
4054
- for index, char in enumerate(command):
4386
+ for char in command:
4055
4387
  if escaped:
4056
4388
  escaped = False
4057
4389
  continue
@@ -4063,7 +4395,7 @@ def _codex_command_has_unquoted_shell_control(command: str) -> bool:
4063
4395
  quote = None
4064
4396
  if quote == '"' and char == "`":
4065
4397
  return True
4066
- if quote == '"' and char == "$" and index + 1 < len(command) and command[index + 1] == "(":
4398
+ if quote == '"' and char == "$":
4067
4399
  return True
4068
4400
  continue
4069
4401
  if char in {"'", '"'}:
@@ -4073,7 +4405,7 @@ def _codex_command_has_unquoted_shell_control(command: str) -> bool:
4073
4405
  return True
4074
4406
  if char in {"|", "&", ";", ">", "<", "`"}:
4075
4407
  return True
4076
- if char == "$" and index + 1 < len(command) and command[index + 1] == "(":
4408
+ if char == "$":
4077
4409
  return True
4078
4410
  return False
4079
4411
 
@@ -4147,6 +4479,8 @@ def _codex_search_target_is_source_like(target: str, *, cwd: Path | None) -> boo
4147
4479
  return False
4148
4480
  if stripped.startswith(("~", "/")):
4149
4481
  return False
4482
+ if any(char in stripped for char in ("*", "?", "{", "}")):
4483
+ return False
4150
4484
  target_path = Path(stripped)
4151
4485
  base_dir = (cwd or Path.cwd()).resolve()
4152
4486
  unresolved_candidate = base_dir / target_path
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for tool version."""
2
2
 
3
- __version__ = "2.0.89"
3
+ __version__ = "2.0.90"