plugin-scanner 2.0.82__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.82 → plugin_scanner-2.0.84}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/commands.py +49 -4
  5. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +57 -15
  6. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/version.py +1 -1
  7. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_runtime.py +203 -11
  8. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_mcp_security.py +124 -0
  9. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/Dockerfile +0 -0
  10. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/build.sh +0 -0
  11. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/project.yaml +0 -0
  12. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  13. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.dockerignore +0 -0
  14. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/CODEOWNERS +0 -0
  15. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  16. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  17. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  18. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/dependabot.yml +0 -0
  19. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/ci.yml +0 -0
  20. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/codeql.yml +0 -0
  21. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/dependabot-uv-lock.yml +0 -0
  22. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/fuzz.yml +0 -0
  23. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/harness-smoke.yml +0 -0
  24. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/publish.yml +0 -0
  25. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/scorecard.yml +0 -0
  26. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.gitignore +0 -0
  27. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.pre-commit-hooks.yaml +0 -0
  28. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/CONTRIBUTING.md +0 -0
  29. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/Dockerfile +0 -0
  30. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/LICENSE +0 -0
  31. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/README.md +0 -0
  32. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/SECURITY.md +0 -0
  33. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/index.html +0 -0
  34. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/package.json +0 -0
  35. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/pnpm-lock.yaml +0 -0
  36. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/apple-touch-icon.png +0 -0
  37. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  38. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Whole.png +0 -0
  39. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon-16x16.png +0 -0
  40. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon-32x32.png +0 -0
  41. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon.ico +0 -0
  42. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/app.tsx +0 -0
  43. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-layout.tsx +0 -0
  44. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-primitives.tsx +0 -0
  45. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-utils.ts +0 -0
  46. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/fleet-workspace.tsx +0 -0
  47. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-api.ts +0 -0
  48. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-demo.ts +0 -0
  49. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-types.ts +0 -0
  50. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/main.tsx +0 -0
  51. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/receipts-workspace.tsx +0 -0
  52. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/runtime-overview.tsx +0 -0
  53. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/settings-workspace.tsx +0 -0
  54. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/styles.css +0 -0
  55. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/vite-env.d.ts +0 -0
  56. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/tsconfig.json +0 -0
  57. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/vite.config.ts +0 -0
  58. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docker-requirements.txt +0 -0
  59. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/approval-audit.md +0 -0
  60. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/architecture.md +0 -0
  61. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/get-started.md +0 -0
  62. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/harness-support.md +0 -0
  63. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/local-vs-cloud.md +0 -0
  64. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/testing-matrix.md +0 -0
  65. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/mcp-trust-draft.md +0 -0
  66. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/plugin-trust-draft.md +0 -0
  67. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/skill-trust-local.md +0 -0
  68. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/fuzzers/manifest_fuzzer.py +0 -0
  69. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/requirements.txt +0 -0
  70. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/plugin-quality.v1.json +0 -0
  71. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/scan-result.v1.json +0 -0
  72. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/verify-result.v1.json +0 -0
  73. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/__init__.py +0 -0
  74. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/action_runner.py +0 -0
  75. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  76. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  77. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  78. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/claude.py +0 -0
  79. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  80. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  81. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  82. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  83. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  84. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  85. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  86. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  87. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  88. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/security.py +0 -0
  89. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  90. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli.py +0 -0
  91. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli_ui.py +0 -0
  92. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/config.py +0 -0
  93. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  94. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  95. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  96. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  97. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  98. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  99. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  100. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  101. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  102. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/github_reporting.py +0 -0
  103. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  104. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  105. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  106. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  107. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  108. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  109. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  110. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  111. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  112. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  113. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  114. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  115. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  116. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  117. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  118. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  119. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  120. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  121. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  122. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  123. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  124. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  125. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  126. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  127. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  128. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  129. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  130. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/config.py +0 -0
  131. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  132. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  133. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  134. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  135. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  136. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  137. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  138. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  139. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  140. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  141. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  142. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  143. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  144. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  145. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  146. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  147. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/incident.py +0 -0
  148. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  149. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  150. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/models.py +0 -0
  151. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  152. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  153. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/protect.py +0 -0
  154. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  155. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  156. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  157. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  158. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  159. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  160. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  161. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/risk.py +0 -0
  162. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  163. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  164. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  165. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  166. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  167. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  168. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  169. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  170. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/shims.py +0 -0
  171. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store.py +0 -0
  172. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  173. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  174. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/types.py +0 -0
  175. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  176. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  177. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  178. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  179. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/models.py +0 -0
  180. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/path_support.py +0 -0
  181. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/policy.py +0 -0
  182. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  183. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/repo_detect.py +0 -0
  184. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/reporting.py +0 -0
  185. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  186. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/registry.py +0 -0
  187. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/specs.py +0 -0
  188. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/scanner.py +0 -0
  189. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/submission.py +0 -0
  190. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/suppressions.py +0 -0
  191. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  192. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  193. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  194. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_models.py +0 -0
  195. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  196. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  197. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  198. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_specs.py +0 -0
  199. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/verification.py +0 -0
  200. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/__init__.py +0 -0
  201. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/conftest.py +0 -0
  202. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/__init__.py +0 -0
  203. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  204. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  205. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/secrets.js +0 -0
  206. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  207. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  208. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/README.md +0 -0
  209. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  210. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  211. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  212. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/evil.js +0 -0
  213. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/inject.js +0 -0
  214. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  215. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  216. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/README.md +0 -0
  217. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  218. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  219. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  220. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  221. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codexignore +0 -0
  222. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/LICENSE +0 -0
  223. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/README.md +0 -0
  224. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  225. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  226. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  227. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  228. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  229. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  230. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  231. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  232. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  233. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  234. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  235. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  236. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  237. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  238. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  239. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  240. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  241. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  242. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  243. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  244. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/mcp-canary-server.py +0 -0
  245. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  246. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  247. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/mit-license/LICENSE +0 -0
  248. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  250. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  251. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  252. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  253. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  254. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  255. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  256. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  257. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  258. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  259. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  260. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  261. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  262. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  263. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  264. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  265. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  266. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/LICENSE +0 -0
  267. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/README.md +0 -0
  268. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  269. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  270. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  271. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  272. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  273. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  274. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  275. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  276. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test-trust-scoring.py +0 -0
  277. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test-trust-specs.py +0 -0
  278. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_action_runner.py +0 -0
  279. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_best_practices.py +0 -0
  280. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_cisco_install_surfaces.py +0 -0
  281. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_cli.py +0 -0
  282. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_code_quality.py +0 -0
  283. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_config.py +0 -0
  284. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_coverage_remaining.py +0 -0
  285. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_ecosystems.py +0 -0
  286. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_edge_cases.py +0 -0
  287. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_final_coverage.py +0 -0
  288. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_approvals.py +0 -0
  289. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_bootstrap.py +0 -0
  290. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_capabilities.py +0 -0
  291. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_claude_adapter.py +0 -0
  292. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_cli.py +0 -0
  293. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_e2e.py +0 -0
  294. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_install.py +0 -0
  295. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_proxy.py +0 -0
  296. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_config_paths.py +0 -0
  297. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_connect_flow.py +0 -0
  298. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_consumer_mode.py +0 -0
  299. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_copilot_adapter.py +0 -0
  300. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_copilot_proxy.py +0 -0
  301. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_daemon_manager.py +0 -0
  302. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_event_schema_v1.py +0 -0
  303. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_events.py +0 -0
  304. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_launch_env.py +0 -0
  305. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_opencode_proxy.py +0 -0
  306. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_product_flow.py +0 -0
  307. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_protect.py +0 -0
  308. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_render.py +0 -0
  309. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_risk.py +0 -0
  310. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_store_migrations.py +0 -0
  311. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_surface_server.py +0 -0
  312. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_verdicts.py +0 -0
  313. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_hermes_adapter.py +0 -0
  314. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_integration.py +0 -0
  315. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_lint_fixes.py +0 -0
  316. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_live_cisco_smoke.py +0 -0
  317. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_manifest.py +0 -0
  318. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_marketplace.py +0 -0
  319. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_operational_security.py +0 -0
  320. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_policy.py +0 -0
  321. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_quality_artifact.py +0 -0
  322. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_rule_registry.py +0 -0
  323. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_scanner.py +0 -0
  324. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_schema_contracts.py +0 -0
  325. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_security.py +0 -0
  326. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_security_ops.py +0 -0
  327. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_skill_security.py +0 -0
  328. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_submission.py +0 -0
  329. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_trust_scoring.py +0 -0
  330. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_trust_specs.py +0 -0
  331. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_verification.py +0 -0
  332. {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_versioning.py +0 -0
  333. {plugin_scanner-2.0.82 → 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.82
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.82"
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.82"
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:
@@ -4118,6 +4145,17 @@ _PROMPT_CONTENT_SCAN_SKIP_BASENAMES = frozenset(
4118
4145
  ".git-credentials",
4119
4146
  }
4120
4147
  )
4148
+ _PROMPT_CONTENT_SCAN_SECRET_BASENAME_MARKERS = frozenset(
4149
+ {
4150
+ "auth",
4151
+ "credential",
4152
+ "env",
4153
+ "key",
4154
+ "pass",
4155
+ "secret",
4156
+ "token",
4157
+ }
4158
+ )
4121
4159
 
4122
4160
 
4123
4161
  def _codex_prompt_credential_file_artifact(
@@ -4135,6 +4173,8 @@ def _codex_prompt_credential_file_artifact(
4135
4173
  continue
4136
4174
  if not path.name.startswith("."):
4137
4175
  continue
4176
+ if not _prompt_path_looks_secret_bearing(path):
4177
+ continue
4138
4178
  if not path.is_file():
4139
4179
  continue
4140
4180
  try:
@@ -4181,6 +4221,11 @@ def _codex_prompt_credential_file_artifact(
4181
4221
  return None
4182
4222
 
4183
4223
 
4224
+ def _prompt_path_looks_secret_bearing(path: Path) -> bool:
4225
+ lowered_name = path.name.lower()
4226
+ return any(marker in lowered_name for marker in _PROMPT_CONTENT_SCAN_SECRET_BASENAME_MARKERS)
4227
+
4228
+
4184
4229
  def _with_codex_prompt_display_metadata(artifact: GuardArtifact, *, prompt_text: str) -> GuardArtifact:
4185
4230
  matched_text = artifact.metadata.get("prompt_matched_text")
4186
4231
  display = _codex_prompt_display_text(
@@ -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.82"
3
+ __version__ = "2.0.84"
@@ -413,10 +413,10 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
413
413
  home_dir = tmp_path / "home"
414
414
  workspace_dir = tmp_path / "workspace"
415
415
  _build_guard_fixture(home_dir, workspace_dir)
416
- _write_text(workspace_dir / ".nvmrc", "fake_credential=canary\n")
416
+ _write_text(workspace_dir / ".authrc", "fake_credential=canary\n")
417
417
  event = {
418
418
  "event": "UserPromptSubmit",
419
- "prompt": "read .nvmrc",
419
+ "prompt": "read .authrc",
420
420
  "source_scope": "project",
421
421
  }
422
422
  monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
@@ -440,8 +440,8 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
440
440
 
441
441
  assert rc == 1
442
442
  assert output["artifact_type"] == "prompt_request"
443
- assert "read .nvmrc" in output["launch_summary"]
444
- assert approval_requests[0]["launch_target"] == "Codex prompt for `.nvmrc`: read .nvmrc"
443
+ assert "read .authrc" in output["launch_summary"]
444
+ assert approval_requests[0]["launch_target"] == "Codex prompt for `.authrc`: read .authrc"
445
445
 
446
446
  def test_codex_prompt_display_sanitizes_common_home_paths(self) -> None:
447
447
  display = guard_commands_module._codex_prompt_display_text(
@@ -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,
@@ -10096,10 +10227,10 @@ def test_guard_hook_codex_user_prompt_submit_blocks_credential_looking_dotfile(
10096
10227
  home_dir = tmp_path / "home"
10097
10228
  workspace_dir = tmp_path / "workspace"
10098
10229
  _build_guard_fixture(home_dir, workspace_dir)
10099
- _write_text(workspace_dir / ".nvmrc", "fake_credential\n")
10230
+ _write_text(workspace_dir / ".authrc", "fake_credential\n")
10100
10231
  event = {
10101
10232
  "hook_event_name": "UserPromptSubmit",
10102
- "prompt": "Use bash to print the full contents of ./.nvmrc exactly.",
10233
+ "prompt": "Use bash to print the full contents of ./.authrc exactly.",
10103
10234
  "source_scope": "project",
10104
10235
  }
10105
10236
  monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
@@ -10121,7 +10252,7 @@ def test_guard_hook_codex_user_prompt_submit_blocks_credential_looking_dotfile(
10121
10252
  assert "http://127.0.0.1:4455/approvals/" in payload["reason"]
10122
10253
 
10123
10254
 
10124
- def test_guard_hook_codex_user_prompt_submit_blocks_bare_credential_dotfile(
10255
+ def test_guard_hook_codex_user_prompt_submit_allows_generic_dotfile_with_canary_text(
10125
10256
  tmp_path,
10126
10257
  capsys,
10127
10258
  monkeypatch,
@@ -10135,6 +10266,67 @@ def test_guard_hook_codex_user_prompt_submit_blocks_bare_credential_dotfile(
10135
10266
  "prompt": "read .nvmrc",
10136
10267
  "source_scope": "project",
10137
10268
  }
10269
+
10270
+ rc, output = _run_guard_hook(
10271
+ home_dir=home_dir,
10272
+ workspace_dir=workspace_dir,
10273
+ harness="codex",
10274
+ event=event,
10275
+ capsys=capsys,
10276
+ monkeypatch=monkeypatch,
10277
+ )
10278
+ payload = json.loads(output)
10279
+
10280
+ assert rc == 0
10281
+ assert payload == {"hookSpecificOutput": {"hookEventName": "UserPromptSubmit"}}
10282
+
10283
+
10284
+ def test_guard_hook_codex_user_prompt_submit_blocks_bare_credential_dotfile(
10285
+ tmp_path,
10286
+ capsys,
10287
+ monkeypatch,
10288
+ ):
10289
+ home_dir = tmp_path / "home"
10290
+ workspace_dir = tmp_path / "workspace"
10291
+ _build_guard_fixture(home_dir, workspace_dir)
10292
+ _write_text(workspace_dir / ".authrc", "fake_credential\n")
10293
+ event = {
10294
+ "hook_event_name": "UserPromptSubmit",
10295
+ "prompt": "read .authrc",
10296
+ "source_scope": "project",
10297
+ }
10298
+ monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
10299
+
10300
+ rc, output = _run_guard_hook(
10301
+ home_dir=home_dir,
10302
+ workspace_dir=workspace_dir,
10303
+ harness="codex",
10304
+ event=event,
10305
+ capsys=capsys,
10306
+ monkeypatch=monkeypatch,
10307
+ )
10308
+ payload = json.loads(output)
10309
+
10310
+ assert rc == 0
10311
+ assert payload["decision"] == "block"
10312
+ assert "HOL Guard" in payload["reason"]
10313
+ assert "credential-looking local file" in payload["reason"]
10314
+
10315
+
10316
+ def test_guard_hook_codex_user_prompt_submit_blocks_envrc_credential_dotfile(
10317
+ tmp_path,
10318
+ capsys,
10319
+ monkeypatch,
10320
+ ):
10321
+ home_dir = tmp_path / "home"
10322
+ workspace_dir = tmp_path / "workspace"
10323
+ _build_guard_fixture(home_dir, workspace_dir)
10324
+ _write_text(workspace_dir / ".envrc", "token = fixture-only\n")
10325
+ event = {
10326
+ "hook_event_name": "UserPromptSubmit",
10327
+ "prompt": "read .envrc",
10328
+ "source_scope": "project",
10329
+ }
10138
10330
  monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
10139
10331
 
10140
10332
  rc, output = _run_guard_hook(
@@ -10161,11 +10353,11 @@ def test_guard_hook_codex_prompt_dotfile_scan_uses_bounded_file_read(
10161
10353
  home_dir = tmp_path / "home"
10162
10354
  workspace_dir = tmp_path / "workspace"
10163
10355
  _build_guard_fixture(home_dir, workspace_dir)
10164
- _write_text(workspace_dir / ".nvmrc", "token = fixture-only\n")
10356
+ _write_text(workspace_dir / ".authrc", "token = fixture-only\n")
10165
10357
  monkeypatch.setattr(Path, "read_bytes", lambda _path: (_ for _ in ()).throw(AssertionError("unbounded read")))
10166
10358
  event = {
10167
10359
  "hook_event_name": "UserPromptSubmit",
10168
- "prompt": "read .nvmrc",
10360
+ "prompt": "read .authrc",
10169
10361
  "source_scope": "project",
10170
10362
  }
10171
10363
 
@@ -10184,7 +10376,7 @@ def test_guard_hook_codex_prompt_dotfile_scan_uses_bounded_file_read(
10184
10376
  assert "credential-looking local file" in payload["reason"]
10185
10377
 
10186
10378
 
10187
- @pytest.mark.parametrize("prompt", ["read .nvmrc.", "print ./.nvmrc, please"])
10379
+ @pytest.mark.parametrize("prompt", ["read .authrc.", "print ./.authrc, please"])
10188
10380
  def test_guard_hook_codex_prompt_dotfile_scan_ignores_trailing_punctuation(
10189
10381
  prompt,
10190
10382
  tmp_path,
@@ -10194,7 +10386,7 @@ def test_guard_hook_codex_prompt_dotfile_scan_ignores_trailing_punctuation(
10194
10386
  home_dir = tmp_path / "home"
10195
10387
  workspace_dir = tmp_path / "workspace"
10196
10388
  _build_guard_fixture(home_dir, workspace_dir)
10197
- _write_text(workspace_dir / ".nvmrc", "token = fixture-only\n")
10389
+ _write_text(workspace_dir / ".authrc", "token = fixture-only\n")
10198
10390
  event = {
10199
10391
  "hook_event_name": "UserPromptSubmit",
10200
10392
  "prompt": prompt,