plugin-scanner 2.0.107__tar.gz → 2.0.108__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 (350) hide show
  1. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/commands.py +47 -8
  5. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +124 -2
  6. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/version.py +1 -1
  7. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_risk.py +56 -1
  8. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime.py +169 -3
  9. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime_detectors.py +3 -0
  10. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.clusterfuzzlite/Dockerfile +0 -0
  11. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.clusterfuzzlite/build.sh +0 -0
  12. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.clusterfuzzlite/project.yaml +0 -0
  13. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  14. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.dockerignore +0 -0
  15. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/CODEOWNERS +0 -0
  16. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  17. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  19. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/dependabot.yml +0 -0
  20. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/ci.yml +0 -0
  21. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/codeql.yml +0 -0
  22. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/dependabot-uv-lock.yml +0 -0
  23. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/fuzz.yml +0 -0
  24. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/harness-smoke.yml +0 -0
  25. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/publish.yml +0 -0
  26. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.github/workflows/scorecard.yml +0 -0
  27. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.gitignore +0 -0
  28. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/.pre-commit-hooks.yaml +0 -0
  29. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/CONTRIBUTING.md +0 -0
  30. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/Dockerfile +0 -0
  31. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/LICENSE +0 -0
  32. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/README.md +0 -0
  33. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/SECURITY.md +0 -0
  34. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/index.html +0 -0
  35. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/package.json +0 -0
  36. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/pnpm-lock.yaml +0 -0
  37. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/apple-touch-icon.png +0 -0
  38. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  39. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/brand/Logo_Whole.png +0 -0
  40. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/favicon-16x16.png +0 -0
  41. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/favicon-32x32.png +0 -0
  42. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/public/favicon.ico +0 -0
  43. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/app.tsx +0 -0
  44. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/approval-center-layout.tsx +0 -0
  45. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/approval-center-primitives.tsx +0 -0
  46. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/approval-center-utils.ts +0 -0
  47. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/fleet-workspace.tsx +0 -0
  48. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/guard-api.test.ts +0 -0
  49. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/guard-api.ts +0 -0
  50. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/guard-demo.ts +0 -0
  51. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/guard-types.ts +0 -0
  52. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/main.tsx +0 -0
  53. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/receipts-workspace.tsx +0 -0
  54. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/runtime-overview.tsx +0 -0
  55. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/settings-workspace.tsx +0 -0
  56. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/styles.css +0 -0
  57. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/src/vite-env.d.ts +0 -0
  58. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/tsconfig.json +0 -0
  59. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/dashboard/vite.config.ts +0 -0
  60. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docker-requirements.txt +0 -0
  61. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/approval-audit.md +0 -0
  62. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/architecture.md +0 -0
  63. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/get-started.md +0 -0
  64. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/harness-support.md +0 -0
  65. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/local-vs-cloud.md +0 -0
  66. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/guard/testing-matrix.md +0 -0
  67. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/trust/mcp-trust-draft.md +0 -0
  68. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/trust/plugin-trust-draft.md +0 -0
  69. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/docs/trust/skill-trust-local.md +0 -0
  70. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/fuzzers/manifest_fuzzer.py +0 -0
  71. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/requirements.txt +0 -0
  72. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/schemas/plugin-quality.v1.json +0 -0
  73. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/schemas/scan-result.v1.json +0 -0
  74. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/schemas/verify-result.v1.json +0 -0
  75. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/__init__.py +0 -0
  76. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/action_runner.py +0 -0
  77. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  78. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  79. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  80. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/claude.py +0 -0
  81. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  82. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  83. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  84. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  85. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  86. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  87. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  88. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  89. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  90. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/security.py +0 -0
  91. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  92. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/cli.py +0 -0
  93. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/cli_ui.py +0 -0
  94. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/config.py +0 -0
  95. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  96. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  97. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  98. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  99. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  100. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  101. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  102. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  103. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  104. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/github_reporting.py +0 -0
  105. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  106. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  107. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  108. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  109. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  110. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
  111. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  112. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  113. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  114. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  115. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  116. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  117. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
  118. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  119. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  120. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  121. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  122. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  123. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  124. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  125. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  126. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  127. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  128. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  129. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  130. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  131. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  132. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  133. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  134. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  135. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  136. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/config.py +0 -0
  137. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  138. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  139. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  140. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  141. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  142. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  143. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  144. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  145. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  146. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  147. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  148. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  149. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  150. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  151. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  152. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  153. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/incident.py +0 -0
  154. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  155. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  156. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/models.py +0 -0
  157. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  158. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  159. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/protect.py +0 -0
  160. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  161. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  162. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  163. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  164. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  165. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  166. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  167. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/risk.py +0 -0
  168. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  169. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  170. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  171. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
  172. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  173. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  174. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  175. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  176. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  177. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  178. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  179. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  180. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/shims.py +0 -0
  181. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/store.py +0 -0
  182. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  183. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  184. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/guard/types.py +0 -0
  185. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  186. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  187. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  188. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  189. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  190. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/models.py +0 -0
  191. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/path_support.py +0 -0
  192. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/policy.py +0 -0
  193. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  194. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/repo_detect.py +0 -0
  195. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/reporting.py +0 -0
  196. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  197. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/rules/registry.py +0 -0
  198. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/rules/specs.py +0 -0
  199. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/scanner.py +0 -0
  200. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/submission.py +0 -0
  201. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/suppressions.py +0 -0
  202. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  203. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  204. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  205. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_models.py +0 -0
  206. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  207. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  208. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  209. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/trust_specs.py +0 -0
  210. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/src/codex_plugin_scanner/verification.py +0 -0
  211. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/__init__.py +0 -0
  212. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/conftest.py +0 -0
  213. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/__init__.py +0 -0
  214. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  215. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  216. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/bad-plugin/secrets.js +0 -0
  217. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  218. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  219. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/README.md +0 -0
  220. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  221. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  222. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  223. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/code-quality-bad/evil.js +0 -0
  224. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/code-quality-bad/inject.js +0 -0
  225. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  226. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  227. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/README.md +0 -0
  228. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  229. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  230. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  231. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  232. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/.codexignore +0 -0
  233. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/LICENSE +0 -0
  234. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/README.md +0 -0
  235. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  236. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  237. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  238. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  239. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  240. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  241. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  242. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  243. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  244. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  245. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  246. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  247. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  248. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  250. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  251. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  252. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  253. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  254. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  255. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/mcp-canary-server.py +0 -0
  256. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  257. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  258. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/mit-license/LICENSE +0 -0
  259. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  260. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  261. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  262. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  263. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  264. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  265. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  266. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  267. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  268. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  269. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  270. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  271. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  272. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  273. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  274. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  275. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  276. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  277. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/LICENSE +0 -0
  278. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/README.md +0 -0
  279. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  280. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  281. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  282. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  283. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  284. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  285. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  286. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  287. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test-trust-scoring.py +0 -0
  288. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test-trust-specs.py +0 -0
  289. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_action_runner.py +0 -0
  290. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_best_practices.py +0 -0
  291. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_cisco_install_surfaces.py +0 -0
  292. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_cli.py +0 -0
  293. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_code_quality.py +0 -0
  294. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_config.py +0 -0
  295. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_coverage_remaining.py +0 -0
  296. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_ecosystems.py +0 -0
  297. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_edge_cases.py +0 -0
  298. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_final_coverage.py +0 -0
  299. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_access_graph.py +0 -0
  300. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_approvals.py +0 -0
  301. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_bootstrap.py +0 -0
  302. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_capabilities.py +0 -0
  303. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_claude_adapter.py +0 -0
  304. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_cli.py +0 -0
  305. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_codex_e2e.py +0 -0
  306. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_codex_install.py +0 -0
  307. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_codex_proxy.py +0 -0
  308. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_config_paths.py +0 -0
  309. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_connect_flow.py +0 -0
  310. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_consumer_mode.py +0 -0
  311. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_copilot_adapter.py +0 -0
  312. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_copilot_proxy.py +0 -0
  313. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_daemon_manager.py +0 -0
  314. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_event_schema_v1.py +0 -0
  315. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_events.py +0 -0
  316. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_launch_env.py +0 -0
  317. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_opencode_proxy.py +0 -0
  318. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_product_flow.py +0 -0
  319. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_protect.py +0 -0
  320. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_render.py +0 -0
  321. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime_action_harnesses.py +0 -0
  322. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime_actions.py +0 -0
  323. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime_decisions.py +0 -0
  324. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_runtime_signals.py +0 -0
  325. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_store_migrations.py +0 -0
  326. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_surface_server.py +0 -0
  327. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_guard_verdicts.py +0 -0
  328. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_hermes_adapter.py +0 -0
  329. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_integration.py +0 -0
  330. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_lint_fixes.py +0 -0
  331. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_live_cisco_smoke.py +0 -0
  332. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_manifest.py +0 -0
  333. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_marketplace.py +0 -0
  334. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_mcp_security.py +0 -0
  335. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_openclaw_adapter.py +0 -0
  336. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_operational_security.py +0 -0
  337. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_policy.py +0 -0
  338. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_quality_artifact.py +0 -0
  339. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_rule_registry.py +0 -0
  340. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_scanner.py +0 -0
  341. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_schema_contracts.py +0 -0
  342. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_security.py +0 -0
  343. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_security_ops.py +0 -0
  344. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_skill_security.py +0 -0
  345. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_submission.py +0 -0
  346. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_trust_scoring.py +0 -0
  347. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_trust_specs.py +0 -0
  348. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_verification.py +0 -0
  349. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/tests/test_versioning.py +0 -0
  350. {plugin_scanner-2.0.107 → plugin_scanner-2.0.108}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.107
