plugin-scanner 2.0.109__tar.gz → 2.0.110__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.109 → plugin_scanner-2.0.110}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/pyproject.toml +1 -1
  3. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/pyproject.toml.bak +1 -1
  4. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/commands.py +251 -9
  5. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/consumer/service.py +9 -1
  6. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +25 -2
  7. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/version.py +1 -1
  8. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_risk.py +20 -0
  9. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime.py +433 -0
  10. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.clusterfuzzlite/Dockerfile +0 -0
  11. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.clusterfuzzlite/build.sh +0 -0
  12. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.clusterfuzzlite/project.yaml +0 -0
  13. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  14. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.dockerignore +0 -0
  15. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/CODEOWNERS +0 -0
  16. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  17. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  19. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/dependabot.yml +0 -0
  20. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/ci.yml +0 -0
  21. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/codeql.yml +0 -0
  22. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/dependabot-uv-lock.yml +0 -0
  23. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/fuzz.yml +0 -0
  24. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/harness-smoke.yml +0 -0
  25. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/publish.yml +0 -0
  26. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.github/workflows/scorecard.yml +0 -0
  27. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.gitignore +0 -0
  28. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/.pre-commit-hooks.yaml +0 -0
  29. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/CONTRIBUTING.md +0 -0
  30. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/Dockerfile +0 -0
  31. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/LICENSE +0 -0
  32. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/README.md +0 -0
  33. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/SECURITY.md +0 -0
  34. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/index.html +0 -0
  35. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/package.json +0 -0
  36. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/pnpm-lock.yaml +0 -0
  37. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/apple-touch-icon.png +0 -0
  38. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  39. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/brand/Logo_Whole.png +0 -0
  40. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/favicon-16x16.png +0 -0
  41. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/favicon-32x32.png +0 -0
  42. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/public/favicon.ico +0 -0
  43. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/app.tsx +0 -0
  44. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/approval-center-layout.tsx +0 -0
  45. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/approval-center-primitives.tsx +0 -0
  46. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/approval-center-utils.ts +0 -0
  47. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/fleet-workspace.tsx +0 -0
  48. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/guard-api.test.ts +0 -0
  49. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/guard-api.ts +0 -0
  50. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/guard-demo.ts +0 -0
  51. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/guard-types.ts +0 -0
  52. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/main.tsx +0 -0
  53. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/receipts-workspace.tsx +0 -0
  54. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/runtime-overview.tsx +0 -0
  55. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/settings-workspace.tsx +0 -0
  56. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/styles.css +0 -0
  57. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/src/vite-env.d.ts +0 -0
  58. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/tsconfig.json +0 -0
  59. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/dashboard/vite.config.ts +0 -0
  60. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docker-requirements.txt +0 -0
  61. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/approval-audit.md +0 -0
  62. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/architecture.md +0 -0
  63. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/get-started.md +0 -0
  64. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/harness-support.md +0 -0
  65. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/local-vs-cloud.md +0 -0
  66. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/guard/testing-matrix.md +0 -0
  67. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/trust/mcp-trust-draft.md +0 -0
  68. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/trust/plugin-trust-draft.md +0 -0
  69. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/docs/trust/skill-trust-local.md +0 -0
  70. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/fuzzers/manifest_fuzzer.py +0 -0
  71. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/requirements.txt +0 -0
  72. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/schemas/plugin-quality.v1.json +0 -0
  73. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/schemas/scan-result.v1.json +0 -0
  74. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/schemas/verify-result.v1.json +0 -0
  75. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/__init__.py +0 -0
  76. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/action_runner.py +0 -0
  77. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  78. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  79. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  80. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/claude.py +0 -0
  81. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  82. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  83. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  84. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  85. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  86. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  87. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  88. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  89. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  90. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/security.py +0 -0
  91. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  92. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/cli.py +0 -0
  93. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/cli_ui.py +0 -0
  94. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/config.py +0 -0
  95. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  96. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  97. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  98. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  99. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  100. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  101. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  102. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  103. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  104. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/github_reporting.py +0 -0
  105. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  106. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  107. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  108. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  109. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  110. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
  111. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  112. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  113. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  114. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  115. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  116. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  117. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
  118. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  119. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  120. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  121. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  122. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  123. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  124. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  125. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  126. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  127. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  128. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  129. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  130. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  131. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  132. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  133. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  134. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  135. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  136. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/config.py +0 -0
  137. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  138. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  139. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  140. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  141. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  142. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  143. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
  144. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  145. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  146. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  147. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  148. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  149. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  150. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  151. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  152. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/incident.py +0 -0
  153. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  154. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  155. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/models.py +0 -0
  156. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  157. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  158. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/protect.py +0 -0
  159. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  160. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  161. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  162. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  163. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  164. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  165. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  166. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/risk.py +0 -0
  167. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  168. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  169. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  170. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
  171. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  172. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  173. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  174. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  175. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  176. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  177. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  178. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  179. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/shims.py +0 -0
  180. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store.py +0 -0
  181. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  182. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  183. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/guard/types.py +0 -0
  184. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  185. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  186. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  187. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  188. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  189. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/models.py +0 -0
  190. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/path_support.py +0 -0
  191. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/policy.py +0 -0
  192. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  193. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/repo_detect.py +0 -0
  194. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/reporting.py +0 -0
  195. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  196. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/registry.py +0 -0
  197. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/rules/specs.py +0 -0
  198. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/scanner.py +0 -0
  199. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/submission.py +0 -0
  200. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/suppressions.py +0 -0
  201. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  202. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  203. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  204. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_models.py +0 -0
  205. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  206. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  207. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  208. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/trust_specs.py +0 -0
  209. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/src/codex_plugin_scanner/verification.py +0 -0
  210. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/__init__.py +0 -0
  211. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/conftest.py +0 -0
  212. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/__init__.py +0 -0
  213. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  214. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  215. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/bad-plugin/secrets.js +0 -0
  216. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  217. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  218. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/README.md +0 -0
  219. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  220. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  221. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  222. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/code-quality-bad/evil.js +0 -0
  223. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/code-quality-bad/inject.js +0 -0
  224. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  225. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  226. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/README.md +0 -0
  227. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  228. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  229. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  230. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  231. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/.codexignore +0 -0
  232. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/LICENSE +0 -0
  233. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/README.md +0 -0
  234. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  235. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  236. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  237. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  238. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  239. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  240. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  241. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  242. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  243. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  244. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  245. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  246. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  247. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  248. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  250. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  251. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  252. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  253. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  254. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/mcp-canary-server.py +0 -0
  255. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  256. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  257. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/mit-license/LICENSE +0 -0
  258. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  259. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  260. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  261. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  262. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  263. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  264. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  265. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  266. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  267. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  268. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  269. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  270. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  271. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  272. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  273. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  274. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  275. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  276. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/LICENSE +0 -0
  277. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/README.md +0 -0
  278. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  279. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  280. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  281. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  282. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  283. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  284. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  285. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  286. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test-trust-scoring.py +0 -0
  287. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test-trust-specs.py +0 -0
  288. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_action_runner.py +0 -0
  289. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_best_practices.py +0 -0
  290. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_cisco_install_surfaces.py +0 -0
  291. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_cli.py +0 -0
  292. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_code_quality.py +0 -0
  293. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_config.py +0 -0
  294. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_coverage_remaining.py +0 -0
  295. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_ecosystems.py +0 -0
  296. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_edge_cases.py +0 -0
  297. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_final_coverage.py +0 -0
  298. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_access_graph.py +0 -0
  299. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_approvals.py +0 -0
  300. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_bootstrap.py +0 -0
  301. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_capabilities.py +0 -0
  302. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_claude_adapter.py +0 -0
  303. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_cli.py +0 -0
  304. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_codex_e2e.py +0 -0
  305. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_codex_install.py +0 -0
  306. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_codex_proxy.py +0 -0
  307. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_config_paths.py +0 -0
  308. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_connect_flow.py +0 -0
  309. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_consumer_mode.py +0 -0
  310. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_copilot_adapter.py +0 -0
  311. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_copilot_proxy.py +0 -0
  312. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_daemon_manager.py +0 -0
  313. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_event_schema_v1.py +0 -0
  314. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_events.py +0 -0
  315. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_launch_env.py +0 -0
  316. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_opencode_proxy.py +0 -0
  317. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_product_flow.py +0 -0
  318. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_protect.py +0 -0
  319. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_render.py +0 -0
  320. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime_action_harnesses.py +0 -0
  321. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime_actions.py +0 -0
  322. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime_decisions.py +0 -0
  323. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime_detectors.py +0 -0
  324. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_runtime_signals.py +0 -0
  325. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_store_migrations.py +0 -0
  326. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_surface_server.py +0 -0
  327. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_guard_verdicts.py +0 -0
  328. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_hermes_adapter.py +0 -0
  329. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_integration.py +0 -0
  330. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_lint_fixes.py +0 -0
  331. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_live_cisco_smoke.py +0 -0
  332. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_manifest.py +0 -0
  333. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_marketplace.py +0 -0
  334. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_mcp_security.py +0 -0
  335. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_openclaw_adapter.py +0 -0
  336. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_operational_security.py +0 -0
  337. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_policy.py +0 -0
  338. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_quality_artifact.py +0 -0
  339. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_rule_registry.py +0 -0
  340. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_scanner.py +0 -0
  341. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_schema_contracts.py +0 -0
  342. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_security.py +0 -0
  343. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_security_ops.py +0 -0
  344. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_skill_security.py +0 -0
  345. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_submission.py +0 -0
  346. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_trust_scoring.py +0 -0
  347. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_trust_specs.py +0 -0
  348. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_verification.py +0 -0
  349. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/tests/test_versioning.py +0 -0
  350. {plugin_scanner-2.0.109 → plugin_scanner-2.0.110}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.109
