plugin-scanner 2.0.113__tar.gz → 2.0.114__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.113 → plugin_scanner-2.0.114}/PKG-INFO +1 -1
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/approval-center-layout.tsx +2 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/approval-center-utils.ts +42 -0
- plugin_scanner-2.0.114/dashboard/src/data-flow-evidence-card.tsx +37 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/guard-api.test.ts +97 -2
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/guard-api.ts +1 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/settings-workspace.tsx +8 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/pyproject.toml +1 -1
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/commands.py +96 -7
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/config.py +4 -0
- plugin_scanner-2.0.114/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +16 -0
- plugin_scanner-2.0.114/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +108 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/decisions.py +34 -1
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_config_paths.py +16 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_data_flow.py +12 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime.py +85 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime_decisions.py +57 -0
- plugin_scanner-2.0.113/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.dockerignore +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.gitignore +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/Dockerfile +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/get-started.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/guard/testing-matrix.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/requirements.txt +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_cli.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_product_flow.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.113 → plugin_scanner-2.0.114}/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.114
|
|
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
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
ListControls,
|
|
22
22
|
PaginationControls
|
|
23
23
|
} from "./approval-center-primitives";
|
|
24
|
+
import { DataFlowEvidenceCard } from "./data-flow-evidence-card";
|
|
24
25
|
import { ReceiptsWorkspace } from "./receipts-workspace";
|
|
25
26
|
import { RuntimeOverview } from "./runtime-overview";
|
|
26
27
|
import {
|
|
@@ -555,6 +556,7 @@ function WhatChanged(props: { item: GuardApprovalRequest; diff: GuardArtifactDif
|
|
|
555
556
|
<div className="mt-4 space-y-3 border-l-2 border-brand-blue/10 pl-4">
|
|
556
557
|
<p className="text-sm leading-relaxed text-brand-dark/70">{buildStoppedReason(item, receipt)}</p>
|
|
557
558
|
<WhyGuardCares item={item} />
|
|
559
|
+
<DataFlowEvidenceCard item={item} />
|
|
558
560
|
{policy.length > 0 ? (
|
|
559
561
|
<p className="text-sm leading-relaxed text-brand-dark/70">
|
|
560
562
|
HOL Guard checked {policy.length} saved {policy.length === 1 ? "decision" : "decisions"} before asking you.
|
|
@@ -5,6 +5,48 @@ import type {
|
|
|
5
5
|
GuardReceipt
|
|
6
6
|
} from "./guard-types";
|
|
7
7
|
|
|
8
|
+
export type DataFlowEvidenceSummary = {
|
|
9
|
+
signalTitle: string;
|
|
10
|
+
sourceLabel: string;
|
|
11
|
+
sinkLabel: string;
|
|
12
|
+
signalId: string;
|
|
13
|
+
count: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function deriveDataFlowEvidence(item: GuardApprovalRequest): DataFlowEvidenceSummary | null {
|
|
17
|
+
const signals = item.decision_v2_json?.signals ?? [];
|
|
18
|
+
const dataFlowSignals = signals.filter(
|
|
19
|
+
(s) => s.detector === "data_flow.exfiltration" || s.signal_id.startsWith("data-flow:")
|
|
20
|
+
);
|
|
21
|
+
if (dataFlowSignals.length === 0) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const primary = dataFlowSignals[0];
|
|
25
|
+
return {
|
|
26
|
+
signalTitle: primary.title,
|
|
27
|
+
sourceLabel: "Local secret",
|
|
28
|
+
sinkLabel: resolveDataFlowSinkLabel(primary),
|
|
29
|
+
signalId: primary.signal_id,
|
|
30
|
+
count: dataFlowSignals.length,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function resolveDataFlowSinkLabel(signal: RiskSignalV2): string {
|
|
35
|
+
if (signal.category === "network") {
|
|
36
|
+
return "Network host";
|
|
37
|
+
}
|
|
38
|
+
if (signal.signal_id === "data-flow:clipboard-secret") {
|
|
39
|
+
return "Clipboard";
|
|
40
|
+
}
|
|
41
|
+
if (signal.signal_id === "data-flow:world-readable-temp-secret") {
|
|
42
|
+
return "World-readable temp file";
|
|
43
|
+
}
|
|
44
|
+
if (signal.signal_id === "data-flow:git-remote-token") {
|
|
45
|
+
return "Git remote config";
|
|
46
|
+
}
|
|
47
|
+
return "External sink";
|
|
48
|
+
}
|
|
49
|
+
|
|
8
50
|
export function resolveEnvelopeDisplayText(envelope: GuardActionEnvelope): string | null {
|
|
9
51
|
if (envelope.action_type === "shell_command" && envelope.command !== null) {
|
|
10
52
|
return envelope.command;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SectionLabel } from "./approval-center-primitives";
|
|
2
|
+
import { deriveDataFlowEvidence } from "./approval-center-utils";
|
|
3
|
+
import type { GuardApprovalRequest } from "./guard-types";
|
|
4
|
+
|
|
5
|
+
export function DataFlowEvidenceCard(props: { item: GuardApprovalRequest }) {
|
|
6
|
+
const evidence = deriveDataFlowEvidence(props.item);
|
|
7
|
+
if (evidence === null) return null;
|
|
8
|
+
const extraCount = evidence.count - 1;
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
className="rounded-xl border border-brand-blue/20 bg-brand-blue/[0.04] p-4"
|
|
12
|
+
aria-label="Data flow evidence"
|
|
13
|
+
>
|
|
14
|
+
<SectionLabel>Data flow detected</SectionLabel>
|
|
15
|
+
<div
|
|
16
|
+
className="mt-3 flex flex-wrap items-center gap-2"
|
|
17
|
+
role="group"
|
|
18
|
+
aria-label="Source to sink route"
|
|
19
|
+
>
|
|
20
|
+
<span className="rounded-full bg-brand-purple/10 px-2.5 py-1 text-xs font-medium text-brand-purple">
|
|
21
|
+
{evidence.sourceLabel}
|
|
22
|
+
</span>
|
|
23
|
+
<span className="select-none text-muted-foreground" aria-hidden="true">-></span>
|
|
24
|
+
<span className="rounded-full bg-brand-blue/10 px-2.5 py-1 text-xs font-medium text-brand-blue">
|
|
25
|
+
{evidence.sinkLabel}
|
|
26
|
+
</span>
|
|
27
|
+
</div>
|
|
28
|
+
<p className="mt-2 text-sm leading-relaxed text-brand-dark/80">{evidence.signalTitle}</p>
|
|
29
|
+
<p className="mt-1 font-mono text-[11px] text-muted-foreground">{evidence.signalId}</p>
|
|
30
|
+
{extraCount > 0 ? (
|
|
31
|
+
<p className="mt-1 text-xs text-muted-foreground">
|
|
32
|
+
{`and ${extraCount} more data-flow ${extraCount === 1 ? "signal" : "signals"}`}
|
|
33
|
+
</p>
|
|
34
|
+
) : null}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
resolveDecisionV2Detail,
|
|
9
9
|
resolveDecisionV2Title,
|
|
10
10
|
resolveEnvelopeDisplayText,
|
|
11
|
-
resolveStoppedCommandText
|
|
11
|
+
resolveStoppedCommandText,
|
|
12
|
+
deriveDataFlowEvidence
|
|
12
13
|
} from "./approval-center-utils";
|
|
13
|
-
import type { GuardActionEnvelope, GuardApprovalRequest, GuardDecisionV2 } from "./guard-types";
|
|
14
|
+
import type { GuardActionEnvelope, GuardApprovalRequest, GuardDecisionV2, RiskSignalV2 } from "./guard-types";
|
|
14
15
|
|
|
15
16
|
function assert(condition: boolean, message: string): void {
|
|
16
17
|
if (!condition) {
|
|
@@ -284,3 +285,97 @@ assert(
|
|
|
284
285
|
resolveDecisionV2Detail(requestWithEmptyV2Detail) === null,
|
|
285
286
|
"T082: resolveDecisionV2Detail returns null for empty dashboard_primary_detail"
|
|
286
287
|
);
|
|
288
|
+
|
|
289
|
+
const DATA_FLOW_SIGNAL: RiskSignalV2 = {
|
|
290
|
+
signal_id: "data-flow:exfil-env",
|
|
291
|
+
category: "network",
|
|
292
|
+
severity: "high",
|
|
293
|
+
confidence: "strong",
|
|
294
|
+
detector: "data_flow.exfiltration",
|
|
295
|
+
title: "Secret value sent to remote host",
|
|
296
|
+
plain_reason: "A value from a local credential file was passed to a network request.",
|
|
297
|
+
technical_detail: "source: /home/user/project/.env, sink: https://example.com/collect",
|
|
298
|
+
evidence_ref: "metadata.data_flow_path",
|
|
299
|
+
redaction_level: "redacted",
|
|
300
|
+
false_positive_hint: null,
|
|
301
|
+
advisory_id: null
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
assert(
|
|
305
|
+
deriveDataFlowEvidence(BASE_REQUEST) === null,
|
|
306
|
+
"T090: no data-flow evidence when request has no decision_v2_json"
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
const requestNoDataFlowSignals: GuardApprovalRequest = {
|
|
310
|
+
...BASE_REQUEST,
|
|
311
|
+
decision_v2_json: { ...BASE_DECISION_V2, signals: [BASE_DECISION_V2.signals[0]] }
|
|
312
|
+
};
|
|
313
|
+
assert(
|
|
314
|
+
deriveDataFlowEvidence(requestNoDataFlowSignals) === null,
|
|
315
|
+
"T090: no data-flow evidence when signals contain no data-flow detector or id prefix"
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
const requestWithDetectorSignal: GuardApprovalRequest = {
|
|
319
|
+
...BASE_REQUEST,
|
|
320
|
+
decision_v2_json: { ...BASE_DECISION_V2, signals: [DATA_FLOW_SIGNAL] }
|
|
321
|
+
};
|
|
322
|
+
const detectorEvidence = deriveDataFlowEvidence(requestWithDetectorSignal);
|
|
323
|
+
assert(detectorEvidence !== null, "T091: evidence returned when signal detector is data_flow.exfiltration");
|
|
324
|
+
assert(detectorEvidence?.sourceLabel === "Local secret", "T091: sourceLabel is 'Local secret' for exfiltration signal");
|
|
325
|
+
assert(detectorEvidence?.sinkLabel === "Network host", "T091: sinkLabel is 'Network host' for network category signal");
|
|
326
|
+
|
|
327
|
+
const DATA_FLOW_ID_SIGNAL: RiskSignalV2 = {
|
|
328
|
+
...DATA_FLOW_SIGNAL,
|
|
329
|
+
detector: "guard-risk-v2",
|
|
330
|
+
signal_id: "data-flow:env-to-curl",
|
|
331
|
+
category: "secret",
|
|
332
|
+
title: "Env variable forwarded via shell"
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const requestWithIdPrefixSignal: GuardApprovalRequest = {
|
|
336
|
+
...BASE_REQUEST,
|
|
337
|
+
decision_v2_json: { ...BASE_DECISION_V2, signals: [DATA_FLOW_ID_SIGNAL] }
|
|
338
|
+
};
|
|
339
|
+
const idPrefixEvidence = deriveDataFlowEvidence(requestWithIdPrefixSignal);
|
|
340
|
+
assert(idPrefixEvidence !== null, "T092: evidence returned when signal_id starts with data-flow:");
|
|
341
|
+
assert(idPrefixEvidence?.signalId === "data-flow:env-to-curl", "T092: signalId preserved from signal");
|
|
342
|
+
assert(idPrefixEvidence?.sinkLabel === "External sink", "T092: sinkLabel is 'External sink' for non-network category");
|
|
343
|
+
|
|
344
|
+
const DATA_FLOW_CLIPBOARD_SIGNAL: RiskSignalV2 = {
|
|
345
|
+
...DATA_FLOW_SIGNAL,
|
|
346
|
+
signal_id: "data-flow:clipboard-secret",
|
|
347
|
+
category: "secret",
|
|
348
|
+
title: "Clipboard receives a local secret"
|
|
349
|
+
};
|
|
350
|
+
const requestWithClipboardSignal: GuardApprovalRequest = {
|
|
351
|
+
...BASE_REQUEST,
|
|
352
|
+
decision_v2_json: { ...BASE_DECISION_V2, signals: [DATA_FLOW_CLIPBOARD_SIGNAL] }
|
|
353
|
+
};
|
|
354
|
+
const clipboardEvidence = deriveDataFlowEvidence(requestWithClipboardSignal);
|
|
355
|
+
assert(clipboardEvidence?.sinkLabel === "Clipboard", "T092: sinkLabel names clipboard for clipboard data-flow signal");
|
|
356
|
+
|
|
357
|
+
const detectorEvidenceSummary = deriveDataFlowEvidence(requestWithDetectorSignal);
|
|
358
|
+
assert(
|
|
359
|
+
detectorEvidenceSummary !== null && !detectorEvidenceSummary.sourceLabel.includes(".env"),
|
|
360
|
+
"T093: sourceLabel does not expose raw secret path even if technical_detail mentions .env"
|
|
361
|
+
);
|
|
362
|
+
assert(
|
|
363
|
+
detectorEvidenceSummary !== null && !detectorEvidenceSummary.sinkLabel.includes(".env"),
|
|
364
|
+
"T093: sinkLabel does not expose raw secret path"
|
|
365
|
+
);
|
|
366
|
+
assert(
|
|
367
|
+
detectorEvidenceSummary !== null && !detectorEvidenceSummary.signalTitle.includes("/home/"),
|
|
368
|
+
"T093: signalTitle does not echo raw filesystem paths from technical_detail"
|
|
369
|
+
);
|
|
370
|
+
assert(
|
|
371
|
+
detectorEvidenceSummary !== null && detectorEvidenceSummary.count === 1,
|
|
372
|
+
"T093: count matches number of data-flow signals"
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
const mixedSignals: RiskSignalV2[] = [BASE_DECISION_V2.signals[0], DATA_FLOW_SIGNAL, DATA_FLOW_ID_SIGNAL];
|
|
376
|
+
const requestWithMixedSignals: GuardApprovalRequest = {
|
|
377
|
+
...BASE_REQUEST,
|
|
378
|
+
decision_v2_json: { ...BASE_DECISION_V2, signals: mixedSignals }
|
|
379
|
+
};
|
|
380
|
+
const mixedEvidence = deriveDataFlowEvidence(requestWithMixedSignals);
|
|
381
|
+
assert(mixedEvidence !== null && mixedEvidence.count === 2, "T094: count reflects only data-flow signals, not unrelated ones");
|
|
@@ -444,6 +444,7 @@ export async function fetchSettings(): Promise<GuardSettingsPayload> {
|
|
|
444
444
|
risk_actions: {
|
|
445
445
|
local_secret_read: "require-reapproval",
|
|
446
446
|
credential_exfiltration: "require-reapproval",
|
|
447
|
+
data_flow_exfiltration: "require-reapproval",
|
|
447
448
|
destructive_shell: "require-reapproval",
|
|
448
449
|
encoded_execution: "require-reapproval",
|
|
449
450
|
network_egress: "warn"
|
|
@@ -74,6 +74,11 @@ const riskControls = [
|
|
|
74
74
|
label: "Credential sharing",
|
|
75
75
|
description: "Commands or scripts that appear to send keys, tokens, or credentials away."
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
key: "data_flow_exfiltration",
|
|
79
|
+
label: "Secret data flow",
|
|
80
|
+
description: "Detected source-to-sink route where a local secret is read and its value reaches a network or external sink."
|
|
81
|
+
},
|
|
77
82
|
{
|
|
78
83
|
key: "destructive_shell",
|
|
79
84
|
label: "Destructive commands",
|
|
@@ -97,6 +102,7 @@ const riskProfileActions: Record<"balanced" | "strict" | "custom", Record<RiskKe
|
|
|
97
102
|
balanced: {
|
|
98
103
|
local_secret_read: "require-reapproval",
|
|
99
104
|
credential_exfiltration: "require-reapproval",
|
|
105
|
+
data_flow_exfiltration: "require-reapproval",
|
|
100
106
|
destructive_shell: "require-reapproval",
|
|
101
107
|
encoded_execution: "require-reapproval",
|
|
102
108
|
network_egress: "warn"
|
|
@@ -104,6 +110,7 @@ const riskProfileActions: Record<"balanced" | "strict" | "custom", Record<RiskKe
|
|
|
104
110
|
strict: {
|
|
105
111
|
local_secret_read: "require-reapproval",
|
|
106
112
|
credential_exfiltration: "require-reapproval",
|
|
113
|
+
data_flow_exfiltration: "block",
|
|
107
114
|
destructive_shell: "require-reapproval",
|
|
108
115
|
encoded_execution: "require-reapproval",
|
|
109
116
|
network_egress: "require-reapproval"
|
|
@@ -111,6 +118,7 @@ const riskProfileActions: Record<"balanced" | "strict" | "custom", Record<RiskKe
|
|
|
111
118
|
custom: {
|
|
112
119
|
local_secret_read: "require-reapproval",
|
|
113
120
|
credential_exfiltration: "require-reapproval",
|
|
121
|
+
data_flow_exfiltration: "require-reapproval",
|
|
114
122
|
destructive_shell: "require-reapproval",
|
|
115
123
|
encoded_execution: "require-reapproval",
|
|
116
124
|
network_egress: "warn"
|
|
@@ -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.114"
|
|
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.114"
|
|
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.113 → plugin_scanner-2.0.114}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -70,7 +70,7 @@ from ..mcp_tool_calls import (
|
|
|
70
70
|
evaluate_tool_call,
|
|
71
71
|
)
|
|
72
72
|
from ..models import GuardArtifact, HarnessDetection, PolicyDecision
|
|
73
|
-
from ..policy.engine import SAFE_CHANGED_HASH_ACTION, VALID_GUARD_ACTIONS
|
|
73
|
+
from ..policy.engine import SAFE_CHANGED_HASH_ACTION, VALID_GUARD_ACTIONS, build_decision_v2
|
|
74
74
|
from ..protect import build_protect_payload
|
|
75
75
|
from ..proxy import (
|
|
76
76
|
CodexMcpGuardProxy,
|
|
@@ -80,8 +80,9 @@ from ..proxy import (
|
|
|
80
80
|
StdioGuardProxy,
|
|
81
81
|
)
|
|
82
82
|
from ..receipts import build_receipt
|
|
83
|
-
from ..risk import artifact_risk_signals, artifact_risk_summary
|
|
83
|
+
from ..risk import artifact_risk_signals, artifact_risk_signals_v2, artifact_risk_summary
|
|
84
84
|
from ..runtime.actions import GuardActionEnvelope, normalize_harness_payload
|
|
85
|
+
from ..runtime.data_flow_rules import detect_data_flow_exfiltration
|
|
85
86
|
from ..runtime.runner import (
|
|
86
87
|
GuardSyncNotConfiguredError,
|
|
87
88
|
extract_prompt_requests,
|
|
@@ -103,6 +104,7 @@ from ..runtime.secret_sensitivity import (
|
|
|
103
104
|
classify_secret_content,
|
|
104
105
|
classify_secret_path,
|
|
105
106
|
)
|
|
107
|
+
from ..runtime.signals import RiskSignalV2
|
|
106
108
|
from ..runtime.surface_server import GuardSurfaceRuntime
|
|
107
109
|
from ..store import GuardStore
|
|
108
110
|
from .approval_commands import add_approval_parser, run_approval_command
|
|
@@ -1547,11 +1549,12 @@ def run_guard_command(
|
|
|
1547
1549
|
artifact_hash=artifact_hash(legacy_artifact),
|
|
1548
1550
|
workspace=str(runtime_workspace) if runtime_workspace else None,
|
|
1549
1551
|
)
|
|
1550
|
-
|
|
1552
|
+
requested_policy_action = _coalesce_string(
|
|
1551
1553
|
getattr(args, "policy_action", None),
|
|
1552
1554
|
stored_policy_action,
|
|
1553
1555
|
payload.get("policy_action"),
|
|
1554
1556
|
)
|
|
1557
|
+
policy_action = requested_policy_action
|
|
1555
1558
|
if policy_action not in VALID_GUARD_ACTIONS:
|
|
1556
1559
|
policy_action = _runtime_artifact_policy_action(config, runtime_artifact, args.harness)
|
|
1557
1560
|
if _canonical_harness_name(args.harness) == "claude-code" and event_name in {
|
|
@@ -1582,8 +1585,27 @@ def run_guard_command(
|
|
|
1582
1585
|
store.add_receipt(receipt)
|
|
1583
1586
|
return 0
|
|
1584
1587
|
changed_capabilities = [runtime_artifact.artifact_type]
|
|
1585
|
-
|
|
1586
|
-
|
|
1588
|
+
data_flow_signals = _runtime_action_data_flow_signals(action_envelope, workspace=runtime_workspace)
|
|
1589
|
+
if data_flow_signals and requested_policy_action not in VALID_GUARD_ACTIONS:
|
|
1590
|
+
data_flow_action = resolve_risk_action(
|
|
1591
|
+
config,
|
|
1592
|
+
"data_flow_exfiltration",
|
|
1593
|
+
harness=policy_harness,
|
|
1594
|
+
)
|
|
1595
|
+
if _guard_action_severity(data_flow_action) > _guard_action_severity(policy_action):
|
|
1596
|
+
policy_action = data_flow_action
|
|
1597
|
+
decision_signals = data_flow_signals or artifact_risk_signals_v2(runtime_artifact)
|
|
1598
|
+
risk_signals = (
|
|
1599
|
+
[signal.plain_reason for signal in data_flow_signals]
|
|
1600
|
+
if data_flow_signals
|
|
1601
|
+
else list(artifact_risk_signals(runtime_artifact))
|
|
1602
|
+
)
|
|
1603
|
+
risk_summary = (
|
|
1604
|
+
_runtime_data_flow_summary(data_flow_signals)
|
|
1605
|
+
if data_flow_signals
|
|
1606
|
+
else artifact_risk_summary(runtime_artifact)
|
|
1607
|
+
)
|
|
1608
|
+
decision_v2 = build_decision_v2(policy_action, reason=policy_action, signals=decision_signals)
|
|
1587
1609
|
incident = build_incident_context(
|
|
1588
1610
|
harness=args.harness,
|
|
1589
1611
|
artifact=runtime_artifact,
|
|
@@ -1619,6 +1641,7 @@ def run_guard_command(
|
|
|
1619
1641
|
"policy_action": policy_action,
|
|
1620
1642
|
"risk_signals": risk_signals,
|
|
1621
1643
|
"risk_summary": risk_summary,
|
|
1644
|
+
"decision_v2_json": decision_v2.to_dict(),
|
|
1622
1645
|
"artifact_label": incident["artifact_label"],
|
|
1623
1646
|
"source_label": incident["source_label"],
|
|
1624
1647
|
"trigger_summary": incident["trigger_summary"],
|
|
@@ -1703,6 +1726,7 @@ def run_guard_command(
|
|
|
1703
1726
|
"config_path": runtime_artifact.config_path,
|
|
1704
1727
|
"launch_target": _runtime_request_summary(runtime_artifact),
|
|
1705
1728
|
"action_envelope_json": _action_envelope_json(action_envelope),
|
|
1729
|
+
"decision_v2_json": decision_v2.to_dict(),
|
|
1706
1730
|
}
|
|
1707
1731
|
]
|
|
1708
1732
|
}
|
|
@@ -3045,6 +3069,36 @@ def _runtime_artifact_guard_default_action(artifact: GuardArtifact) -> str | Non
|
|
|
3045
3069
|
return None
|
|
3046
3070
|
|
|
3047
3071
|
|
|
3072
|
+
def _runtime_action_data_flow_signals(
|
|
3073
|
+
action_envelope: GuardActionEnvelope | None,
|
|
3074
|
+
*,
|
|
3075
|
+
workspace: Path | None,
|
|
3076
|
+
) -> tuple[RiskSignalV2, ...]:
|
|
3077
|
+
if action_envelope is None:
|
|
3078
|
+
return ()
|
|
3079
|
+
return detect_data_flow_exfiltration(action_envelope, workspace=workspace)
|
|
3080
|
+
|
|
3081
|
+
|
|
3082
|
+
def _runtime_data_flow_summary(signals: tuple[RiskSignalV2, ...]) -> str:
|
|
3083
|
+
sink_type = _runtime_data_flow_sink_type(signals)
|
|
3084
|
+
if signals:
|
|
3085
|
+
return f"This command sends local secret to {sink_type}. Guard kept raw secret contents out of the evidence."
|
|
3086
|
+
return f"This command sends local secret to {sink_type}."
|
|
3087
|
+
|
|
3088
|
+
|
|
3089
|
+
def _runtime_data_flow_sink_type(signals: tuple[RiskSignalV2, ...]) -> str:
|
|
3090
|
+
signal_ids = {signal.signal_id for signal in signals}
|
|
3091
|
+
if any(signal.category == "network" for signal in signals):
|
|
3092
|
+
return "network host"
|
|
3093
|
+
if "data-flow:clipboard-secret" in signal_ids:
|
|
3094
|
+
return "clipboard"
|
|
3095
|
+
if "data-flow:world-readable-temp-secret" in signal_ids:
|
|
3096
|
+
return "world-readable temp file"
|
|
3097
|
+
if "data-flow:git-remote-token" in signal_ids:
|
|
3098
|
+
return "git remote configuration"
|
|
3099
|
+
return "external sink"
|
|
3100
|
+
|
|
3101
|
+
|
|
3048
3102
|
def _guard_action_severity(action: str) -> int:
|
|
3049
3103
|
return {
|
|
3050
3104
|
"allow": 0,
|
|
@@ -3077,7 +3131,11 @@ def _runtime_artifact_risk_classes(artifact: GuardArtifact) -> list[str]:
|
|
|
3077
3131
|
if not isinstance(action_class, str):
|
|
3078
3132
|
return []
|
|
3079
3133
|
action_risk_classes = {
|
|
3080
|
-
"credential exfiltration shell command": [
|
|
3134
|
+
"credential exfiltration shell command": [
|
|
3135
|
+
"data_flow_exfiltration",
|
|
3136
|
+
"credential_exfiltration",
|
|
3137
|
+
"network_egress",
|
|
3138
|
+
],
|
|
3081
3139
|
"docker-sensitive command": ["network_egress", "destructive_shell"],
|
|
3082
3140
|
"docker client config access": ["local_secret_read"],
|
|
3083
3141
|
"encoded or encrypted shell command": ["encoded_execution"],
|
|
@@ -3200,7 +3258,7 @@ def _native_prompt_context(artifact: GuardArtifact) -> str:
|
|
|
3200
3258
|
|
|
3201
3259
|
def _runtime_artifact_native_reason(artifact: GuardArtifact, response_payload: dict[str, object]) -> str:
|
|
3202
3260
|
decision_message = _decision_v2_harness_message(response_payload)
|
|
3203
|
-
if decision_message is not None:
|
|
3261
|
+
if decision_message is not None and _should_use_decision_v2_harness_message(response_payload, decision_message):
|
|
3204
3262
|
return decision_message
|
|
3205
3263
|
if artifact.artifact_type == "prompt_request":
|
|
3206
3264
|
harness = response_payload.get("harness")
|
|
@@ -3261,6 +3319,37 @@ def _decision_v2_harness_message(response_payload: dict[str, object]) -> str | N
|
|
|
3261
3319
|
return None
|
|
3262
3320
|
|
|
3263
3321
|
|
|
3322
|
+
def _decision_v2_has_data_flow_signal(response_payload: dict[str, object]) -> bool:
|
|
3323
|
+
decision_v2 = response_payload.get("decision_v2_json")
|
|
3324
|
+
if not isinstance(decision_v2, Mapping):
|
|
3325
|
+
return False
|
|
3326
|
+
signals = decision_v2.get("signals")
|
|
3327
|
+
if not isinstance(signals, list):
|
|
3328
|
+
return False
|
|
3329
|
+
for item in signals:
|
|
3330
|
+
if not isinstance(item, Mapping):
|
|
3331
|
+
continue
|
|
3332
|
+
detector = item.get("detector")
|
|
3333
|
+
signal_id = item.get("signal_id")
|
|
3334
|
+
if detector == "data_flow.exfiltration":
|
|
3335
|
+
return True
|
|
3336
|
+
if isinstance(signal_id, str) and signal_id.startswith("data-flow:"):
|
|
3337
|
+
return True
|
|
3338
|
+
return False
|
|
3339
|
+
|
|
3340
|
+
|
|
3341
|
+
def _should_use_decision_v2_harness_message(response_payload: dict[str, object], message: str) -> bool:
|
|
3342
|
+
if _decision_v2_has_data_flow_signal(response_payload):
|
|
3343
|
+
return True
|
|
3344
|
+
generic_messages = {
|
|
3345
|
+
"HOL Guard blocked this action.",
|
|
3346
|
+
"HOL Guard wants this action reviewed and run in a sandboxed path.",
|
|
3347
|
+
}
|
|
3348
|
+
if message in generic_messages:
|
|
3349
|
+
return False
|
|
3350
|
+
return not message.startswith("HOL Guard needs a fresh approval because this action changed.")
|
|
3351
|
+
|
|
3352
|
+
|
|
3264
3353
|
def _claude_prompt_additional_context(
|
|
3265
3354
|
*,
|
|
3266
3355
|
harness: str,
|
|
@@ -37,6 +37,7 @@ VALID_SECURITY_LEVELS = {"balanced", "strict", "custom"}
|
|
|
37
37
|
VALID_RISK_ACTION_KEYS = {
|
|
38
38
|
"local_secret_read",
|
|
39
39
|
"credential_exfiltration",
|
|
40
|
+
"data_flow_exfiltration",
|
|
40
41
|
"destructive_shell",
|
|
41
42
|
"encoded_execution",
|
|
42
43
|
"network_egress",
|
|
@@ -46,6 +47,7 @@ SECURITY_LEVEL_RISK_ACTIONS: dict[str, dict[str, GuardAction]] = {
|
|
|
46
47
|
"balanced": {
|
|
47
48
|
"local_secret_read": "require-reapproval",
|
|
48
49
|
"credential_exfiltration": "require-reapproval",
|
|
50
|
+
"data_flow_exfiltration": "require-reapproval",
|
|
49
51
|
"destructive_shell": "require-reapproval",
|
|
50
52
|
"encoded_execution": "require-reapproval",
|
|
51
53
|
"network_egress": "warn",
|
|
@@ -53,6 +55,7 @@ SECURITY_LEVEL_RISK_ACTIONS: dict[str, dict[str, GuardAction]] = {
|
|
|
53
55
|
"strict": {
|
|
54
56
|
"local_secret_read": "require-reapproval",
|
|
55
57
|
"credential_exfiltration": "require-reapproval",
|
|
58
|
+
"data_flow_exfiltration": "block",
|
|
56
59
|
"destructive_shell": "require-reapproval",
|
|
57
60
|
"encoded_execution": "require-reapproval",
|
|
58
61
|
"network_egress": "require-reapproval",
|
|
@@ -60,6 +63,7 @@ SECURITY_LEVEL_RISK_ACTIONS: dict[str, dict[str, GuardAction]] = {
|
|
|
60
63
|
"custom": {
|
|
61
64
|
"local_secret_read": "require-reapproval",
|
|
62
65
|
"credential_exfiltration": "require-reapproval",
|
|
66
|
+
"data_flow_exfiltration": "require-reapproval",
|
|
63
67
|
"destructive_shell": "require-reapproval",
|
|
64
68
|
"encoded_execution": "require-reapproval",
|
|
65
69
|
"network_egress": "warn",
|