3
+ Version: 2.0.108
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.107"
7
+ version = "2.0.108"
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.107"
7
+ version = "2.0.108"
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"
@@ -97,6 +97,7 @@ from ..runtime.secret_file_requests import (
97
97
  extract_sensitive_tool_action_request,
98
98
  is_explicitly_benign_tool_action_request,
99
99
  )
100
+ from ..runtime.secret_sensitivity import SecretContentMatch, classify_secret_content
100
101
  from ..runtime.surface_server import GuardSurfaceRuntime
101
102
  from ..store import GuardStore
102
103
  from .approval_commands import add_approval_parser, run_approval_command
@@ -3962,10 +3963,6 @@ def _hook_runtime_artifact(
3962
3963
  )
3963
3964
 
3964
3965
 
3965
- _CODEX_SECRET_OUTPUT_PATTERN = re.compile(
3966
- r"(?i)(?:fake[_-]?credential|fake[_-]?secret|"
3967
- r"(?:api[_-]?key|auth[_-]?token|credential|npm[_-]?token|private[_-]?key|secret|token|password)\s*[:=])"
3968
- )
3969
3966
  _CODEX_PROMPT_SECRET_KEY_MARKERS = ("TOKEN", "SECRET", "PASSWORD", "PASS", "API_KEY", "API-KEY", "AUTH", "CREDENTIAL")