3
+ Version: 2.0.110
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.109"
7
+ version = "2.0.110"
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.109"
7
+ version = "2.0.110"
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,7 +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
+ from ..runtime.secret_sensitivity import SecretContentMatch, classify_secret_content, classify_secret_path
101
101
  from ..runtime.surface_server import GuardSurfaceRuntime
102
102
  from ..store import GuardStore
103
103
  from .approval_commands import add_approval_parser, run_approval_command
@@ -2999,16 +2999,47 @@ def _runtime_stored_policy_action(
2999
2999
  def _runtime_artifact_policy_action(config: GuardConfig, artifact: GuardArtifact, harness: str) -> str:
3000
3000
  if _prompt_requires_hard_block(artifact):
3001
3001
  return "block"
3002
- risk_actions = [
3003
- resolve_risk_action(config, risk_class, harness=_canonical_harness_name(harness))
3004
- for risk_class in _runtime_artifact_risk_classes(artifact)
3005
- ]
3002
+ canonical_harness = _canonical_harness_name(harness)
3003
+ risk_classes = _runtime_artifact_risk_classes(artifact)
3004
+ has_configured_risk_action = any(
3005
+ _resolve_configured_risk_action(config, risk_class, harness=canonical_harness) for risk_class in risk_classes
3006
+ )
3007
+ if has_configured_risk_action:
3008
+ risk_actions = [
3009
+ _resolve_configured_risk_action(config, risk_class, harness=canonical_harness)
3010
+ or resolve_risk_action(config, risk_class, harness=canonical_harness)
3011
+ for risk_class in risk_classes
3012
+ ]
3013
+ resolved_actions = [action for action in risk_actions if action in VALID_GUARD_ACTIONS]
3014
+ if resolved_actions:
3015
+ return max(resolved_actions, key=_guard_action_severity)
3016
+ guard_default_action = _runtime_artifact_guard_default_action(artifact)
3017
+ if guard_default_action is not None:
3018
+ return guard_default_action
3019
+ risk_actions = [resolve_risk_action(config, risk_class, harness=canonical_harness) for risk_class in risk_classes]
3006
3020
  resolved_actions = [action for action in risk_actions if action in VALID_GUARD_ACTIONS]
3007
3021
  if resolved_actions:
3008
3022
  return max(resolved_actions, key=_guard_action_severity)
3009
3023
  return SAFE_CHANGED_HASH_ACTION
3010
3024
 
3011
3025
 
3026
+ def _resolve_configured_risk_action(config: GuardConfig, risk_class: str, *, harness: str) -> str | None:
3027
+ if config.harness_risk_actions is not None:
3028
+ harness_actions = config.harness_risk_actions.get(harness)
3029
+ if harness_actions is not None and risk_class in harness_actions:
3030
+ return harness_actions[risk_class]
3031
+ if config.risk_actions is not None and risk_class in config.risk_actions:
3032
+ return config.risk_actions[risk_class]
3033
+ return None
3034
+
3035
+
3036
+ def _runtime_artifact_guard_default_action(artifact: GuardArtifact) -> str | None:
3037
+ value = artifact.metadata.get("guard_default_action")
3038
+ if value in VALID_GUARD_ACTIONS:
3039
+ return str(value)
3040
+ return None
3041
+
3042
+
3012
3043
  def _guard_action_severity(action: str) -> int:
3013
3044
  return {
3014
3045
  "allow": 0,
@@ -3985,13 +4016,16 @@ def _codex_post_tool_output_artifact(
3985
4016
  cwd: Path | None,
3986
4017
  ) -> GuardArtifact | None:
3987
4018
  response_text = _collect_codex_tool_response_text(payload.get("tool_response"))
3988
- content_matches = classify_secret_content(response_text)
3989
- if not content_matches:
3990
- return None
3991
4019
  tool_name = _coalesce_string(payload.get("tool_name"), "Bash")
3992
4020
  command_text = _codex_post_tool_command_text(payload)
3993
4021
  if not command_text:
3994
4022
  command_text = tool_name
4023
+ references_local_content = _codex_command_may_read_local_content(command_text, cwd=cwd)
4024
+ content_matches = classify_secret_content(response_text)
4025
+ if not content_matches and references_local_content:
4026
+ content_matches = classify_secret_content(response_text, suppress_samples=False)
4027
+ if not content_matches:
4028
+ return None
3995
4029
  if _codex_source_inspection_can_skip_secret_output(
3996
4030
  command_text=command_text,
3997
4031
  response_text=response_text,
@@ -4009,6 +4043,10 @@ def _codex_post_tool_output_artifact(
4009
4043
  sort_keys=True,
4010
4044
  ).encode("utf-8")
4011
4045
  ).hexdigest()
4046
+ runtime_default_action = "require-reapproval" if references_local_content else "warn"
4047
+ runtime_request_signals = ["tool output contains credential-looking material"]
4048
+ if references_local_content:
4049
+ runtime_request_signals.append("command references a sensitive local source")
4012
4050
  return GuardArtifact(
4013
4051
  artifact_id=f"codex:{source_scope}:tool-output:{fingerprint}",
4014
4052
  name=f"{tool_name} credential-looking output",
@@ -4020,10 +4058,11 @@ def _codex_post_tool_output_artifact(
4020
4058
  "tool_name": tool_name,
4021
4059
  "command_text": command_text,
4022
4060
  "action_class": "credential exfiltration shell command",
4061
+ "guard_default_action": runtime_default_action,
4023
4062
  "request_summary": (
4024
4063
  f"Codex tool `{tool_name}` produced credential-looking output while running `{command_text}`."
4025
4064
  ),
4026
- "runtime_request_signals": ["tool output contains credential-looking material"],
4065
+ "runtime_request_signals": runtime_request_signals,
4027
4066
  "runtime_request_summary": (
4028
4067
  "Requests a sensitive native tool action: credential-looking output reached Codex."
4029
4068
  ),
@@ -4035,6 +4074,209 @@ def _codex_post_tool_output_artifact(
4035
4074
  )
4036
4075
 
4037
4076
 
4077
+ def _codex_command_references_sensitive_local_source(command_text: str, *, cwd: Path | None) -> bool:
4078
+ if _codex_text_contains_sensitive_path_token(command_text, cwd=cwd):
4079
+ return True
4080
+ try:
4081
+ parts = shlex.split(command_text)
4082
+ except ValueError:
4083
+ return False
4084
+ for part in parts:
4085
+ stripped = part.strip()
4086
+ if not stripped or stripped.startswith("-"):
4087
+ continue
4088
+ if _codex_token_is_url(stripped):
4089
+ continue
4090
+ if classify_secret_path(stripped, cwd=cwd) is not None:
4091
+ return True
4092
+ return False
4093
+
4094
+
4095
+ def _codex_token_is_url(token: str) -> bool:
4096
+ parsed = urllib.parse.urlparse(token)
4097
+ return bool(parsed.scheme and parsed.netloc)
4098
+
4099
+
4100
+ def _codex_text_contains_sensitive_path_token(text: str, *, cwd: Path | None) -> bool:
4101
+ for match in _PROMPT_PATH_TOKEN_PATTERN.finditer(text):
4102
+ if _codex_path_token_is_url_path(text, match.start()):
4103
+ continue
4104
+ if classify_secret_path(match.group(0), cwd=cwd) is not None:
4105
+ return True
4106
+ return False
4107
+
4108
+
4109
+ def _codex_path_token_is_url_path(text: str, start: int) -> bool:
4110
+ prefix = text[:start].lower()
4111
+ last_separator = max(prefix.rfind(separator) for separator in " \t\r\n'\"`<>|;(){}[]")
4112
+ token_prefix = prefix[last_separator + 1 :]
4113
+ if "://" in token_prefix:
4114
+ return True
4115
+ scheme = ""
4116
+ if token_prefix.endswith(":/"):
4117
+ scheme = token_prefix[:-2]
4118
+ elif token_prefix.endswith(":"):
4119
+ scheme = token_prefix[:-1]
4120
+ return _codex_token_prefix_is_url_scheme(scheme)
4121
+
4122
+
4123
+ def _codex_token_prefix_is_url_scheme(scheme: str) -> bool:
4124
+ return bool(scheme) and scheme[0].isalpha() and all(char.isalnum() or char in "+.-" for char in scheme)
4125
+
4126
+
4127
+ def _codex_command_may_read_local_content(command_text: str, *, cwd: Path | None) -> bool:
4128
+ if _codex_command_references_sensitive_local_source(command_text, cwd=cwd):
4129
+ return True
4130
+ if any(marker in command_text for marker in ("$(", "${", "`")):
4131
+ return True
4132
+ pipeline_segments = _split_codex_safe_read_only_pipeline(command_text)
4133
+ if pipeline_segments is not None:
4134
+ return any(
4135
+ _codex_pipeline_segment_may_read_local_content(segment, index=index, cwd=cwd)
4136
+ for index, segment in enumerate(pipeline_segments)
4137
+ )
4138
+ try:
4139
+ parts = _codex_shell_split(command_text)
4140
+ except ValueError:
4141
+ return True
4142
+ return _codex_command_parts_may_read_local_content(parts, cwd=cwd)
4143
+
4144
+
4145
+ def _codex_pipeline_segment_may_read_local_content(segment: str, *, index: int, cwd: Path | None) -> bool:
4146
+ try:
4147
+ parts = _codex_shell_split(segment)
4148
+ except ValueError:
4149
+ return True
4150
+ if not parts:
4151
+ return False
4152
+ if index == 0:
4153
+ return _codex_command_parts_may_read_local_content(parts, cwd=cwd)
4154
+ return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
4155
+ segment, cwd=cwd
4156
+ )
4157
+
4158
+
4159
+ def _codex_command_parts_may_read_local_content(parts: list[str], *, cwd: Path | None) -> bool:
4160
+ for start in _codex_command_start_indexes(parts):
4161
+ previous_token = parts[start - 1] if start > 0 else None
4162
+ segment_parts = _codex_command_segment_parts(parts, start)
4163
+ if previous_token == "|":
4164
+ if _codex_command_sequence_is_read_only_source_inspection(segment_parts, cwd=cwd):
4165
+ return True
4166
+ continue
4167
+ if _codex_command_sequence_starts_with_local_reader(segment_parts, cwd=cwd):
4168
+ return True
4169
+ return False
4170
+
4171
+
4172
+ def _codex_command_start_indexes(parts: list[str]) -> list[int]:
4173
+ starts = [0] if parts else []
4174
+ for index, part in enumerate(parts[:-1]):
4175
+ if part in {"&&", "||", ";", "&", "|", "|&"}:
4176
+ starts.append(index + 1)
4177
+ return starts
4178
+
4179
+
4180
+ def _codex_command_segment_parts(parts: list[str], start: int) -> list[str]:
4181
+ end = start
4182
+ while end < len(parts) and parts[end] not in {"&&", "||", ";", "&", "|", "|&"}:
4183
+ end += 1
4184
+ return parts[start:end]
4185
+
4186
+
4187
+ def _codex_command_sequence_is_read_only_source_inspection(parts: list[str], *, cwd: Path | None) -> bool:
4188
+ command_parts = _codex_unwrapped_command_parts(parts)
4189
+ if not command_parts:
4190
+ return False
4191
+ segment = shlex.join(command_parts)
4192
+ return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
4193
+ segment, cwd=cwd
4194
+ )
4195
+
4196
+
4197
+ def _codex_command_sequence_starts_with_local_reader(parts: list[str], *, cwd: Path | None) -> bool:
4198
+ command_parts = _codex_unwrapped_command_parts(parts)
4199
+ if not command_parts:
4200
+ return False
4201
+ if _codex_command_parts_are_git_grep(command_parts):
4202
+ return True
4203
+ return _codex_command_part_is_local_reader(command_parts, 0, cwd=cwd)
4204
+
4205
+
4206
+ def _codex_command_parts_are_git_grep(parts: list[str]) -> bool:
4207
+ return bool(parts) and Path(parts[0]).name.lower() == "git" and _git_grep_search_args(parts[1:]) is not None
4208
+
4209
+
4210
+ def _codex_unwrapped_command_parts(parts: list[str]) -> list[str]:
4211
+ remaining = parts
4212
+ while remaining:
4213
+ executable = Path(remaining[0]).name.lower()
4214
+ if executable == "command":
4215
+ remaining = _codex_strip_command_wrapper(remaining[1:])
4216
+ continue
4217
+ if executable == "env":
4218
+ remaining = _codex_strip_env_wrapper(remaining[1:])
4219
+ continue
4220
+ return remaining
4221
+ return []
4222
+
4223
+
4224
+ def _codex_strip_command_wrapper(parts: list[str]) -> list[str]:
4225
+ index = 0
4226
+ while index < len(parts) and parts[index] in {"-p", "-v", "-V"}:
4227
+ index += 1
4228
+ if index < len(parts) and parts[index] == "--":
4229
+ index += 1
4230
+ return parts[index:]
4231
+
4232
+
4233
+ def _codex_strip_env_wrapper(parts: list[str]) -> list[str]:
4234
+ index = 0
4235
+ while index < len(parts):
4236
+ part = parts[index]
4237
+ if part == "--":
4238
+ return parts[index + 1 :]
4239
+ if part in {"-i", "-0", "--ignore-environment", "--null"}:
4240
+ index += 1
4241
+ continue
4242
+ if part in {"-u", "--unset", "-C", "--chdir", "-S", "--split-string"}:
4243
+ index += 2
4244
+ continue
4245
+ if part.startswith(("--unset=", "--chdir=", "--split-string=")):
4246
+ index += 1
4247
+ continue
4248
+ if part.startswith("-"):
4249
+ index += 1
4250
+ continue
4251
+ if "=" in part and not part.startswith("="):
4252
+ index += 1
4253
+ continue
4254
+ return parts[index:]
4255
+ return []
4256
+
4257
+
4258
+ def _codex_shell_split(command_text: str) -> list[str]:
4259
+ lexer = shlex.shlex(command_text, posix=True, punctuation_chars=True)
4260
+ lexer.whitespace_split = True
4261
+ lexer.commenters = ""
4262
+ return list(lexer)
4263
+
4264
+
4265
+ def _codex_command_part_is_local_reader(parts: list[str], index: int, *, cwd: Path | None) -> bool:
4266
+ local_read_commands = {"cat", "grep", "head", "rg", "sed", "tail"}
4267
+ executable = Path(parts[index]).name.lower()
4268
+ if executable not in local_read_commands:
4269
+ return False
4270
+ if index == 0:
4271
+ return True
4272
+ if parts[index - 1] == "|":
4273
+ segment = shlex.join(parts[index:])
4274
+ return _codex_command_is_read_only_source_search(segment, cwd=cwd) or _codex_command_is_read_only_source_view(
4275
+ segment, cwd=cwd
4276
+ )
4277
+ return parts[index - 1] in {"&&", "||", ";", "&", "|&"}
4278
+
4279
+
4038
4280
  def _codex_post_tool_command_is_read_only_source_inspection(
4039
4281
  *,
4040
4282
  payload: dict[str, object],
@@ -16,6 +16,7 @@ from ..config import GuardConfig
16
16
  from ..incident import build_incident_context
17
17
  from ..models import GuardArtifact, HarnessDetection, PolicyDecision
18
18
  from ..policy import build_decision_v2, decide_action
19
+ from ..policy.engine import VALID_GUARD_ACTIONS
19
20
  from ..receipts import build_receipt
20
21
  from ..risk import artifact_risk_signals_typed, artifact_risk_summary, summarize_signals
21
22
  from ..runtime.signals import RiskSignalV2
@@ -102,6 +103,13 @@ def _is_blocking_action(policy_action: str) -> bool:
102
103
  return policy_action in {"block", "sandbox-required", "require-reapproval"}
103
104
 
104
105
 
106
+ def _guard_default_action(artifact: GuardArtifact) -> str | None:
107
+ value = artifact.metadata.get("guard_default_action")
108
+ if value in VALID_GUARD_ACTIONS:
109
+ return str(value)
110
+ return None
111
+
112
+
105
113
  def _build_removed_provenance(previous: dict[str, object]) -> str:
106
114
  scope = previous.get("source_scope")
107
115
  config_path = previous.get("config_path")
@@ -395,7 +403,7 @@ def evaluate_detection(
395
403
  "file_read_request",
396
404
  "tool_action_request",
397
405
  }:
398
- policy_action = "require-reapproval"
406
+ policy_action = _guard_default_action(artifact) or "require-reapproval"
399
407
  elif is_first_seen and configured_action is None and effective_default_action is not None:
400
408
  policy_action = effective_default_action
401
409
  else:
@@ -92,6 +92,8 @@ _SENSITIVE_PATH_REASONS = {
92
92
  }
93
93
  _SECRET_ASSIGNMENT_VALUE_PATTERN = r"(?:\"[^\"\r\n]+\"|'[^'\r\n]+'|[^ \t\r\n\"',}]+)"
94
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
+ _SAMPLE_SECRET_VALUE_PATTERN = re.compile(r"(?i)\b(?:example|fake|dummy|invalid|test|canary)\b")
96
+ _SAMPLE_SUPPRESSIBLE_CONTENT_CLASSIFIERS = frozenset({"credential-assignment", "generic-bearer-token"})
95
97
  _SECRET_CONTENT_PATTERNS: tuple[tuple[str, str, SecretContentSensitivity, re.Pattern[str], str], ...] = (
96
98
  (
97
99
  "npm-auth-token",
@@ -148,6 +150,13 @@ _SECRET_CONTENT_PATTERNS: tuple[tuple[str, str, SecretContentSensitivity, re.Pat
148
150
  re.compile(r"-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----", re.MULTILINE),
149
151
  "Guard found a PEM private key header.",
150
152
  ),
153
+ (
154
+ "generic-bearer-token",
155
+ "generic bearer token",
156
+ "medium",
157
+ re.compile(r"(?im)\bbearer\s+[A-Za-z0-9._~+/=-]{16,}\b"),
158
+ "Guard found a bearer token pattern.",
159
+ ),
151
160
  (
152
161
  "credential-marker",
153
162
  "credential assignment",
@@ -272,13 +281,18 @@ def classify_legacy_secret_path_families(text: str) -> set[str]:
272
281
  return {family for marker, family in LEGACY_SECRET_PATH_TEXT_MARKERS if marker in lowered}
273
282
 
274
283
 
275
- def classify_secret_content(text: str | None) -> tuple[SecretContentMatch, ...]:
284
+ def classify_secret_content(text: str | None, *, suppress_samples: bool = True) -> tuple[SecretContentMatch, ...]:
276
285
  if not isinstance(text, str) or not text.strip():
277
286
  return ()
278
287
  matches: list[SecretContentMatch] = []
279
288
  seen: set[str] = set()
280
289
  for classifier, family, sensitivity, pattern, reason in _SECRET_CONTENT_PATTERNS:
281
- if pattern.search(text) is None or classifier in seen:
290
+ if classifier in seen:
291
+ continue
292
+ if not any(
293
+ not _secret_content_match_is_sample(classifier=classifier, text=match.group(0), enabled=suppress_samples)
294
+ for match in pattern.finditer(text)
295
+ ):
282
296
  continue
283
297
  seen.add(classifier)
284
298
  matches.append(
@@ -292,6 +306,15 @@ def classify_secret_content(text: str | None) -> tuple[SecretContentMatch, ...]:
292
306
  return tuple(matches)
293
307
 
294
308
 
309
+ def _secret_content_match_is_sample(*, classifier: str, text: str, enabled: bool) -> bool:
310
+ if not enabled or classifier not in _SAMPLE_SUPPRESSIBLE_CONTENT_CLASSIFIERS:
311
+ return False
312
+ if classifier == "generic-bearer-token":
313
+ token = text.rsplit(None, 1)[-1]
314
+ return _SAMPLE_SECRET_VALUE_PATTERN.search(token) is not None and re.search(r"[A-Za-z0-9]{20,}", token) is None
315
+ return _SAMPLE_SECRET_VALUE_PATTERN.search(text) is not None
316
+
317
+
295
318
  def redacted_secret_path_context(path: str) -> str | None:
296
319
  segments = tuple(segment for segment in path.replace("\\", "/").split("/") if segment)
297
320
  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.109"
3
+ __version__ = "2.0.110"
@@ -415,10 +415,13 @@ def test_secret_sensitivity_module_classifies_wallet_private_key_filenames(tmp_p
415
415
  ("token=" + "github_pat_" + "A" * 22 + "_" + "B" * 59, "GitHub token"),
416
416
  ("aws_access_key_id=" + "AKIA" + "A" * 16, "AWS access key"),
417
417
  ("OPENAI_API_KEY=" + "sk-" + "A" * 32, "OpenAI API key"),
418
+ ("OPENAI_API_KEY=sk-proj-" + "A" * 24 + "-test-" + "B" * 24, "OpenAI API key"),
418
419
  ("ANTHROPIC_API_KEY=" + "sk-ant-api03-" + "A" * 60, "Anthropic API key"),
419
420
  ("HEDERA_PRIVATE_KEY=" + "a" * 64, "Hedera private key"),
420
421
  ('HEDERA_PRIVATE_KEY="' + "a" * 64 + '"', "Hedera private key"),
421
422
  ("-----BEGIN " + "PRIVATE KEY-----\nredacted\n-----END " + "PRIVATE KEY-----", "PEM private key"),
423
+ ("Authorization: Bearer " + "A" * 32, "generic bearer token"),
424
+ ("Authorization: Bearer " + "A" * 24 + "-test-" + "B" * 24, "generic bearer token"),
422
425
  ('TOKEN="' + "A" * 24 + '"', "credential assignment"),
423
426
  ("auth_token='" + "B" * 24 + "'", "credential assignment"),
424
427
  ('{"password": "' + "C" * 24 + '"}', "credential assignment"),
@@ -439,6 +442,23 @@ def test_secret_content_classifier_does_not_upgrade_npm_token_prose():
439
442
  assert not any(match.family == "npm auth token" for match in matches)
440
443
 
441
444
 
445
+ @pytest.mark.parametrize(
446
+ "content",
447
+ [
448
+ "API_TOKEN=example-token",
449
+ "password=dummy-value",
450
+ "token=definitely-invalid",
451
+ "secret=fake-value",
452
+ "auth_token=canary-token",
453
+ "OPENAI_API_KEY=sk-test",
454
+ "https://api.example.test/health?token=definitely-invalid",
455
+ "Authorization: Bearer definitely-invalid",
456
+ ],
457
+ )
458
+ def test_secret_content_classifier_suppresses_sample_token_values(content):
459
+ assert classify_secret_content(content) == ()
460
+
461
+
442
462
  def test_file_read_request_classifier_is_argument_aware(tmp_path):
443
463
  env_request = extract_sensitive_file_read_request("read_file", {"path": ".env.local"})
444
464
  claude_request = extract_sensitive_file_read_request("Read", {"file_path": "~/.ssh/config"}, home_dir=tmp_path)