plugin-scanner 2.0.82__tar.gz → 2.0.84__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/PKG-INFO +1 -1
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/pyproject.toml +1 -1
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/commands.py +49 -4
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +57 -15
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_runtime.py +203 -11
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_mcp_security.py +124 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.dockerignore +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.gitignore +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/Dockerfile +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/requirements.txt +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.84
|
|
4
4
|
Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
6
6
|
Project-URL: Repository, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plugin-scanner"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.84"
|
|
8
8
|
description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hol-guard"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.84"
|
|
8
8
|
description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
{plugin_scanner-2.0.82 → plugin_scanner-2.0.84}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -3816,7 +3816,13 @@ _CODEX_SEARCH_OPTION_VALUE_FLAGS = frozenset(
|
|
|
3816
3816
|
_CODEX_SEARCH_OPTION_VALUE_FLAGS_BY_EXECUTABLE = {
|
|
3817
3817
|
"rg": frozenset({"-T"}),
|
|
3818
3818
|
}
|
|
3819
|
-
_CODEX_SEARCH_UNSAFE_FLAGS = frozenset({"--pre"})
|
|
3819
|
+
_CODEX_SEARCH_UNSAFE_FLAGS = frozenset({"--dereference-recursive", "--follow", "--pre"})
|
|
3820
|
+
_CODEX_SEARCH_UNSAFE_SHORT_FLAGS_BY_EXECUTABLE = {
|
|
3821
|
+
"egrep": frozenset({"R"}),
|
|
3822
|
+
"fgrep": frozenset({"R"}),
|
|
3823
|
+
"grep": frozenset({"R"}),
|
|
3824
|
+
"rg": frozenset({"L"}),
|
|
3825
|
+
}
|
|
3820
3826
|
_CODEX_GIT_GLOBAL_VALUE_FLAGS = frozenset(
|
|
3821
3827
|
{"-c", "--config-env", "--exec-path", "--git-dir", "--work-tree", "--namespace"}
|
|
3822
3828
|
)
|
|
@@ -3988,6 +3994,7 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
|
|
|
3988
3994
|
positional: list[str] = []
|
|
3989
3995
|
skip_next = False
|
|
3990
3996
|
pattern_from_option = False
|
|
3997
|
+
after_option_terminator = False
|
|
3991
3998
|
option_value_flags = _CODEX_SEARCH_OPTION_VALUE_FLAGS | _CODEX_SEARCH_OPTION_VALUE_FLAGS_BY_EXECUTABLE.get(
|
|
3992
3999
|
executable, frozenset()
|
|
3993
4000
|
)
|
|
@@ -3995,7 +4002,13 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
|
|
|
3995
4002
|
if skip_next:
|
|
3996
4003
|
skip_next = False
|
|
3997
4004
|
continue
|
|
3998
|
-
if
|
|
4005
|
+
if after_option_terminator:
|
|
4006
|
+
positional.append(arg)
|
|
4007
|
+
continue
|
|
4008
|
+
if arg == "--":
|
|
4009
|
+
after_option_terminator = True
|
|
4010
|
+
continue
|
|
4011
|
+
if _codex_search_arg_is_unsafe(arg, executable=executable, option_value_flags=option_value_flags):
|
|
3999
4012
|
return False
|
|
4000
4013
|
if arg in _CODEX_SEARCH_PATTERN_VALUE_FLAGS:
|
|
4001
4014
|
pattern_from_option = True
|
|
@@ -4012,8 +4025,6 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
|
|
|
4012
4025
|
continue
|
|
4013
4026
|
if any(arg.startswith(f"{flag}=") for flag in option_value_flags):
|
|
4014
4027
|
continue
|
|
4015
|
-
if arg == "--":
|
|
4016
|
-
continue
|
|
4017
4028
|
if arg.startswith("-"):
|
|
4018
4029
|
continue
|
|
4019
4030
|
positional.append(arg)
|
|
@@ -4026,6 +4037,22 @@ def _codex_search_targets_are_source_like(args: list[str], *, cwd: Path | None,
|
|
|
4026
4037
|
return bool(targets) and all(_codex_search_target_is_source_like(target, cwd=cwd) for target in targets)
|
|
4027
4038
|
|
|
4028
4039
|
|
|
4040
|
+
def _codex_search_arg_is_unsafe(arg: str, *, executable: str, option_value_flags: frozenset[str]) -> bool:
|
|
4041
|
+
if arg in _CODEX_SEARCH_UNSAFE_FLAGS:
|
|
4042
|
+
return True
|
|
4043
|
+
if any(arg.startswith(f"{flag}=") for flag in _CODEX_SEARCH_UNSAFE_FLAGS):
|
|
4044
|
+
return True
|
|
4045
|
+
if not arg.startswith("-") or arg.startswith("--"):
|
|
4046
|
+
return False
|
|
4047
|
+
unsafe_short_flags = _CODEX_SEARCH_UNSAFE_SHORT_FLAGS_BY_EXECUTABLE.get(executable, frozenset())
|
|
4048
|
+
for flag in arg[1:]:
|
|
4049
|
+
if flag in unsafe_short_flags:
|
|
4050
|
+
return True
|
|
4051
|
+
if f"-{flag}" in option_value_flags:
|
|
4052
|
+
return False
|
|
4053
|
+
return False
|
|
4054
|
+
|
|
4055
|
+
|
|
4029
4056
|
def _codex_search_target_is_source_like(target: str, *, cwd: Path | None) -> bool:
|
|
4030
4057
|
stripped = target.strip().strip("'\"")
|
|
4031
4058
|
if not stripped:
|
|
@@ -4118,6 +4145,17 @@ _PROMPT_CONTENT_SCAN_SKIP_BASENAMES = frozenset(
|
|
|
4118
4145
|
".git-credentials",
|
|
4119
4146
|
}
|
|
4120
4147
|
)
|
|
4148
|
+
_PROMPT_CONTENT_SCAN_SECRET_BASENAME_MARKERS = frozenset(
|
|
4149
|
+
{
|
|
4150
|
+
"auth",
|
|
4151
|
+
"credential",
|
|
4152
|
+
"env",
|
|
4153
|
+
"key",
|
|
4154
|
+
"pass",
|
|
4155
|
+
"secret",
|
|
4156
|
+
"token",
|
|
4157
|
+
}
|
|
4158
|
+
)
|
|
4121
4159
|
|
|
4122
4160
|
|
|
4123
4161
|
def _codex_prompt_credential_file_artifact(
|
|
@@ -4135,6 +4173,8 @@ def _codex_prompt_credential_file_artifact(
|
|
|
4135
4173
|
continue
|
|
4136
4174
|
if not path.name.startswith("."):
|
|
4137
4175
|
continue
|
|
4176
|
+
if not _prompt_path_looks_secret_bearing(path):
|
|
4177
|
+
continue
|
|
4138
4178
|
if not path.is_file():
|
|
4139
4179
|
continue
|
|
4140
4180
|
try:
|
|
@@ -4181,6 +4221,11 @@ def _codex_prompt_credential_file_artifact(
|
|
|
4181
4221
|
return None
|
|
4182
4222
|
|
|
4183
4223
|
|
|
4224
|
+
def _prompt_path_looks_secret_bearing(path: Path) -> bool:
|
|
4225
|
+
lowered_name = path.name.lower()
|
|
4226
|
+
return any(marker in lowered_name for marker in _PROMPT_CONTENT_SCAN_SECRET_BASENAME_MARKERS)
|
|
4227
|
+
|
|
4228
|
+
|
|
4184
4229
|
def _with_codex_prompt_display_metadata(artifact: GuardArtifact, *, prompt_text: str) -> GuardArtifact:
|
|
4185
4230
|
matched_text = artifact.metadata.get("prompt_matched_text")
|
|
4186
4231
|
display = _codex_prompt_display_text(
|
|
@@ -47,6 +47,13 @@ class CiscoMcpScanSummary:
|
|
|
47
47
|
scan_mode: str = "static"
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
@dataclass(frozen=True, slots=True)
|
|
51
|
+
class _StaticScanTarget:
|
|
52
|
+
read_path: Path
|
|
53
|
+
tool_name: str
|
|
54
|
+
content_type: str
|
|
55
|
+
|
|
56
|
+
|
|
50
57
|
def _empty_counts() -> dict[str, int]:
|
|
51
58
|
return {severity.value: 0 for severity in Severity}
|
|
52
59
|
|
|
@@ -235,15 +242,24 @@ def _normalize_finding(plugin_dir: Path, file_path: Path, finding: object) -> Fi
|
|
|
235
242
|
)
|
|
236
243
|
|
|
237
244
|
|
|
238
|
-
def _collect_static_targets(plugin_dir: Path) -> tuple[
|
|
245
|
+
def _collect_static_targets(plugin_dir: Path) -> tuple[_StaticScanTarget, ...]:
|
|
239
246
|
config_path = plugin_dir / ".mcp.json"
|
|
240
|
-
|
|
247
|
+
resolved_config_path = _safe_resolved_static_target(plugin_dir, config_path)
|
|
248
|
+
if resolved_config_path is None:
|
|
241
249
|
return ()
|
|
242
250
|
|
|
243
|
-
targets: list[
|
|
251
|
+
targets: list[_StaticScanTarget] = []
|
|
252
|
+
seen_targets: set[Path] = set()
|
|
244
253
|
try:
|
|
245
|
-
if
|
|
246
|
-
targets.append(
|
|
254
|
+
if resolved_config_path.stat().st_size <= _MAX_TARGET_SIZE_BYTES:
|
|
255
|
+
targets.append(
|
|
256
|
+
_StaticScanTarget(
|
|
257
|
+
read_path=resolved_config_path,
|
|
258
|
+
tool_name=config_path.name,
|
|
259
|
+
content_type="mcp-config",
|
|
260
|
+
)
|
|
261
|
+
)
|
|
262
|
+
seen_targets.add(resolved_config_path)
|
|
247
263
|
except OSError:
|
|
248
264
|
pass
|
|
249
265
|
for root, dirs, files in os.walk(plugin_dir, topdown=True):
|
|
@@ -253,15 +269,40 @@ def _collect_static_targets(plugin_dir: Path) -> tuple[Path, ...]:
|
|
|
253
269
|
file_path = current_dir / file_name
|
|
254
270
|
if file_path == config_path or file_path.suffix.lower() not in _SOURCE_SUFFIXES:
|
|
255
271
|
continue
|
|
272
|
+
resolved_file_path = _safe_resolved_static_target(plugin_dir, file_path)
|
|
273
|
+
if resolved_file_path is None or resolved_file_path in seen_targets:
|
|
274
|
+
continue
|
|
256
275
|
try:
|
|
257
|
-
if
|
|
276
|
+
if resolved_file_path.stat().st_size > _MAX_TARGET_SIZE_BYTES:
|
|
258
277
|
continue
|
|
259
278
|
except OSError:
|
|
260
279
|
continue
|
|
261
|
-
targets.append(
|
|
280
|
+
targets.append(
|
|
281
|
+
_StaticScanTarget(
|
|
282
|
+
read_path=resolved_file_path,
|
|
283
|
+
tool_name=resolved_file_path.name,
|
|
284
|
+
content_type="mcp-source",
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
seen_targets.add(resolved_file_path)
|
|
262
288
|
return tuple(targets)
|
|
263
289
|
|
|
264
290
|
|
|
291
|
+
def _safe_resolved_static_target(plugin_dir: Path, target: Path) -> Path | None:
|
|
292
|
+
try:
|
|
293
|
+
resolved_root = plugin_dir.resolve(strict=True)
|
|
294
|
+
resolved_target = target.resolve(strict=True)
|
|
295
|
+
if not resolved_target.is_file():
|
|
296
|
+
return None
|
|
297
|
+
except (OSError, RuntimeError):
|
|
298
|
+
return None
|
|
299
|
+
try:
|
|
300
|
+
resolved_target.relative_to(resolved_root)
|
|
301
|
+
except ValueError:
|
|
302
|
+
return None
|
|
303
|
+
return resolved_target
|
|
304
|
+
|
|
305
|
+
|
|
265
306
|
def _run_awaitable(awaitable: Awaitable[T]) -> T:
|
|
266
307
|
try:
|
|
267
308
|
asyncio.get_running_loop()
|
|
@@ -288,40 +329,41 @@ def _run_awaitable(awaitable: Awaitable[T]) -> T:
|
|
|
288
329
|
|
|
289
330
|
|
|
290
331
|
async def _scan_targets(
|
|
291
|
-
plugin_dir: Path, targets: tuple[
|
|
332
|
+
plugin_dir: Path, targets: tuple[_StaticScanTarget, ...], analyzer: object
|
|
292
333
|
) -> tuple[tuple[Finding, ...], int]:
|
|
293
334
|
findings: list[Finding] = []
|
|
294
335
|
targets_scanned = 0
|
|
295
336
|
for target in targets:
|
|
296
337
|
try:
|
|
297
|
-
content = target.read_text(encoding="utf-8", errors="ignore")
|
|
338
|
+
content = target.read_path.read_text(encoding="utf-8", errors="ignore")
|
|
298
339
|
except OSError:
|
|
299
340
|
continue
|
|
300
|
-
content_type = "mcp-config" if target.name == ".mcp.json" else "mcp-source"
|
|
301
341
|
external_findings = await analyzer.analyze(
|
|
302
342
|
content,
|
|
303
343
|
{
|
|
304
|
-
"tool_name": target.
|
|
305
|
-
"content_type": content_type,
|
|
306
|
-
"file_path": str(target),
|
|
344
|
+
"tool_name": target.tool_name,
|
|
345
|
+
"content_type": target.content_type,
|
|
346
|
+
"file_path": str(target.read_path),
|
|
307
347
|
},
|
|
308
348
|
)
|
|
309
349
|
targets_scanned += 1
|
|
310
350
|
for finding in external_findings:
|
|
311
|
-
findings.append(_normalize_finding(plugin_dir, target, finding))
|
|
351
|
+
findings.append(_normalize_finding(plugin_dir, target.read_path, finding))
|
|
312
352
|
return tuple(findings), targets_scanned
|
|
313
353
|
|
|
314
354
|
|
|
315
355
|
def run_cisco_mcp_scan(plugin_dir: Path, mode: str = "auto") -> CiscoMcpScanSummary:
|
|
316
356
|
"""Run Cisco MCP scanner static analysis when available."""
|
|
317
357
|
|
|
358
|
+
config_path = plugin_dir / ".mcp.json"
|
|
359
|
+
|
|
318
360
|
if mode == "off":
|
|
319
361
|
return _build_summary(
|
|
320
362
|
status=CiscoIntegrationStatus.SKIPPED,
|
|
321
363
|
message="Cisco MCP scanning disabled by configuration.",
|
|
322
364
|
)
|
|
323
365
|
|
|
324
|
-
if
|
|
366
|
+
if _safe_resolved_static_target(plugin_dir, config_path) is None:
|
|
325
367
|
return _build_summary(
|
|
326
368
|
status=CiscoIntegrationStatus.SKIPPED,
|
|
327
369
|
message="No .mcp.json found; Cisco MCP scan skipped.",
|
|
@@ -413,10 +413,10 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
|
|
|
413
413
|
home_dir = tmp_path / "home"
|
|
414
414
|
workspace_dir = tmp_path / "workspace"
|
|
415
415
|
_build_guard_fixture(home_dir, workspace_dir)
|
|
416
|
-
_write_text(workspace_dir / ".
|
|
416
|
+
_write_text(workspace_dir / ".authrc", "fake_credential=canary\n")
|
|
417
417
|
event = {
|
|
418
418
|
"event": "UserPromptSubmit",
|
|
419
|
-
"prompt": "read .
|
|
419
|
+
"prompt": "read .authrc",
|
|
420
420
|
"source_scope": "project",
|
|
421
421
|
}
|
|
422
422
|
monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
|
|
@@ -440,8 +440,8 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
|
|
|
440
440
|
|
|
441
441
|
assert rc == 1
|
|
442
442
|
assert output["artifact_type"] == "prompt_request"
|
|
443
|
-
assert "read .
|
|
444
|
-
assert approval_requests[0]["launch_target"] == "Codex prompt for `.
|
|
443
|
+
assert "read .authrc" in output["launch_summary"]
|
|
444
|
+
assert approval_requests[0]["launch_target"] == "Codex prompt for `.authrc`: read .authrc"
|
|
445
445
|
|
|
446
446
|
def test_codex_prompt_display_sanitizes_common_home_paths(self) -> None:
|
|
447
447
|
display = guard_commands_module._codex_prompt_display_text(
|
|
@@ -541,6 +541,137 @@ Please investigate the bug end to end, fix the publish flow, and make sure user-
|
|
|
541
541
|
assert output["recorded"] is True
|
|
542
542
|
assert "approval_requests" not in output
|
|
543
543
|
|
|
544
|
+
def test_codex_post_tool_use_allows_short_option_value_payloads(
|
|
545
|
+
self,
|
|
546
|
+
monkeypatch,
|
|
547
|
+
tmp_path,
|
|
548
|
+
capsys,
|
|
549
|
+
) -> None:
|
|
550
|
+
home_dir = tmp_path / "home"
|
|
551
|
+
workspace_dir = tmp_path / "workspace"
|
|
552
|
+
_build_guard_fixture(home_dir, workspace_dir)
|
|
553
|
+
event = {
|
|
554
|
+
"event": "PostToolUse",
|
|
555
|
+
"tool_name": "Bash",
|
|
556
|
+
"tool_input": {"command": "rg -gLICENSE TOKEN src"},
|
|
557
|
+
"tool_response": {
|
|
558
|
+
"stdout": "src/config.ts:1:const auth_token = process.env.TOKEN",
|
|
559
|
+
},
|
|
560
|
+
"source_scope": "project",
|
|
561
|
+
}
|
|
562
|
+
monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
|
|
563
|
+
|
|
564
|
+
rc = main(
|
|
565
|
+
[
|
|
566
|
+
"guard",
|
|
567
|
+
"hook",
|
|
568
|
+
"--home",
|
|
569
|
+
str(home_dir),
|
|
570
|
+
"--workspace",
|
|
571
|
+
str(workspace_dir),
|
|
572
|
+
"--harness",
|
|
573
|
+
"codex",
|
|
574
|
+
"--json",
|
|
575
|
+
]
|
|
576
|
+
)
|
|
577
|
+
output = json.loads(capsys.readouterr().out)
|
|
578
|
+
|
|
579
|
+
assert rc == 0
|
|
580
|
+
assert output["recorded"] is True
|
|
581
|
+
assert "approval_requests" not in output
|
|
582
|
+
|
|
583
|
+
def test_codex_post_tool_use_allows_double_dash_terminated_literal_pattern(
|
|
584
|
+
self,
|
|
585
|
+
monkeypatch,
|
|
586
|
+
tmp_path,
|
|
587
|
+
capsys,
|
|
588
|
+
) -> None:
|
|
589
|
+
home_dir = tmp_path / "home"
|
|
590
|
+
workspace_dir = tmp_path / "workspace"
|
|
591
|
+
_build_guard_fixture(home_dir, workspace_dir)
|
|
592
|
+
event = {
|
|
593
|
+
"event": "PostToolUse",
|
|
594
|
+
"tool_name": "Bash",
|
|
595
|
+
"tool_input": {"command": "rg -- --follow src"},
|
|
596
|
+
"tool_response": {
|
|
597
|
+
"stdout": "src/config.ts:1:const auth_token = process.env.TOKEN",
|
|
598
|
+
},
|
|
599
|
+
"source_scope": "project",
|
|
600
|
+
}
|
|
601
|
+
monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
|
|
602
|
+
|
|
603
|
+
rc = main(
|
|
604
|
+
[
|
|
605
|
+
"guard",
|
|
606
|
+
"hook",
|
|
607
|
+
"--home",
|
|
608
|
+
str(home_dir),
|
|
609
|
+
"--workspace",
|
|
610
|
+
str(workspace_dir),
|
|
611
|
+
"--harness",
|
|
612
|
+
"codex",
|
|
613
|
+
"--json",
|
|
614
|
+
]
|
|
615
|
+
)
|
|
616
|
+
output = json.loads(capsys.readouterr().out)
|
|
617
|
+
|
|
618
|
+
assert rc == 0
|
|
619
|
+
assert output["recorded"] is True
|
|
620
|
+
assert "approval_requests" not in output
|
|
621
|
+
|
|
622
|
+
@pytest.mark.parametrize(
|
|
623
|
+
"command",
|
|
624
|
+
(
|
|
625
|
+
"rg --follow TOKEN src",
|
|
626
|
+
"rg -L TOKEN src",
|
|
627
|
+
"grep -R TOKEN src",
|
|
628
|
+
),
|
|
629
|
+
)
|
|
630
|
+
def test_codex_post_tool_use_blocks_symlink_following_source_search_flags(
|
|
631
|
+
self,
|
|
632
|
+
monkeypatch,
|
|
633
|
+
tmp_path,
|
|
634
|
+
capsys,
|
|
635
|
+
command: str,
|
|
636
|
+
) -> None:
|
|
637
|
+
home_dir = tmp_path / "home"
|
|
638
|
+
workspace_dir = tmp_path / "workspace"
|
|
639
|
+
_build_guard_fixture(home_dir, workspace_dir)
|
|
640
|
+
secret_file = home_dir / ".aws" / "credentials"
|
|
641
|
+
_write_text(secret_file, "auth_token=outside-secret\n")
|
|
642
|
+
src_dir = workspace_dir / "src"
|
|
643
|
+
src_dir.mkdir()
|
|
644
|
+
(src_dir / "config.ts").symlink_to(secret_file)
|
|
645
|
+
event = {
|
|
646
|
+
"event": "PostToolUse",
|
|
647
|
+
"tool_name": "Bash",
|
|
648
|
+
"tool_input": {"command": command},
|
|
649
|
+
"tool_response": {
|
|
650
|
+
"stdout": "src/config.ts:1:auth_token=outside-secret",
|
|
651
|
+
},
|
|
652
|
+
"source_scope": "project",
|
|
653
|
+
}
|
|
654
|
+
monkeypatch.setattr(sys, "stdin", io.StringIO(json.dumps(event)))
|
|
655
|
+
|
|
656
|
+
rc = main(
|
|
657
|
+
[
|
|
658
|
+
"guard",
|
|
659
|
+
"hook",
|
|
660
|
+
"--home",
|
|
661
|
+
str(home_dir),
|
|
662
|
+
"--workspace",
|
|
663
|
+
str(workspace_dir),
|
|
664
|
+
"--harness",
|
|
665
|
+
"codex",
|
|
666
|
+
"--json",
|
|
667
|
+
]
|
|
668
|
+
)
|
|
669
|
+
output = json.loads(capsys.readouterr().out)
|
|
670
|
+
|
|
671
|
+
assert rc == 1
|
|
672
|
+
assert output["artifact_type"] == "tool_action_request"
|
|
673
|
+
assert output["approval_requests"]
|
|
674
|
+
|
|
544
675
|
def test_codex_post_tool_use_allows_ripgrep_type_not_source_search(
|
|
545
676
|
self,
|
|
546
677
|
monkeypatch,
|
|
@@ -10096,10 +10227,10 @@ def test_guard_hook_codex_user_prompt_submit_blocks_credential_looking_dotfile(
|
|
|
10096
10227
|
home_dir = tmp_path / "home"
|
|
10097
10228
|
workspace_dir = tmp_path / "workspace"
|
|
10098
10229
|
_build_guard_fixture(home_dir, workspace_dir)
|
|
10099
|
-
_write_text(workspace_dir / ".
|
|
10230
|
+
_write_text(workspace_dir / ".authrc", "fake_credential\n")
|
|
10100
10231
|
event = {
|
|
10101
10232
|
"hook_event_name": "UserPromptSubmit",
|
|
10102
|
-
"prompt": "Use bash to print the full contents of ./.
|
|
10233
|
+
"prompt": "Use bash to print the full contents of ./.authrc exactly.",
|
|
10103
10234
|
"source_scope": "project",
|
|
10104
10235
|
}
|
|
10105
10236
|
monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
|
|
@@ -10121,7 +10252,7 @@ def test_guard_hook_codex_user_prompt_submit_blocks_credential_looking_dotfile(
|
|
|
10121
10252
|
assert "http://127.0.0.1:4455/approvals/" in payload["reason"]
|
|
10122
10253
|
|
|
10123
10254
|
|
|
10124
|
-
def
|
|
10255
|
+
def test_guard_hook_codex_user_prompt_submit_allows_generic_dotfile_with_canary_text(
|
|
10125
10256
|
tmp_path,
|
|
10126
10257
|
capsys,
|
|
10127
10258
|
monkeypatch,
|
|
@@ -10135,6 +10266,67 @@ def test_guard_hook_codex_user_prompt_submit_blocks_bare_credential_dotfile(
|
|
|
10135
10266
|
"prompt": "read .nvmrc",
|
|
10136
10267
|
"source_scope": "project",
|
|
10137
10268
|
}
|
|
10269
|
+
|
|
10270
|
+
rc, output = _run_guard_hook(
|
|
10271
|
+
home_dir=home_dir,
|
|
10272
|
+
workspace_dir=workspace_dir,
|
|
10273
|
+
harness="codex",
|
|
10274
|
+
event=event,
|
|
10275
|
+
capsys=capsys,
|
|
10276
|
+
monkeypatch=monkeypatch,
|
|
10277
|
+
)
|
|
10278
|
+
payload = json.loads(output)
|
|
10279
|
+
|
|
10280
|
+
assert rc == 0
|
|
10281
|
+
assert payload == {"hookSpecificOutput": {"hookEventName": "UserPromptSubmit"}}
|
|
10282
|
+
|
|
10283
|
+
|
|
10284
|
+
def test_guard_hook_codex_user_prompt_submit_blocks_bare_credential_dotfile(
|
|
10285
|
+
tmp_path,
|
|
10286
|
+
capsys,
|
|
10287
|
+
monkeypatch,
|
|
10288
|
+
):
|
|
10289
|
+
home_dir = tmp_path / "home"
|
|
10290
|
+
workspace_dir = tmp_path / "workspace"
|
|
10291
|
+
_build_guard_fixture(home_dir, workspace_dir)
|
|
10292
|
+
_write_text(workspace_dir / ".authrc", "fake_credential\n")
|
|
10293
|
+
event = {
|
|
10294
|
+
"hook_event_name": "UserPromptSubmit",
|
|
10295
|
+
"prompt": "read .authrc",
|
|
10296
|
+
"source_scope": "project",
|
|
10297
|
+
}
|
|
10298
|
+
monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
|
|
10299
|
+
|
|
10300
|
+
rc, output = _run_guard_hook(
|
|
10301
|
+
home_dir=home_dir,
|
|
10302
|
+
workspace_dir=workspace_dir,
|
|
10303
|
+
harness="codex",
|
|
10304
|
+
event=event,
|
|
10305
|
+
capsys=capsys,
|
|
10306
|
+
monkeypatch=monkeypatch,
|
|
10307
|
+
)
|
|
10308
|
+
payload = json.loads(output)
|
|
10309
|
+
|
|
10310
|
+
assert rc == 0
|
|
10311
|
+
assert payload["decision"] == "block"
|
|
10312
|
+
assert "HOL Guard" in payload["reason"]
|
|
10313
|
+
assert "credential-looking local file" in payload["reason"]
|
|
10314
|
+
|
|
10315
|
+
|
|
10316
|
+
def test_guard_hook_codex_user_prompt_submit_blocks_envrc_credential_dotfile(
|
|
10317
|
+
tmp_path,
|
|
10318
|
+
capsys,
|
|
10319
|
+
monkeypatch,
|
|
10320
|
+
):
|
|
10321
|
+
home_dir = tmp_path / "home"
|
|
10322
|
+
workspace_dir = tmp_path / "workspace"
|
|
10323
|
+
_build_guard_fixture(home_dir, workspace_dir)
|
|
10324
|
+
_write_text(workspace_dir / ".envrc", "token = fixture-only\n")
|
|
10325
|
+
event = {
|
|
10326
|
+
"hook_event_name": "UserPromptSubmit",
|
|
10327
|
+
"prompt": "read .envrc",
|
|
10328
|
+
"source_scope": "project",
|
|
10329
|
+
}
|
|
10138
10330
|
monkeypatch.setattr(guard_commands_module, "ensure_guard_daemon", lambda _guard_home: "http://127.0.0.1:4455")
|
|
10139
10331
|
|
|
10140
10332
|
rc, output = _run_guard_hook(
|
|
@@ -10161,11 +10353,11 @@ def test_guard_hook_codex_prompt_dotfile_scan_uses_bounded_file_read(
|
|
|
10161
10353
|
home_dir = tmp_path / "home"
|
|
10162
10354
|
workspace_dir = tmp_path / "workspace"
|
|
10163
10355
|
_build_guard_fixture(home_dir, workspace_dir)
|
|
10164
|
-
_write_text(workspace_dir / ".
|
|
10356
|
+
_write_text(workspace_dir / ".authrc", "token = fixture-only\n")
|
|
10165
10357
|
monkeypatch.setattr(Path, "read_bytes", lambda _path: (_ for _ in ()).throw(AssertionError("unbounded read")))
|
|
10166
10358
|
event = {
|
|
10167
10359
|
"hook_event_name": "UserPromptSubmit",
|
|
10168
|
-
"prompt": "read .
|
|
10360
|
+
"prompt": "read .authrc",
|
|
10169
10361
|
"source_scope": "project",
|
|
10170
10362
|
}
|
|
10171
10363
|
|
|
@@ -10184,7 +10376,7 @@ def test_guard_hook_codex_prompt_dotfile_scan_uses_bounded_file_read(
|
|
|
10184
10376
|
assert "credential-looking local file" in payload["reason"]
|
|
10185
10377
|
|
|
10186
10378
|
|
|
10187
|
-
@pytest.mark.parametrize("prompt", ["read .
|
|
10379
|
+
@pytest.mark.parametrize("prompt", ["read .authrc.", "print ./.authrc, please"])
|
|
10188
10380
|
def test_guard_hook_codex_prompt_dotfile_scan_ignores_trailing_punctuation(
|
|
10189
10381
|
prompt,
|
|
10190
10382
|
tmp_path,
|
|
@@ -10194,7 +10386,7 @@ def test_guard_hook_codex_prompt_dotfile_scan_ignores_trailing_punctuation(
|
|
|
10194
10386
|
home_dir = tmp_path / "home"
|
|
10195
10387
|
workspace_dir = tmp_path / "workspace"
|
|
10196
10388
|
_build_guard_fixture(home_dir, workspace_dir)
|
|
10197
|
-
_write_text(workspace_dir / ".
|
|
10389
|
+
_write_text(workspace_dir / ".authrc", "token = fixture-only\n")
|
|
10198
10390
|
event = {
|
|
10199
10391
|
"hook_event_name": "UserPromptSubmit",
|
|
10200
10392
|
"prompt": prompt,
|