3970
3967
  _CODEX_TOOL_RESPONSE_MAX_DEPTH = 5
3971
3968
  _CODEX_TOOL_RESPONSE_TEXT_LIMIT = 20000
@@ -3980,13 +3977,19 @@ def _codex_post_tool_output_artifact(
3980
3977
  cwd: Path | None,
3981
3978
  ) -> GuardArtifact | None:
3982
3979
  response_text = _collect_codex_tool_response_text(payload.get("tool_response"))
3983
- if not response_text or _CODEX_SECRET_OUTPUT_PATTERN.search(response_text) is None:
3980
+ content_matches = classify_secret_content(response_text)
3981
+ if not content_matches:
3984
3982
  return None
3985
3983
  tool_name = _coalesce_string(payload.get("tool_name"), "Bash")
3986
3984
  command_text = _codex_post_tool_command_text(payload)
3987
3985
  if not command_text:
3988
3986
  command_text = tool_name
3989
- if _codex_command_is_read_only_source_inspection(command_text, cwd=cwd):
3987
+ if _codex_source_inspection_can_skip_secret_output(
3988
+ command_text=command_text,
3989
+ response_text=response_text,
3990
+ content_matches=content_matches,
3991
+ cwd=cwd,
3992
+ ):
3990
3993
  return None
3991
3994
  fingerprint = hashlib.sha256(
3992
3995
  json.dumps(
@@ -4109,6 +4112,10 @@ _CODEX_SOURCE_SEARCH_EXTENSIONS = frozenset(
4109
4112
  ".yml",
4110
4113
  }
4111
4114
  )
4115
+ _CODEX_BENIGN_SOURCE_DOTFILES = frozenset({".nvmrc"})
4116
+ _CODEX_BENIGN_SECRET_FIXTURE_ASSIGNMENT_PATTERN = re.compile(
4117
+ r"(?i)\s*fake[_-]?(?:credential|secret|token)\s*[:=]\s*(?:\"[^\r\n\"]+\"|'[^\r\n']+'|[^\s\"',}]+)\s*"
4118
+ )
4112
4119
  _CODEX_SENSITIVE_SEARCH_BASENAMES = frozenset(
4113
4120
  {
4114
4121
  ".aws",
@@ -4127,6 +4134,35 @@ _CODEX_SENSITIVE_SEARCH_BASENAMES = frozenset(
4127
4134
  _CODEX_SED_PRINT_SCRIPT_PATTERN = re.compile(r"^\s*(?:\$|\d+)?(?:\s*,\s*(?:\$|\d+))?p\s*$")
4128
4135
 
4129
4136
 
4137
+ def _codex_source_inspection_can_skip_secret_output(
4138
+ *,
4139
+ command_text: str,
4140
+ response_text: str,
4141
+ content_matches: tuple[SecretContentMatch, ...],
4142
+ cwd: Path | None,
4143
+ ) -> bool:
4144
+ if not _codex_command_is_read_only_source_inspection(command_text, cwd=cwd):
4145
+ return False
4146
+ if any(match.sensitivity != "medium" for match in content_matches):
4147
+ return False
4148
+ if _codex_command_references_benign_source_dotfile(command_text):
4149
+ return _codex_output_is_only_benign_secret_fixture(response_text)
4150
+ return True
4151
+
4152
+
4153
+ def _codex_output_is_only_benign_secret_fixture(response_text: str) -> bool:
4154
+ lines = [line for line in response_text.splitlines() if line.strip()]
4155
+ return bool(lines) and all(_CODEX_BENIGN_SECRET_FIXTURE_ASSIGNMENT_PATTERN.fullmatch(line) for line in lines)
4156
+
4157
+
4158
+ def _codex_command_references_benign_source_dotfile(command_text: str) -> bool:
4159
+ try:
4160
+ parts = shlex.split(command_text)
4161
+ except ValueError:
4162
+ return False
4163
+ return any(Path(part).name.lower() in _CODEX_BENIGN_SOURCE_DOTFILES for part in parts)
4164
+
4165
+
4130
4166
  def _codex_command_is_read_only_source_inspection(command_text: str, *, cwd: Path | None) -> bool:
4131
4167
  command = command_text.strip()
4132
4168
  if not command:
@@ -4644,13 +4680,16 @@ def _codex_search_target_is_source_like(target: str, *, cwd: Path | None) -> boo
4644
4680
  lowered_parts = [part.lower() for part in parts]
4645
4681
  if any(part in _CODEX_SENSITIVE_SEARCH_BASENAMES for part in lowered_parts):
4646
4682
  return False
4647
- if any(part.startswith(".") for part in parts):
4683
+ hidden_parts = [part for part in lowered_parts if part.startswith(".")]
4684
+ if hidden_parts and not all(part in _CODEX_BENIGN_SOURCE_DOTFILES for part in hidden_parts):
4648
4685
  return False
4649
4686
  normalized = "/".join(parts)
4650
4687
  if normalized in {prefix.rstrip("/") for prefix in _CODEX_SOURCE_SEARCH_PREFIXES}:
4651
4688
  return True
4652
4689
  if any(normalized.startswith(prefix) for prefix in _CODEX_SOURCE_SEARCH_PREFIXES):
4653
4690
  return True
4691
+ if Path(stripped).name.lower() in _CODEX_BENIGN_SOURCE_DOTFILES:
4692
+ return True
4654
4693
  return Path(stripped).suffix.lower() in _CODEX_SOURCE_SEARCH_EXTENSIONS
4655
4694
 
4656
4695
 
@@ -4745,7 +4784,7 @@ def _codex_prompt_credential_file_artifact(
4745
4784
  content = handle.read(_PROMPT_CONTENT_SCAN_MAX_BYTES).decode("utf-8", errors="ignore")
4746
4785
  except OSError:
4747
4786
  continue
4748
- if _CODEX_SECRET_OUTPUT_PATTERN.search(content) is None:
4787
+ if not classify_secret_content(content):
4749
4788
  continue
4750
4789
  normalized_path = str(path)
4751
4790
  fingerprint = hashlib.sha256(
@@ -3,11 +3,13 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
+ import re
6
7
  from dataclasses import dataclass
7
8
  from pathlib import Path
8
9
  from typing import Literal
9
10
 
10
11
  SecretSensitivity = Literal["high", "critical"]
12
+ SecretContentSensitivity = Literal["medium", "high", "critical"]
11
13
 
12
14
  _AWS_CREDENTIALS_MARKER = "/".join((".aws", "credentials"))
13
15
  _DOCKER_CONFIG_MARKER = "/".join((".docker", "config.json"))
@@ -42,8 +44,12 @@ _SENSITIVE_BASENAME_LABELS = {
42
44
  ".netrc": "netrc credentials",
43
45
  ".git-credentials": "Git credential store",
44
46
  ".terraform.tfvars": "Terraform variable secrets",
47
+ "private-key.pem": "wallet/private-key file",
48
+ "private.key": "wallet/private-key file",
49
+ "wallet.key": "wallet/private-key file",
45
50
  "terraform.tfvars": "Terraform variable secrets",
46
51
  }
52
+ _SENSITIVE_BASENAME_KEYWORDS = ("private-key", "private_key", "wallet-key", "wallet_key")
47
53
  _REDACTED_BASENAME_LABELS = {
48
54
  "id_rsa": "SSH private key",
49
55
  "id_ed25519": "SSH private key",
@@ -80,7 +86,86 @@ _SENSITIVE_PATH_REASONS = {
80
86
  "Terraform variable secrets": (
81
87
  "Guard treats Terraform variable files as sensitive because they often contain secrets."
82
88
  ),
89
+ "wallet/private-key file": (
90
+ "Guard treats wallet and private-key files as sensitive because they can authorize account control."
91
+ ),
83
92
  }
93
+ _SECRET_ASSIGNMENT_VALUE_PATTERN = r"(?:\"[^\"\r\n]+\"|'[^'\r\n]+'|[^ \t\r\n\"',}]+)"
94
+ _HEDERA_PRIVATE_KEY_VALUE_PATTERN = r"(?:\"(?:0x)?[0-9a-f]{64,96}\"|'(?:0x)?[0-9a-f]{64,96}'|(?:0x)?[0-9a-f]{64,96}\b)"
95
+ _SECRET_CONTENT_PATTERNS: tuple[tuple[str, str, SecretContentSensitivity, re.Pattern[str], str], ...] = (
96
+ (
97
+ "npm-auth-token",
98
+ "npm auth token",
99
+ "high",
100
+ re.compile(
101
+ r"(?im)[\"']?\b[A-Za-z0-9_-]*(?:_authToken|npm[_-]?token)\b[\"']?\s*[:=]\s*"
102
+ + _SECRET_ASSIGNMENT_VALUE_PATTERN
103
+ ),
104
+ "Guard found an npm registry token pattern.",
105
+ ),
106
+ (
107
+ "github-token",
108
+ "GitHub token",
109
+ "high",
110
+ re.compile(r"\b(?:gh[pousr]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}_[A-Za-z0-9_]{20,})\b"),
111
+ "Guard found a GitHub token pattern.",
112
+ ),
113
+ (
114
+ "aws-access-key",
115
+ "AWS access key",
116
+ "high",
117
+ re.compile(r"\b(?:AKIA|ASIA)[0-9A-Z]{16}\b"),
118
+ "Guard found an AWS access key pattern.",
119
+ ),
120
+ (
121
+ "openai-api-key",
122
+ "OpenAI API key",
123
+ "high",
124
+ re.compile(r"\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b"),
125
+ "Guard found an OpenAI API key pattern.",
126
+ ),
127
+ (
128
+ "anthropic-api-key",
129
+ "Anthropic API key",
130
+ "high",
131
+ re.compile(r"\bsk-ant-api03-[A-Za-z0-9_-]{20,}\b"),
132
+ "Guard found an Anthropic API key pattern.",
133
+ ),
134
+ (
135
+ "hedera-private-key",
136
+ "Hedera private key",
137
+ "critical",
138
+ re.compile(
139
+ r"(?im)[\"']?\b[A-Za-z0-9_-]*(?:hedera[_-]?)?(?:operator[_-]?)?private[_-]?key\b[\"']?\s*[:=]\s*"
140
+ + _HEDERA_PRIVATE_KEY_VALUE_PATTERN
141
+ ),
142
+ "Guard found a Hedera private-key-like value.",
143
+ ),
144
+ (
145
+ "pem-private-key",
146
+ "PEM private key",
147
+ "critical",
148
+ re.compile(r"-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----", re.MULTILINE),
149
+ "Guard found a PEM private key header.",
150
+ ),
151
+ (
152
+ "credential-marker",
153
+ "credential assignment",
154
+ "medium",
155
+ re.compile(r"(?i)(?:^|[^a-z0-9])fake[_-]?(?:credential|secret)\b"),
156
+ "Guard found credential-looking marker text.",
157
+ ),
158
+ (
159
+ "credential-assignment",
160
+ "credential assignment",
161
+ "medium",
162
+ re.compile(
163
+ r"(?im)[\"']?\b[A-Za-z0-9_-]*(?:api[_-]?key|auth[_-]?token|credential|credentials|npm[_-]?token|"
164
+ r"private[_-]?key|secret|token|password)\b[\"']?\s*[:=]\s*" + _SECRET_ASSIGNMENT_VALUE_PATTERN
165
+ ),
166
+ "Guard found credential-looking assignment text.",
167
+ ),
168
+ )
84
169
 
85
170
 
86
171
  @dataclass(frozen=True, slots=True)
@@ -100,6 +185,14 @@ class SecretPathMatch:
100
185
  return self.family
101
186
 
102
187
 
188
+ @dataclass(frozen=True, slots=True)
189
+ class SecretContentMatch:
190
+ classifier: str
191
+ family: str
192
+ sensitivity: SecretContentSensitivity
193
+ reason: str
194
+
195
+
103
196
  def classify_secret_path(
104
197
  path: str | None,
105
198
  *,
@@ -125,11 +218,20 @@ def classify_secret_path(
125
218
  sensitivity="critical",
126
219
  )
127
220
  if basename in _SENSITIVE_BASENAME_LABELS:
221
+ family = _SENSITIVE_BASENAME_LABELS[basename]
222
+ sensitivity: SecretSensitivity = "critical" if family == "wallet/private-key file" else "high"
223
+ return _match(
224
+ requested_path=requested_path,
225
+ normalized_path=normalized_path,
226
+ family=family,
227
+ sensitivity=sensitivity,
228
+ )
229
+ if any(keyword in basename for keyword in _SENSITIVE_BASENAME_KEYWORDS):
128
230
  return _match(
129
231
  requested_path=requested_path,
130
232
  normalized_path=normalized_path,
131
- family=_SENSITIVE_BASENAME_LABELS[basename],
132
- sensitivity="high",
233
+ family="wallet/private-key file",
234
+ sensitivity="critical",
133
235
  )
134
236
  if "..." in lowered_segments and basename in _REDACTED_BASENAME_LABELS:
135
237
  family = _REDACTED_BASENAME_LABELS[basename]
@@ -170,6 +272,26 @@ def classify_legacy_secret_path_families(text: str) -> set[str]:
170
272
  return {family for marker, family in LEGACY_SECRET_PATH_TEXT_MARKERS if marker in lowered}
171
273
 
172
274
 
275
+ def classify_secret_content(text: str | None) -> tuple[SecretContentMatch, ...]:
276
+ if not isinstance(text, str) or not text.strip():
277
+ return ()
278
+ matches: list[SecretContentMatch] = []
279
+ seen: set[str] = set()
280
+ for classifier, family, sensitivity, pattern, reason in _SECRET_CONTENT_PATTERNS:
281
+ if pattern.search(text) is None or classifier in seen:
282
+ continue
283
+ seen.add(classifier)
284
+ matches.append(
285
+ SecretContentMatch(
286
+ classifier=classifier,
287
+ family=family,
288
+ sensitivity=sensitivity,
289
+ reason=reason,
290
+ )
291
+ )
292
+ return tuple(matches)
293
+
294
+
173
295
  def redacted_secret_path_context(path: str) -> str | None:
174
296
  segments = tuple(segment for segment in path.replace("\\", "/").split("/") if segment)
175
297
  lowered_segments = tuple(segment.lower() for segment in segments)
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for tool version."""
2
2
 
3
- __version__ = "2.0.107"
3
+ __version__ = "2.0.108"
@@ -44,7 +44,12 @@ from codex_plugin_scanner.guard.runtime.secret_file_requests import (
44
44
  is_explicitly_benign_tool_action_request,
45
45
  is_file_read_tool_name,
46
46
  )
47
- from codex_plugin_scanner.guard.runtime.secret_sensitivity import SecretPathMatch, classify_secret_path
47
+ from codex_plugin_scanner.guard.runtime.secret_sensitivity import (
48
+ SecretContentMatch,
49
+ SecretPathMatch,
50
+ classify_secret_content,
51
+ classify_secret_path,
52
+ )
48
53
  from codex_plugin_scanner.guard.store import GuardStore
49
54
 
50
55
 
@@ -384,6 +389,56 @@ def test_secret_sensitivity_module_classifies_planned_secret_path_families(tmp_p
384
389
  assert match.reason
385
390
 
386
391
 
392
+ @pytest.mark.parametrize(
393
+ ("path", "family"),
394
+ [
395
+ ("wallet.key", "wallet/private-key file"),
396
+ ("private-key.pem", "wallet/private-key file"),
397
+ ("operator-private-key.txt", "wallet/private-key file"),
398
+ ],
399
+ )
400
+ def test_secret_sensitivity_module_classifies_wallet_private_key_filenames(tmp_path, path, family):
401
+ match = classify_secret_path(path, home_dir=tmp_path)
402
+
403
+ assert isinstance(match, SecretPathMatch)
404
+ assert match.family == family
405
+ assert match.sensitivity == "critical"
406
+
407
+
408
+ @pytest.mark.parametrize(
409
+ ("content", "family"),
410
+ [
411
+ ("//registry.npmjs.org/:_authToken=" + "n" * 36, "npm auth token"),
412
+ ('//registry.npmjs.org/:_authToken="' + "n" * 36 + '"', "npm auth token"),
413
+ ('MY_NPM_TOKEN="' + "n" * 36 + '"', "npm auth token"),
414
+ ("token=" + "ghp_" + "A" * 36, "GitHub token"),
415
+ ("token=" + "github_pat_" + "A" * 22 + "_" + "B" * 59, "GitHub token"),
416
+ ("aws_access_key_id=" + "AKIA" + "A" * 16, "AWS access key"),
417
+ ("OPENAI_API_KEY=" + "sk-" + "A" * 32, "OpenAI API key"),
418
+ ("ANTHROPIC_API_KEY=" + "sk-ant-api03-" + "A" * 60, "Anthropic API key"),
419
+ ("HEDERA_PRIVATE_KEY=" + "a" * 64, "Hedera private key"),
420
+ ('HEDERA_PRIVATE_KEY="' + "a" * 64 + '"', "Hedera private key"),
421
+ ("-----BEGIN " + "PRIVATE KEY-----\nredacted\n-----END " + "PRIVATE KEY-----", "PEM private key"),
422
+ ('TOKEN="' + "A" * 24 + '"', "credential assignment"),
423
+ ("auth_token='" + "B" * 24 + "'", "credential assignment"),
424
+ ('{"password": "' + "C" * 24 + '"}', "credential assignment"),
425
+ ("MY_TOKEN=fixture-token", "credential assignment"),
426
+ ('MY_NPM_TOKEN="fixture-token"', "credential assignment"),
427
+ ('{"OPENAI_API_KEY": "fixture-key"}', "credential assignment"),
428
+ ],
429
+ )
430
+ def test_secret_content_classifier_detects_planned_secret_content(content, family):
431
+ matches = classify_secret_content(content)
432
+
433
+ assert any(isinstance(match, SecretContentMatch) and match.family == family for match in matches)
434
+
435
+
436
+ def test_secret_content_classifier_does_not_upgrade_npm_token_prose():
437
+ matches = classify_secret_content("Docs say npm token: use an environment variable instead.")
438
+
439
+ assert not any(match.family == "npm auth token" for match in matches)
440
+
441
+
387
442
  def test_file_read_request_classifier_is_argument_aware(tmp_path):
388
443
  env_request = extract_sensitive_file_read_request("read_file", {"path": ".env.local"})
389
444
  claude_request = extract_sensitive_file_read_request("Read", {"file_path": "~/.ssh/config"}, home_dir=tmp_path)
@@ -879,6 +879,172 @@ clearer UX and an implementation plan with technical references.
879
879
  assert output["recorded"] is True
880
880
  assert "approval_requests" not in output
881
881
 
882
+ def test_codex_post_tool_use_allows_benign_nvmrc_fake_credential_fixture(
883
+ self,
884
+ monkeypatch,
885
+ tmp_path,
886
+ capsys,
887
+ ) -> None:
888
+ home_dir = tmp_path / "home"
889
+ workspace_dir = tmp_path / "workspace"
890
+ _build_guard_fixture(home_dir, workspace_dir)
891
+ _write_text(workspace_dir / ".nvmrc", "fake_credential=fixture-only\n")
892
+ event = {
893
+ "event": "PostToolUse",
894
+ "tool_name": "Bash",
895
+ "tool_input": {"command": "cat .nvmrc"},
896
+ "tool_response": {"stdout": "fake_credential=fixture-only\n"},
897
+ "source_scope": "project",
898
+ }
899
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
900
+
901
+ rc = main(
902
+ [
903
+ "guard",
904
+ "hook",
905
+ "--home",
906
+ str(home_dir),
907
+ "--workspace",
908
+ str(workspace_dir),
909
+ "--harness",
910
+ "codex",
911
+ "--json",
912
+ ]
913
+ )
914
+ output = json.loads(capsys.readouterr().out)
915
+
916
+ assert rc == 0
917
+ assert output["recorded"] is True
918
+ assert "approval_requests" not in output
919
+
920
+ @pytest.mark.parametrize(
921
+ "secret_output",
922
+ [
923
+ "NPM_TOKEN=" + "n" * 36 + "\n",
924
+ 'NPM_TOKEN="' + "n" * 36 + '"\n',
925
+ "DB_PASSWORD=fixture-pass\n",
926
+ "auth_token='fixture-token'\n",
927
+ ],
928
+ )
929
+ def test_codex_post_tool_use_blocks_nvmrc_high_confidence_secret(
930
+ self,
931
+ monkeypatch,
932
+ tmp_path,
933
+ capsys,
934
+ secret_output,
935
+ ) -> None:
936
+ home_dir = tmp_path / "home"
937
+ workspace_dir = tmp_path / "workspace"
938
+ _build_guard_fixture(home_dir, workspace_dir)
939
+ _write_text(workspace_dir / ".nvmrc", secret_output)
940
+ event = {
941
+ "event": "PostToolUse",
942
+ "tool_name": "Bash",
943
+ "tool_input": {"command": "cat .nvmrc"},
944
+ "tool_response": {"stdout": secret_output},
945
+ "source_scope": "project",
946
+ }
947
+ monkeypatch.setenv("CODEX_HOME", str(home_dir / ".codex"))
948
+ monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
949
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
950
+
951
+ rc = main(
952
+ [
953
+ "guard",
954
+ "hook",
955
+ "--home",
956
+ str(home_dir),
957
+ "--workspace",
958
+ str(workspace_dir),
959
+ "--harness",
960
+ "codex",
961
+ ]
962
+ )
963
+ output = json.loads(capsys.readouterr().out)
964
+
965
+ assert rc == 0
966
+ assert output["continue"] is False
967
+ assert "credential-looking output" in output["stopReason"]
968
+
969
+ def test_codex_post_tool_use_blocks_nvmrc_mixed_fake_and_secret_assignments(
970
+ self,
971
+ monkeypatch,
972
+ tmp_path,
973
+ capsys,
974
+ ) -> None:
975
+ home_dir = tmp_path / "home"
976
+ workspace_dir = tmp_path / "workspace"
977
+ _build_guard_fixture(home_dir, workspace_dir)
978
+ secret_output = "fake_credential=fixture-only\nDB_PASSWORD=fixture-pass\n"
979
+ _write_text(workspace_dir / ".nvmrc", secret_output)
980
+ event = {
981
+ "event": "PostToolUse",
982
+ "tool_name": "Bash",
983
+ "tool_input": {"command": "cat .nvmrc"},
984
+ "tool_response": {"stdout": secret_output},
985
+ "source_scope": "project",
986
+ }
987
+ monkeypatch.setenv("CODEX_HOME", str(home_dir / ".codex"))
988
+ monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
989
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
990
+
991
+ rc = main(
992
+ [
993
+ "guard",
994
+ "hook",
995
+ "--home",
996
+ str(home_dir),
997
+ "--workspace",
998
+ str(workspace_dir),
999
+ "--harness",
1000
+ "codex",
1001
+ ]
1002
+ )
1003
+ output = json.loads(capsys.readouterr().out)
1004
+
1005
+ assert rc == 0
1006
+ assert output["continue"] is False
1007
+ assert "credential-looking output" in output["stopReason"]
1008
+
1009
+ def test_codex_post_tool_use_allows_docs_fake_token_examples(
1010
+ self,
1011
+ monkeypatch,
1012
+ tmp_path,
1013
+ capsys,
1014
+ ) -> None:
1015
+ home_dir = tmp_path / "home"
1016
+ workspace_dir = tmp_path / "workspace"
1017
+ _build_guard_fixture(home_dir, workspace_dir)
1018
+ docs_file = workspace_dir / "docs" / "secret-examples.md"
1019
+ _write_text(docs_file, "Use fake_token=example-only in docs.\n")
1020
+ event = {
1021
+ "event": "PostToolUse",
1022
+ "tool_name": "Bash",
1023
+ "tool_input": {"command": "cat docs/secret-examples.md"},
1024
+ "tool_response": {"stdout": "Use fake_token=example-only in docs.\n"},
1025
+ "source_scope": "project",
1026
+ }
1027
+ monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
1028
+
1029
+ rc = main(
1030
+ [
1031
+ "guard",
1032
+ "hook",
1033
+ "--home",
1034
+ str(home_dir),
1035
+ "--workspace",
1036
+ str(workspace_dir),
1037
+ "--harness",
1038
+ "codex",
1039
+ "--json",
1040
+ ]
1041
+ )
1042
+ output = json.loads(capsys.readouterr().out)
1043
+
1044
+ assert rc == 0
1045
+ assert output["recorded"] is True
1046
+ assert "approval_requests" not in output
1047
+
882
1048
  def test_codex_post_tool_use_allows_short_option_value_payloads(
883
1049
  self,
884
1050
  monkeypatch,
@@ -10911,7 +11077,7 @@ def test_guard_hook_codex_post_tool_use_blocks_credential_looking_output(
10911
11077
  event = {
10912
11078
  "hook_event_name": "PostToolUse",
10913
11079
  "tool_name": "Bash",
10914
- "tool_input": {"command": "cat .nvmrc"},
11080
+ "tool_input": {"command": "cat .authrc"},
10915
11081
  "tool_response": {"stdout": "HOL_GUARD_FAKE_CREDENTIAL=fixture-only\n"},
10916
11082
  "source_scope": "project",
10917
11083
  }
@@ -10958,7 +11124,7 @@ def test_guard_hook_codex_post_tool_use_browser_approval_resumes_result(
10958
11124
  event = {
10959
11125
  "hook_event_name": "PostToolUse",
10960
11126
  "tool_name": "Bash",
10961
- "tool_input": {"command": "cat .nvmrc"},
11127
+ "tool_input": {"command": "cat .authrc"},
10962
11128
  "tool_response": {"stdout": "HOL_GUARD_FAKE_CREDENTIAL=fixture-only\n"},
10963
11129
  "source_scope": "project",
10964
11130
  }
@@ -11440,7 +11606,7 @@ def test_guard_hook_codex_runtime_risk_ignores_broad_allow_policy(
11440
11606
  event = {
11441
11607
  "hook_event_name": "PostToolUse",
11442
11608
  "tool_name": "Bash",
11443
- "tool_input": {"command": "sed -n '1,20p' .nvmrc"},
11609
+ "tool_input": {"command": "sed -n '1,20p' .authrc"},
11444
11610
  "tool_response": "fake_credential\n",
11445
11611
  "source_scope": "project",
11446
11612
  }
@@ -248,6 +248,9 @@ def test_register_default_detectors_includes_secret_path_detector():
248
248
  "~/.docker/" + "config.json",
249
249
  "~/.kube/config",
250
250
  ".terraform.tfvars",
251
+ "wallet.key",
252
+ "private-key.pem",
253
+ "operator-private-key.txt",
251
254
  ],
252
255
  )
253
256
  def test_default_secret_path_detector_flags_planned_direct_file_reads(tmp_path, path):