SafeAI-Static-Analyzer 2.2.1__tar.gz → 2.4.0__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.
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/PKG-INFO +103 -7
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/README.md +102 -6
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/PKG-INFO +103 -7
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/SOURCES.txt +19 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/pyproject.toml +4 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/capability_diff.py +228 -2
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/component_graph.py +34 -0
- safeai_static_analyzer-2.4.0/safeai/analyzers/__init__.py +169 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/capability/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/claude_code/analyzer.py +2 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/data_leakage/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/dataflow/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/env_dependency/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/governance/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/mcp/analyzer.py +2 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/model_config/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/prompt/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/prompt_file/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/skill/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/tool_def/analyzer.py +2 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/workflow/analyzer.py +3 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/cmd/cli.py +144 -1
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/cmd/postprocess.py +110 -4
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/cmd/registry_cli.py +38 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/engine/file_discovery.py +12 -2
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/engine/orchestrator.py +53 -34
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/__init__.py +26 -1
- safeai_static_analyzer-2.4.0/safeai/frameworks/copilot/parser.py +184 -0
- safeai_static_analyzer-2.4.0/safeai/frameworks/openclaw/parser.py +172 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/__init__.py +1 -1
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/contract.py +48 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/enrich.py +66 -1
- safeai_static_analyzer-2.4.0/safeai/kya/exceptions.py +264 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/exporter.py +18 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/importer.py +50 -1
- safeai_static_analyzer-2.4.0/safeai/kya/lockfile.py +128 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/manifest.py +69 -2
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/policy.py +157 -10
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/registry/persist.py +13 -4
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/registry/schema.py +24 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/html.py +160 -1
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/pr_comment.py +76 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/terminal.py +10 -0
- safeai_static_analyzer-2.4.0/safeai/rules/pack_test.py +152 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/scorecard.py +1 -1
- safeai_static_analyzer-2.4.0/safeai/scoring/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/version.py +1 -1
- safeai_static_analyzer-2.4.0/tests/test_architectural_invariants.py +236 -0
- safeai_static_analyzer-2.4.0/tests/test_architecture_diagram.py +291 -0
- safeai_static_analyzer-2.4.0/tests/test_authority_change.py +318 -0
- safeai_static_analyzer-2.4.0/tests/test_baseline_compat.py +66 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_benchmarks.py +2 -2
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_capability_diff_v2.py +1 -1
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_compatibility.py +62 -0
- safeai_static_analyzer-2.4.0/tests/test_config_adapters.py +192 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_dco.py +8 -0
- safeai_static_analyzer-2.4.0/tests/test_evidence_contract_v7.py +335 -0
- safeai_static_analyzer-2.4.0/tests/test_exceptions.py +284 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_github_action.py +2 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_html_report.py +26 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_manifest_integrity.py +50 -0
- safeai_static_analyzer-2.4.0/tests/test_plugin_sdk.py +489 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_policy.py +154 -6
- safeai_static_analyzer-2.4.0/tests/test_pr_paths.py +163 -0
- safeai_static_analyzer-2.4.0/tests/test_release_workflow.py +114 -0
- safeai_static_analyzer-2.4.0/tests/test_scan_framework.py +374 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_scorecard.py +2 -2
- safeai_static_analyzer-2.4.0/tests/test_unknown_authority.py +175 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/LICENSE +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/dependency_links.txt +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/entry_points.txt +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/requires.txt +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/SafeAI_Static_Analyzer.egg-info/top_level.txt +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/__main__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/aggregation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/capabilities.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/component_diff.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/components.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/dependency_correlation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/escalation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/escalation_remediation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/import_graph.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/project_graph.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/semantic.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/target_taxonomy.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/tool_identity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/tool_implementation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analysis/tool_surface.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers → safeai_static_analyzer-2.4.0/safeai/analyzers/capability}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/claude_code/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/capability → safeai_static_analyzer-2.4.0/safeai/analyzers/data_leakage}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/dataflow/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/env_dependency/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/governance/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/data_leakage → safeai_static_analyzer-2.4.0/safeai/analyzers/mcp}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/mcp/compatibility.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/mcp/schema.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/analyzers/mcp/validators.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/mcp → safeai_static_analyzer-2.4.0/safeai/analyzers/model_config}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/model_config → safeai_static_analyzer-2.4.0/safeai/analyzers/prompt}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/prompt → safeai_static_analyzer-2.4.0/safeai/analyzers/prompt_file}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/prompt_file → safeai_static_analyzer-2.4.0/safeai/analyzers/skill}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/skill → safeai_static_analyzer-2.4.0/safeai/analyzers/tool_def}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/tool_def → safeai_static_analyzer-2.4.0/safeai/analyzers/workflow}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/analyzers/workflow → safeai_static_analyzer-2.4.0/safeai/cmd}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/cmd/manifest_cli.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/controls/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/controls/catalogs.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/controls/mappings.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/cmd → safeai_static_analyzer-2.4.0/safeai/engine}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/engine/metadata.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/engine/scan.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/autogen/parser.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/engine → safeai_static_analyzer-2.4.0/safeai/frameworks/azure_foundry}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/azure_foundry/parser.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/frameworks/azure_foundry → safeai_static_analyzer-2.4.0/safeai/frameworks/bedrock_agent}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/bedrock_agent/parser.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/frameworks/bedrock_agent → safeai_static_analyzer-2.4.0/safeai/frameworks/claude_code}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/claude_code/commands.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/claude_code/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/claude_code/permissions.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/claude_code/settings.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/frameworks/claude_code → safeai_static_analyzer-2.4.0/safeai/frameworks/copilot}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/crewai/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/crewai/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/cursorrules/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/cursorrules/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/dify/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/dify/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/google_adk/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/google_adk/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/haystack/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/haystack/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/langchain/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/langchain/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/langgraph/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/langgraph/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/llamaindex/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/llamaindex/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/mastra/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/mastra/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/microsoft_agent/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/microsoft_agent/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/n8n/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/n8n/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/openai_agents/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/openai_agents/parser.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/frameworks/semantic_kernel → safeai_static_analyzer-2.4.0/safeai/frameworks/openclaw}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/frameworks/windsurf → safeai_static_analyzer-2.4.0/safeai/frameworks/semantic_kernel}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/semantic_kernel/parser.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/report → safeai_static_analyzer-2.4.0/safeai/frameworks/windsurf}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/frameworks/windsurf/parser.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/assurance.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/baseline.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/ci_context.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/fingerprints.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/identity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/integrity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/registry/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/registry/connection.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/registry/queries.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/suppressions.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/kya/util.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/rules → safeai_static_analyzer-2.4.0/safeai/report}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/failure_matrix.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/html_kit.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/json_report.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/registry_html.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/report/sarif.py +0 -0
- {safeai_static_analyzer-2.2.1/safeai/scoring → safeai_static_analyzer-2.4.0/safeai/rules}/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/rules/base_rules.yaml +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/rules/loader.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/scoring/engine.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/severity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/telemetry/__init__.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/telemetry/client.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/telemetry/config.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/safeai/telemetry/schema.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/setup.cfg +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_adapter_dataflow.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_assurance.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_baseline.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_capability_detection.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_ci_context.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_claude_code_deep.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_component_graph.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_component_hash.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_confidence_arbitration.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_control_mappings.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_crewai_framework.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_cursorrules_framework.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_env_dependency.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_escalation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_escalation_remediation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_evidence_type.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_fingerprints.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_governance_analyzer.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_init_and_rules.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_kya_integration.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_kya_manifest.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_langgraph_framework.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_llamaindex_framework.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_manifest_contract.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_mcp_tool_poisoning.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_mcp_validation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_n8n_workflow.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_parser_aggregation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_phase15.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_pr_comment.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_pr_comment_cli.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_quality_gates.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_registry.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_registry_cli.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_registry_html.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_regression_fixtures.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_release_assets.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_release_fixes.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_release_validation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_rules_loader_determinism.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_sarif.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_scan_phase11.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_scoring.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_semantic.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_severity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_suppressions.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_target_taxonomy_engine.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_telemetry.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_tool_identity.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_tool_implementation.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_version.py +0 -0
- {safeai_static_analyzer-2.2.1 → safeai_static_analyzer-2.4.0}/tests/test_windsurf_framework.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SafeAI-Static-Analyzer
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: The lightweight, open-source Static AI Capability & Risk Analyzer for CI/CD pipelines.
|
|
5
5
|
Author: IkarusCareer
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -31,17 +31,29 @@ Provides-Extra: standalone
|
|
|
31
31
|
Requires-Dist: pyinstaller>=6.0; extra == "standalone"
|
|
32
32
|
Dynamic: license-file
|
|
33
33
|
|
|
34
|
-
# SafeAI —
|
|
34
|
+
# SafeAI — Agent Authority Security for the Software Supply Chain
|
|
35
35
|
|
|
36
36
|
[](https://github.com/ikaruscareer/SafeAI/actions/workflows/ci.yml)
|
|
37
37
|
[](https://scorecard.dev/viewer/?uri=github.com/ikaruscareer/SafeAI)
|
|
38
38
|
[](https://safeai-analyzer.ikaruscareer.com)
|
|
39
|
-
[](https://github.com/ikaruscareer/SafeAI/releases/tag/v2.3.0)
|
|
40
40
|
[](https://www.bestpractices.dev/en/projects/14126)
|
|
41
41
|
|
|
42
42
|
Enjoying SafeAI? A ⭐ on [GitHub](https://github.com/ikaruscareer/SafeAI) helps more security teams find it.
|
|
43
43
|
|
|
44
|
-
**
|
|
44
|
+
**Know what your AI agent can do before you deploy it.**
|
|
45
|
+
|
|
46
|
+
**SafeAI** statically maps agent capabilities, tools, MCP integrations, and authority changes, then turns material changes into explainable CI/CD security decisions and portable evidence. Technically, SafeAI is a *Static AI Capability & Risk Analyzer*: it scans AI application source code for security risks, capability exposure, and governance gaps. It is offline and source-private by default — it never executes agents or calls LLMs, and network activity occurs only through explicitly enabled integration commands (currently only `--pr-comment-post`). It integrates into CI/CD pipelines.
|
|
47
|
+
|
|
48
|
+
**Three pillars — DISCOVER / COMPARE / GOVERN:**
|
|
49
|
+
|
|
50
|
+
| Pillar | Question | What SafeAI does |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| **DISCOVER** | What can the agent access? | Builds an evidence-backed model of agent authority: tools, MCP servers, filesystem, shell, databases, APIs, destinations, memory, delegation, autonomy, approval controls |
|
|
53
|
+
| **COMPARE** | What changed? | Diffs authority against the approved baseline: new tools, `read → write` widening, new destinations, removed approval gates |
|
|
54
|
+
| **GOVERN** | Should that change be allowed? | Deterministic CI/CD decisions — `pass`, `review-required`, `block`, `accepted-exception` — with evidence, never an opaque score |
|
|
55
|
+
|
|
56
|
+
> SafeAI is not a runtime guardrail and does not certify an agent as safe. It provides source-first, evidence-backed visibility into agent authority and meaningful changes *before deployment*.
|
|
45
57
|
|
|
46
58
|
> 🌐 [safeai-analyzer.ikaruscareer.com](https://safeai-analyzer.ikaruscareer.com) — project landing page
|
|
47
59
|
|
|
@@ -75,6 +87,65 @@ Designed to be lightweight, explainable, and community-driven, SafeAI aims to be
|
|
|
75
87
|
|
|
76
88
|
SafeAI sits before runtime guardrails and red-teaming tools in the security lifecycle. It scans agent source code at commit time — detecting framework-specific capabilities, MCP misconfigurations, and prompt injection patterns — before you ever deploy an agent to staging. It does not replace runtime tools (Microsoft AGT), evaluation frameworks (LangSmith, DeepEval), or red-teaming scanners (Promptfoo, Garak). It complements them: find the risk in code first, then validate at runtime.
|
|
77
89
|
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Example: authority-change report
|
|
93
|
+
|
|
94
|
+
*SafeAI's most important security event is not simply that a finding exists. It is that an agent's effective authority materially changes.*
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Agent: customer-support-agent Baseline: release v2.4.0 (approved)
|
|
98
|
+
|
|
99
|
+
AUTHORITY CHANGE (material)
|
|
100
|
+
+ tool: crm_update
|
|
101
|
+
+ capability: database write
|
|
102
|
+
+ destination: production CRM
|
|
103
|
+
+ access: read → write
|
|
104
|
+
- human approval gate (GOV_APPROVAL_MISSING)
|
|
105
|
+
|
|
106
|
+
Policy decision: BLOCK
|
|
107
|
+
Reason: production write authority was added without an approved
|
|
108
|
+
exception or required approval control.
|
|
109
|
+
Evidence: source files · tool definition · baseline manifest ·
|
|
110
|
+
current manifest · policy profile · SafeAI version ·
|
|
111
|
+
ruleset version · commit SHA
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The reviewer learns *what the agent can now do that it could not do
|
|
115
|
+
before* — and the decision cites evidence, not a score.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Agent Authority Model
|
|
120
|
+
|
|
121
|
+
SafeAI builds an analytical model — not an observation of runtime
|
|
122
|
+
permissions — of what an agent is empowered to do:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Agent
|
|
126
|
+
→ Tool / MCP Server / Skill / Workflow Node
|
|
127
|
+
→ Capability
|
|
128
|
+
→ Access Mode (none < read < write < mutate < execute)
|
|
129
|
+
→ Data / Destination / Resource
|
|
130
|
+
→ Authority
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Every authority statement carries a class: **declared** (config says so),
|
|
134
|
+
**detected** (code shows it), **inferred** (heuristic, confidence-labelled),
|
|
135
|
+
**repository/IaC-observed** (in-repo infrastructure grants), or
|
|
136
|
+
**unknown**. Runtime-granted authority (live IAM, deployed network policy,
|
|
137
|
+
runtime identity) is explicitly **unknown** to the static scanner —
|
|
138
|
+
*unknown is an evidence state, not evidence of safety*, and SafeAI never
|
|
139
|
+
converts it into a pass.
|
|
140
|
+
|
|
141
|
+
**What decisions mean.** `pass` means no configured deterministic gate
|
|
142
|
+
triggered — never "the agent is safe." `unknown` means unattributable
|
|
143
|
+
evidence — never "no risk detected." Organizations can govern unknown
|
|
144
|
+
authority explicitly (`authority.unknown` policy, `--unknown-authority`),
|
|
145
|
+
but the default leaves it visible and unfailed.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
78
149
|
<img width="1024" height="1024" alt="SafeAI_Concept" src="https://github.com/user-attachments/assets/c07999b2-79d5-4200-9eec-ce1ab4e63cc8" />
|
|
79
150
|
|
|
80
151
|
|
|
@@ -84,7 +155,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
84
155
|
|
|
85
156
|
| Feature | Description |
|
|
86
157
|
|---------|-------------|
|
|
87
|
-
| **Framework Detection** | Detects and parses
|
|
158
|
+
| **Framework Detection** | Detects and parses 19 AI agent frameworks (AST + config + regex, no mutual exclusion) |
|
|
88
159
|
| **Tool Identity & Access Modes** | Capabilities attributed to named tools (agent / MCP server / skill / tool / workflow node) on an access scale `none < read < write < mutate < execute`; inferred modes are flagged, never overstated |
|
|
89
160
|
| **Capability Discovery** | Maps 19 capability categories (shell, filesystem, network, database, memory, MCP, ...) with evidence, confidence, and provenance |
|
|
90
161
|
| **Capability Escalation Detection** | Per-tool authority diffs between scans (new shell, read→write widening, new MCP server, removed approval gate, ...) — 14 rules, including gating-aware subsumption |
|
|
@@ -101,7 +172,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
101
172
|
| **Baseline & Escalation Gating** | `--fail-on-new` for new/regressed findings, `--fail-on-escalation` for authority changes, `--pr-comment` PR summaries |
|
|
102
173
|
| **Policy-as-Code & Suppressions** | `allow`/`warn`/`require_review`/`deny` policy with selectors; required-reason suppressions |
|
|
103
174
|
| **Assurance Boundary** | Every scan states exactly what it did and could not verify — never a fixed disclaimer |
|
|
104
|
-
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome;
|
|
175
|
+
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome; informational unless you opt into `--scorecard-fail-under` gating — evidence and policy decide, the score does not |
|
|
105
176
|
| **CI/CD Integration** | SARIF 2.1.0 output, exit codes, GitHub Actions **Marketplace action** and workflow included |
|
|
106
177
|
| **Community Scan** | Governed private-pilot workflow for scanning public third-party agent frameworks with responsible disclosure (`community-scans/`) — private by default, human-reviewed before any publication |
|
|
107
178
|
| **Multi-Format Reports** | Terminal, JSON, SARIF 2.1.0, HTML, canonical KYA manifest, PR comment, Security Scorecard |
|
|
@@ -170,6 +241,8 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
170
241
|
| n8n | ✔ | Partial | Minimal | Minimal | Experimental |
|
|
171
242
|
| Cursor (.cursorrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
172
243
|
| Windsurf (.windsurfrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
244
|
+
| OpenClaw config | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
245
|
+
| GitHub Copilot instructions | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
173
246
|
|
|
174
247
|
|
|
175
248
|
### Framework Support Details
|
|
@@ -194,6 +267,12 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
194
267
|
- **Cursor (.cursorrules)** — detects declared tools/permissions and
|
|
195
268
|
capability-relevant keywords (shell, filesystem, HTTP, database) in the
|
|
196
269
|
IDE's rules config, JSON, YAML, or free text
|
|
270
|
+
- **Windsurf (.windsurfrules)** — detects declared tools, models, and
|
|
271
|
+
capability-relevant keywords in JSON, YAML, or free-text rules
|
|
272
|
+
- **OpenClaw config** — detects JSON/YAML files under `.openclaw/` and
|
|
273
|
+
`.openclaw.yaml`, including declared tools, models, and MCP servers
|
|
274
|
+
- **GitHub Copilot instructions** — detects repository instruction Markdown,
|
|
275
|
+
YAML frontmatter, and `.copilot/*.yml` tool or permission grants
|
|
197
276
|
|
|
198
277
|
Maturity is on the scale defined in [`docs/reference/FRAMEWORK_SUPPORT.md`](docs/reference/FRAMEWORK_SUPPORT.md):
|
|
199
278
|
**Partial** = reliable detection and discovery with capability/risk analysis over
|
|
@@ -211,6 +290,8 @@ Representative test fixtures and validation tests for framework detection:
|
|
|
211
290
|
| LlamaIndex | `test_llamaindex_framework.py` | `fixtures/llamaindex/representative/agent.py` | @adnqcr7-code [#61] |
|
|
212
291
|
| CrewAI | `test_crewai_framework.py` | `fixtures/crewai/representative/crew.py` | @adnqcr7-code [#62] |
|
|
213
292
|
| Claude Code | `test_claude_code_deep.py` | `fixtures/claude_code/compatibility/` | @adnqcr7-code [#59] |
|
|
293
|
+
| OpenClaw config | `test_config_adapters.py` | `fixtures/openclaw/representative/.openclaw/config.json` | @YaoSong808 [#159] |
|
|
294
|
+
| GitHub Copilot instructions | `test_config_adapters.py` | `fixtures/copilot/representative/.github/copilot-instructions.md` | @YaoSong808 [#159] |
|
|
214
295
|
|
|
215
296
|
---
|
|
216
297
|
|
|
@@ -302,6 +383,16 @@ to a shared path, or use `--no-registry` for ephemeral scans.
|
|
|
302
383
|
- Python 3.11, 3.12, or 3.13
|
|
303
384
|
- PyYAML (for YAML configuration parsing)
|
|
304
385
|
|
|
386
|
+
### Install from PyPI (recommended)
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
pip install SafeAI-Static-Analyzer
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Unpinned on purpose — this always resolves to the latest stable
|
|
393
|
+
release (see [releases](https://github.com/ikaruscareer/SafeAI/releases)).
|
|
394
|
+
Verify the download with [`docs/reference/VERIFICATION.md`](docs/reference/VERIFICATION.md).
|
|
395
|
+
|
|
305
396
|
### Install from source
|
|
306
397
|
|
|
307
398
|
```bash
|
|
@@ -343,6 +434,7 @@ python -m safeai registry <subcommand> [options]
|
|
|
343
434
|
| `--json` | — | JSON output path |
|
|
344
435
|
| `--html` | — | HTML report output path |
|
|
345
436
|
| `--manifest` | — | Canonical KYA manifest output path (`safeai-manifest.json`) |
|
|
437
|
+
| `--digest-file` | — | With `--manifest`: write `<canonical-sha256> <manifest-basename>` to this path. The digest is the one `safeai manifest verify` reports, not a raw file hash, so it is not `sha256sum -c` compatible |
|
|
346
438
|
| `--baseline` | — | Prior manifest/report for new/existing comparison |
|
|
347
439
|
| `--fail-on-new` | off | With `--baseline`: fail only on new/regressed findings |
|
|
348
440
|
| `--policy` | `.safeai/policy.yml` | Policy-as-code YAML file |
|
|
@@ -450,7 +542,7 @@ jobs:
|
|
|
450
542
|
- uses: actions/checkout@v4
|
|
451
543
|
- uses: actions/setup-python@v5
|
|
452
544
|
with: { python-version: '3.12' }
|
|
453
|
-
- uses: ikaruscareer/SafeAI@
|
|
545
|
+
- uses: ikaruscareer/SafeAI@v2
|
|
454
546
|
with: { path: '.', fail-on: critical }
|
|
455
547
|
- uses: github/codeql-action/upload-sarif@v3
|
|
456
548
|
if: always()
|
|
@@ -504,9 +596,13 @@ contributors who have helped make AI safer:
|
|
|
504
596
|
| [@hadbiaghiles](https://github.com/hadbiaghiles) | AutoGen framework documentation |
|
|
505
597
|
| [@D05TL3](https://github.com/D05TL3) | GitHub Actions scanning example |
|
|
506
598
|
| [@mikemikimike](https://github.com/mikemikimike) | Adapter negative detection tests |
|
|
599
|
+
| [@burakeyler](https://github.com/burakeyler) | `--digest-file` manifest digest sidecar (PR #148) |
|
|
600
|
+
| [@YaoSong808](https://github.com/YaoSong808) | OpenClaw and GitHub Copilot config-file adapters (PR #159) |
|
|
507
601
|
| [@mah](https://github.com/mahirhir) | Claude Code deep analysis documentation |
|
|
508
602
|
| [@asarakhatun17-lgtm](https://github.com/asarakhatun17-lgtm) | Supported frameworks consistency fix |
|
|
509
603
|
| [@yugaaank](https://github.com/yugaaank) | Capability detectors (Docker, Kubernetes, Redis, S3, GCP, Slack, Jira, browser) |
|
|
604
|
+
| [@Teachmeplaycode](https://github.com/Teachmeplaycode) | Benchmark corpus expansion, static subprocess precision gap documentation (PR #174) |
|
|
605
|
+
| [@nikitajos7](https://github.com/nikitajos7) | Policy profile display in terminal and HTML reports (PR #175) |
|
|
510
606
|
|
|
511
607
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
512
608
|
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
# SafeAI —
|
|
1
|
+
# SafeAI — Agent Authority Security for the Software Supply Chain
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ikaruscareer/SafeAI/actions/workflows/ci.yml)
|
|
4
4
|
[](https://scorecard.dev/viewer/?uri=github.com/ikaruscareer/SafeAI)
|
|
5
5
|
[](https://safeai-analyzer.ikaruscareer.com)
|
|
6
|
-
[](https://github.com/ikaruscareer/SafeAI/releases/tag/v2.3.0)
|
|
7
7
|
[](https://www.bestpractices.dev/en/projects/14126)
|
|
8
8
|
|
|
9
9
|
Enjoying SafeAI? A ⭐ on [GitHub](https://github.com/ikaruscareer/SafeAI) helps more security teams find it.
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**Know what your AI agent can do before you deploy it.**
|
|
12
|
+
|
|
13
|
+
**SafeAI** statically maps agent capabilities, tools, MCP integrations, and authority changes, then turns material changes into explainable CI/CD security decisions and portable evidence. Technically, SafeAI is a *Static AI Capability & Risk Analyzer*: it scans AI application source code for security risks, capability exposure, and governance gaps. It is offline and source-private by default — it never executes agents or calls LLMs, and network activity occurs only through explicitly enabled integration commands (currently only `--pr-comment-post`). It integrates into CI/CD pipelines.
|
|
14
|
+
|
|
15
|
+
**Three pillars — DISCOVER / COMPARE / GOVERN:**
|
|
16
|
+
|
|
17
|
+
| Pillar | Question | What SafeAI does |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **DISCOVER** | What can the agent access? | Builds an evidence-backed model of agent authority: tools, MCP servers, filesystem, shell, databases, APIs, destinations, memory, delegation, autonomy, approval controls |
|
|
20
|
+
| **COMPARE** | What changed? | Diffs authority against the approved baseline: new tools, `read → write` widening, new destinations, removed approval gates |
|
|
21
|
+
| **GOVERN** | Should that change be allowed? | Deterministic CI/CD decisions — `pass`, `review-required`, `block`, `accepted-exception` — with evidence, never an opaque score |
|
|
22
|
+
|
|
23
|
+
> SafeAI is not a runtime guardrail and does not certify an agent as safe. It provides source-first, evidence-backed visibility into agent authority and meaningful changes *before deployment*.
|
|
12
24
|
|
|
13
25
|
> 🌐 [safeai-analyzer.ikaruscareer.com](https://safeai-analyzer.ikaruscareer.com) — project landing page
|
|
14
26
|
|
|
@@ -42,6 +54,65 @@ Designed to be lightweight, explainable, and community-driven, SafeAI aims to be
|
|
|
42
54
|
|
|
43
55
|
SafeAI sits before runtime guardrails and red-teaming tools in the security lifecycle. It scans agent source code at commit time — detecting framework-specific capabilities, MCP misconfigurations, and prompt injection patterns — before you ever deploy an agent to staging. It does not replace runtime tools (Microsoft AGT), evaluation frameworks (LangSmith, DeepEval), or red-teaming scanners (Promptfoo, Garak). It complements them: find the risk in code first, then validate at runtime.
|
|
44
56
|
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Example: authority-change report
|
|
60
|
+
|
|
61
|
+
*SafeAI's most important security event is not simply that a finding exists. It is that an agent's effective authority materially changes.*
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Agent: customer-support-agent Baseline: release v2.4.0 (approved)
|
|
65
|
+
|
|
66
|
+
AUTHORITY CHANGE (material)
|
|
67
|
+
+ tool: crm_update
|
|
68
|
+
+ capability: database write
|
|
69
|
+
+ destination: production CRM
|
|
70
|
+
+ access: read → write
|
|
71
|
+
- human approval gate (GOV_APPROVAL_MISSING)
|
|
72
|
+
|
|
73
|
+
Policy decision: BLOCK
|
|
74
|
+
Reason: production write authority was added without an approved
|
|
75
|
+
exception or required approval control.
|
|
76
|
+
Evidence: source files · tool definition · baseline manifest ·
|
|
77
|
+
current manifest · policy profile · SafeAI version ·
|
|
78
|
+
ruleset version · commit SHA
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The reviewer learns *what the agent can now do that it could not do
|
|
82
|
+
before* — and the decision cites evidence, not a score.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Agent Authority Model
|
|
87
|
+
|
|
88
|
+
SafeAI builds an analytical model — not an observation of runtime
|
|
89
|
+
permissions — of what an agent is empowered to do:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Agent
|
|
93
|
+
→ Tool / MCP Server / Skill / Workflow Node
|
|
94
|
+
→ Capability
|
|
95
|
+
→ Access Mode (none < read < write < mutate < execute)
|
|
96
|
+
→ Data / Destination / Resource
|
|
97
|
+
→ Authority
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Every authority statement carries a class: **declared** (config says so),
|
|
101
|
+
**detected** (code shows it), **inferred** (heuristic, confidence-labelled),
|
|
102
|
+
**repository/IaC-observed** (in-repo infrastructure grants), or
|
|
103
|
+
**unknown**. Runtime-granted authority (live IAM, deployed network policy,
|
|
104
|
+
runtime identity) is explicitly **unknown** to the static scanner —
|
|
105
|
+
*unknown is an evidence state, not evidence of safety*, and SafeAI never
|
|
106
|
+
converts it into a pass.
|
|
107
|
+
|
|
108
|
+
**What decisions mean.** `pass` means no configured deterministic gate
|
|
109
|
+
triggered — never "the agent is safe." `unknown` means unattributable
|
|
110
|
+
evidence — never "no risk detected." Organizations can govern unknown
|
|
111
|
+
authority explicitly (`authority.unknown` policy, `--unknown-authority`),
|
|
112
|
+
but the default leaves it visible and unfailed.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
45
116
|
<img width="1024" height="1024" alt="SafeAI_Concept" src="https://github.com/user-attachments/assets/c07999b2-79d5-4200-9eec-ce1ab4e63cc8" />
|
|
46
117
|
|
|
47
118
|
|
|
@@ -51,7 +122,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
51
122
|
|
|
52
123
|
| Feature | Description |
|
|
53
124
|
|---------|-------------|
|
|
54
|
-
| **Framework Detection** | Detects and parses
|
|
125
|
+
| **Framework Detection** | Detects and parses 19 AI agent frameworks (AST + config + regex, no mutual exclusion) |
|
|
55
126
|
| **Tool Identity & Access Modes** | Capabilities attributed to named tools (agent / MCP server / skill / tool / workflow node) on an access scale `none < read < write < mutate < execute`; inferred modes are flagged, never overstated |
|
|
56
127
|
| **Capability Discovery** | Maps 19 capability categories (shell, filesystem, network, database, memory, MCP, ...) with evidence, confidence, and provenance |
|
|
57
128
|
| **Capability Escalation Detection** | Per-tool authority diffs between scans (new shell, read→write widening, new MCP server, removed approval gate, ...) — 14 rules, including gating-aware subsumption |
|
|
@@ -68,7 +139,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
68
139
|
| **Baseline & Escalation Gating** | `--fail-on-new` for new/regressed findings, `--fail-on-escalation` for authority changes, `--pr-comment` PR summaries |
|
|
69
140
|
| **Policy-as-Code & Suppressions** | `allow`/`warn`/`require_review`/`deny` policy with selectors; required-reason suppressions |
|
|
70
141
|
| **Assurance Boundary** | Every scan states exactly what it did and could not verify — never a fixed disclaimer |
|
|
71
|
-
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome;
|
|
142
|
+
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome; informational unless you opt into `--scorecard-fail-under` gating — evidence and policy decide, the score does not |
|
|
72
143
|
| **CI/CD Integration** | SARIF 2.1.0 output, exit codes, GitHub Actions **Marketplace action** and workflow included |
|
|
73
144
|
| **Community Scan** | Governed private-pilot workflow for scanning public third-party agent frameworks with responsible disclosure (`community-scans/`) — private by default, human-reviewed before any publication |
|
|
74
145
|
| **Multi-Format Reports** | Terminal, JSON, SARIF 2.1.0, HTML, canonical KYA manifest, PR comment, Security Scorecard |
|
|
@@ -137,6 +208,8 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
137
208
|
| n8n | ✔ | Partial | Minimal | Minimal | Experimental |
|
|
138
209
|
| Cursor (.cursorrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
139
210
|
| Windsurf (.windsurfrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
211
|
+
| OpenClaw config | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
212
|
+
| GitHub Copilot instructions | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
140
213
|
|
|
141
214
|
|
|
142
215
|
### Framework Support Details
|
|
@@ -161,6 +234,12 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
161
234
|
- **Cursor (.cursorrules)** — detects declared tools/permissions and
|
|
162
235
|
capability-relevant keywords (shell, filesystem, HTTP, database) in the
|
|
163
236
|
IDE's rules config, JSON, YAML, or free text
|
|
237
|
+
- **Windsurf (.windsurfrules)** — detects declared tools, models, and
|
|
238
|
+
capability-relevant keywords in JSON, YAML, or free-text rules
|
|
239
|
+
- **OpenClaw config** — detects JSON/YAML files under `.openclaw/` and
|
|
240
|
+
`.openclaw.yaml`, including declared tools, models, and MCP servers
|
|
241
|
+
- **GitHub Copilot instructions** — detects repository instruction Markdown,
|
|
242
|
+
YAML frontmatter, and `.copilot/*.yml` tool or permission grants
|
|
164
243
|
|
|
165
244
|
Maturity is on the scale defined in [`docs/reference/FRAMEWORK_SUPPORT.md`](docs/reference/FRAMEWORK_SUPPORT.md):
|
|
166
245
|
**Partial** = reliable detection and discovery with capability/risk analysis over
|
|
@@ -178,6 +257,8 @@ Representative test fixtures and validation tests for framework detection:
|
|
|
178
257
|
| LlamaIndex | `test_llamaindex_framework.py` | `fixtures/llamaindex/representative/agent.py` | @adnqcr7-code [#61] |
|
|
179
258
|
| CrewAI | `test_crewai_framework.py` | `fixtures/crewai/representative/crew.py` | @adnqcr7-code [#62] |
|
|
180
259
|
| Claude Code | `test_claude_code_deep.py` | `fixtures/claude_code/compatibility/` | @adnqcr7-code [#59] |
|
|
260
|
+
| OpenClaw config | `test_config_adapters.py` | `fixtures/openclaw/representative/.openclaw/config.json` | @YaoSong808 [#159] |
|
|
261
|
+
| GitHub Copilot instructions | `test_config_adapters.py` | `fixtures/copilot/representative/.github/copilot-instructions.md` | @YaoSong808 [#159] |
|
|
181
262
|
|
|
182
263
|
---
|
|
183
264
|
|
|
@@ -269,6 +350,16 @@ to a shared path, or use `--no-registry` for ephemeral scans.
|
|
|
269
350
|
- Python 3.11, 3.12, or 3.13
|
|
270
351
|
- PyYAML (for YAML configuration parsing)
|
|
271
352
|
|
|
353
|
+
### Install from PyPI (recommended)
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
pip install SafeAI-Static-Analyzer
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Unpinned on purpose — this always resolves to the latest stable
|
|
360
|
+
release (see [releases](https://github.com/ikaruscareer/SafeAI/releases)).
|
|
361
|
+
Verify the download with [`docs/reference/VERIFICATION.md`](docs/reference/VERIFICATION.md).
|
|
362
|
+
|
|
272
363
|
### Install from source
|
|
273
364
|
|
|
274
365
|
```bash
|
|
@@ -310,6 +401,7 @@ python -m safeai registry <subcommand> [options]
|
|
|
310
401
|
| `--json` | — | JSON output path |
|
|
311
402
|
| `--html` | — | HTML report output path |
|
|
312
403
|
| `--manifest` | — | Canonical KYA manifest output path (`safeai-manifest.json`) |
|
|
404
|
+
| `--digest-file` | — | With `--manifest`: write `<canonical-sha256> <manifest-basename>` to this path. The digest is the one `safeai manifest verify` reports, not a raw file hash, so it is not `sha256sum -c` compatible |
|
|
313
405
|
| `--baseline` | — | Prior manifest/report for new/existing comparison |
|
|
314
406
|
| `--fail-on-new` | off | With `--baseline`: fail only on new/regressed findings |
|
|
315
407
|
| `--policy` | `.safeai/policy.yml` | Policy-as-code YAML file |
|
|
@@ -417,7 +509,7 @@ jobs:
|
|
|
417
509
|
- uses: actions/checkout@v4
|
|
418
510
|
- uses: actions/setup-python@v5
|
|
419
511
|
with: { python-version: '3.12' }
|
|
420
|
-
- uses: ikaruscareer/SafeAI@
|
|
512
|
+
- uses: ikaruscareer/SafeAI@v2
|
|
421
513
|
with: { path: '.', fail-on: critical }
|
|
422
514
|
- uses: github/codeql-action/upload-sarif@v3
|
|
423
515
|
if: always()
|
|
@@ -471,9 +563,13 @@ contributors who have helped make AI safer:
|
|
|
471
563
|
| [@hadbiaghiles](https://github.com/hadbiaghiles) | AutoGen framework documentation |
|
|
472
564
|
| [@D05TL3](https://github.com/D05TL3) | GitHub Actions scanning example |
|
|
473
565
|
| [@mikemikimike](https://github.com/mikemikimike) | Adapter negative detection tests |
|
|
566
|
+
| [@burakeyler](https://github.com/burakeyler) | `--digest-file` manifest digest sidecar (PR #148) |
|
|
567
|
+
| [@YaoSong808](https://github.com/YaoSong808) | OpenClaw and GitHub Copilot config-file adapters (PR #159) |
|
|
474
568
|
| [@mah](https://github.com/mahirhir) | Claude Code deep analysis documentation |
|
|
475
569
|
| [@asarakhatun17-lgtm](https://github.com/asarakhatun17-lgtm) | Supported frameworks consistency fix |
|
|
476
570
|
| [@yugaaank](https://github.com/yugaaank) | Capability detectors (Docker, Kubernetes, Redis, S3, GCP, Slack, Jira, browser) |
|
|
571
|
+
| [@Teachmeplaycode](https://github.com/Teachmeplaycode) | Benchmark corpus expansion, static subprocess precision gap documentation (PR #174) |
|
|
572
|
+
| [@nikitajos7](https://github.com/nikitajos7) | Policy profile display in terminal and HTML reports (PR #175) |
|
|
477
573
|
|
|
478
574
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
479
575
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SafeAI-Static-Analyzer
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: The lightweight, open-source Static AI Capability & Risk Analyzer for CI/CD pipelines.
|
|
5
5
|
Author: IkarusCareer
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -31,17 +31,29 @@ Provides-Extra: standalone
|
|
|
31
31
|
Requires-Dist: pyinstaller>=6.0; extra == "standalone"
|
|
32
32
|
Dynamic: license-file
|
|
33
33
|
|
|
34
|
-
# SafeAI —
|
|
34
|
+
# SafeAI — Agent Authority Security for the Software Supply Chain
|
|
35
35
|
|
|
36
36
|
[](https://github.com/ikaruscareer/SafeAI/actions/workflows/ci.yml)
|
|
37
37
|
[](https://scorecard.dev/viewer/?uri=github.com/ikaruscareer/SafeAI)
|
|
38
38
|
[](https://safeai-analyzer.ikaruscareer.com)
|
|
39
|
-
[](https://github.com/ikaruscareer/SafeAI/releases/tag/v2.3.0)
|
|
40
40
|
[](https://www.bestpractices.dev/en/projects/14126)
|
|
41
41
|
|
|
42
42
|
Enjoying SafeAI? A ⭐ on [GitHub](https://github.com/ikaruscareer/SafeAI) helps more security teams find it.
|
|
43
43
|
|
|
44
|
-
**
|
|
44
|
+
**Know what your AI agent can do before you deploy it.**
|
|
45
|
+
|
|
46
|
+
**SafeAI** statically maps agent capabilities, tools, MCP integrations, and authority changes, then turns material changes into explainable CI/CD security decisions and portable evidence. Technically, SafeAI is a *Static AI Capability & Risk Analyzer*: it scans AI application source code for security risks, capability exposure, and governance gaps. It is offline and source-private by default — it never executes agents or calls LLMs, and network activity occurs only through explicitly enabled integration commands (currently only `--pr-comment-post`). It integrates into CI/CD pipelines.
|
|
47
|
+
|
|
48
|
+
**Three pillars — DISCOVER / COMPARE / GOVERN:**
|
|
49
|
+
|
|
50
|
+
| Pillar | Question | What SafeAI does |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| **DISCOVER** | What can the agent access? | Builds an evidence-backed model of agent authority: tools, MCP servers, filesystem, shell, databases, APIs, destinations, memory, delegation, autonomy, approval controls |
|
|
53
|
+
| **COMPARE** | What changed? | Diffs authority against the approved baseline: new tools, `read → write` widening, new destinations, removed approval gates |
|
|
54
|
+
| **GOVERN** | Should that change be allowed? | Deterministic CI/CD decisions — `pass`, `review-required`, `block`, `accepted-exception` — with evidence, never an opaque score |
|
|
55
|
+
|
|
56
|
+
> SafeAI is not a runtime guardrail and does not certify an agent as safe. It provides source-first, evidence-backed visibility into agent authority and meaningful changes *before deployment*.
|
|
45
57
|
|
|
46
58
|
> 🌐 [safeai-analyzer.ikaruscareer.com](https://safeai-analyzer.ikaruscareer.com) — project landing page
|
|
47
59
|
|
|
@@ -75,6 +87,65 @@ Designed to be lightweight, explainable, and community-driven, SafeAI aims to be
|
|
|
75
87
|
|
|
76
88
|
SafeAI sits before runtime guardrails and red-teaming tools in the security lifecycle. It scans agent source code at commit time — detecting framework-specific capabilities, MCP misconfigurations, and prompt injection patterns — before you ever deploy an agent to staging. It does not replace runtime tools (Microsoft AGT), evaluation frameworks (LangSmith, DeepEval), or red-teaming scanners (Promptfoo, Garak). It complements them: find the risk in code first, then validate at runtime.
|
|
77
89
|
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Example: authority-change report
|
|
93
|
+
|
|
94
|
+
*SafeAI's most important security event is not simply that a finding exists. It is that an agent's effective authority materially changes.*
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Agent: customer-support-agent Baseline: release v2.4.0 (approved)
|
|
98
|
+
|
|
99
|
+
AUTHORITY CHANGE (material)
|
|
100
|
+
+ tool: crm_update
|
|
101
|
+
+ capability: database write
|
|
102
|
+
+ destination: production CRM
|
|
103
|
+
+ access: read → write
|
|
104
|
+
- human approval gate (GOV_APPROVAL_MISSING)
|
|
105
|
+
|
|
106
|
+
Policy decision: BLOCK
|
|
107
|
+
Reason: production write authority was added without an approved
|
|
108
|
+
exception or required approval control.
|
|
109
|
+
Evidence: source files · tool definition · baseline manifest ·
|
|
110
|
+
current manifest · policy profile · SafeAI version ·
|
|
111
|
+
ruleset version · commit SHA
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The reviewer learns *what the agent can now do that it could not do
|
|
115
|
+
before* — and the decision cites evidence, not a score.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Agent Authority Model
|
|
120
|
+
|
|
121
|
+
SafeAI builds an analytical model — not an observation of runtime
|
|
122
|
+
permissions — of what an agent is empowered to do:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Agent
|
|
126
|
+
→ Tool / MCP Server / Skill / Workflow Node
|
|
127
|
+
→ Capability
|
|
128
|
+
→ Access Mode (none < read < write < mutate < execute)
|
|
129
|
+
→ Data / Destination / Resource
|
|
130
|
+
→ Authority
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Every authority statement carries a class: **declared** (config says so),
|
|
134
|
+
**detected** (code shows it), **inferred** (heuristic, confidence-labelled),
|
|
135
|
+
**repository/IaC-observed** (in-repo infrastructure grants), or
|
|
136
|
+
**unknown**. Runtime-granted authority (live IAM, deployed network policy,
|
|
137
|
+
runtime identity) is explicitly **unknown** to the static scanner —
|
|
138
|
+
*unknown is an evidence state, not evidence of safety*, and SafeAI never
|
|
139
|
+
converts it into a pass.
|
|
140
|
+
|
|
141
|
+
**What decisions mean.** `pass` means no configured deterministic gate
|
|
142
|
+
triggered — never "the agent is safe." `unknown` means unattributable
|
|
143
|
+
evidence — never "no risk detected." Organizations can govern unknown
|
|
144
|
+
authority explicitly (`authority.unknown` policy, `--unknown-authority`),
|
|
145
|
+
but the default leaves it visible and unfailed.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
78
149
|
<img width="1024" height="1024" alt="SafeAI_Concept" src="https://github.com/user-attachments/assets/c07999b2-79d5-4200-9eec-ce1ab4e63cc8" />
|
|
79
150
|
|
|
80
151
|
|
|
@@ -84,7 +155,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
84
155
|
|
|
85
156
|
| Feature | Description |
|
|
86
157
|
|---------|-------------|
|
|
87
|
-
| **Framework Detection** | Detects and parses
|
|
158
|
+
| **Framework Detection** | Detects and parses 19 AI agent frameworks (AST + config + regex, no mutual exclusion) |
|
|
88
159
|
| **Tool Identity & Access Modes** | Capabilities attributed to named tools (agent / MCP server / skill / tool / workflow node) on an access scale `none < read < write < mutate < execute`; inferred modes are flagged, never overstated |
|
|
89
160
|
| **Capability Discovery** | Maps 19 capability categories (shell, filesystem, network, database, memory, MCP, ...) with evidence, confidence, and provenance |
|
|
90
161
|
| **Capability Escalation Detection** | Per-tool authority diffs between scans (new shell, read→write widening, new MCP server, removed approval gate, ...) — 14 rules, including gating-aware subsumption |
|
|
@@ -101,7 +172,7 @@ SafeAI sits before runtime guardrails and red-teaming tools in the security life
|
|
|
101
172
|
| **Baseline & Escalation Gating** | `--fail-on-new` for new/regressed findings, `--fail-on-escalation` for authority changes, `--pr-comment` PR summaries |
|
|
102
173
|
| **Policy-as-Code & Suppressions** | `allow`/`warn`/`require_review`/`deny` policy with selectors; required-reason suppressions |
|
|
103
174
|
| **Assurance Boundary** | Every scan states exactly what it did and could not verify — never a fixed disclaimer |
|
|
104
|
-
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome;
|
|
175
|
+
| **Security Scorecard** | Deterministic 0–10 score with per-category breakdown and `pass`/`warn`/`fail` outcome; informational unless you opt into `--scorecard-fail-under` gating — evidence and policy decide, the score does not |
|
|
105
176
|
| **CI/CD Integration** | SARIF 2.1.0 output, exit codes, GitHub Actions **Marketplace action** and workflow included |
|
|
106
177
|
| **Community Scan** | Governed private-pilot workflow for scanning public third-party agent frameworks with responsible disclosure (`community-scans/`) — private by default, human-reviewed before any publication |
|
|
107
178
|
| **Multi-Format Reports** | Terminal, JSON, SARIF 2.1.0, HTML, canonical KYA manifest, PR comment, Security Scorecard |
|
|
@@ -170,6 +241,8 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
170
241
|
| n8n | ✔ | Partial | Minimal | Minimal | Experimental |
|
|
171
242
|
| Cursor (.cursorrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
172
243
|
| Windsurf (.windsurfrules) | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
244
|
+
| OpenClaw config | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
245
|
+
| GitHub Copilot instructions | ✔ | Minimal | Minimal | Minimal | Experimental |
|
|
173
246
|
|
|
174
247
|
|
|
175
248
|
### Framework Support Details
|
|
@@ -194,6 +267,12 @@ Registry & Reports — shared SQLite registry; terminal, JSON, SARIF 2.1.0, HTML
|
|
|
194
267
|
- **Cursor (.cursorrules)** — detects declared tools/permissions and
|
|
195
268
|
capability-relevant keywords (shell, filesystem, HTTP, database) in the
|
|
196
269
|
IDE's rules config, JSON, YAML, or free text
|
|
270
|
+
- **Windsurf (.windsurfrules)** — detects declared tools, models, and
|
|
271
|
+
capability-relevant keywords in JSON, YAML, or free-text rules
|
|
272
|
+
- **OpenClaw config** — detects JSON/YAML files under `.openclaw/` and
|
|
273
|
+
`.openclaw.yaml`, including declared tools, models, and MCP servers
|
|
274
|
+
- **GitHub Copilot instructions** — detects repository instruction Markdown,
|
|
275
|
+
YAML frontmatter, and `.copilot/*.yml` tool or permission grants
|
|
197
276
|
|
|
198
277
|
Maturity is on the scale defined in [`docs/reference/FRAMEWORK_SUPPORT.md`](docs/reference/FRAMEWORK_SUPPORT.md):
|
|
199
278
|
**Partial** = reliable detection and discovery with capability/risk analysis over
|
|
@@ -211,6 +290,8 @@ Representative test fixtures and validation tests for framework detection:
|
|
|
211
290
|
| LlamaIndex | `test_llamaindex_framework.py` | `fixtures/llamaindex/representative/agent.py` | @adnqcr7-code [#61] |
|
|
212
291
|
| CrewAI | `test_crewai_framework.py` | `fixtures/crewai/representative/crew.py` | @adnqcr7-code [#62] |
|
|
213
292
|
| Claude Code | `test_claude_code_deep.py` | `fixtures/claude_code/compatibility/` | @adnqcr7-code [#59] |
|
|
293
|
+
| OpenClaw config | `test_config_adapters.py` | `fixtures/openclaw/representative/.openclaw/config.json` | @YaoSong808 [#159] |
|
|
294
|
+
| GitHub Copilot instructions | `test_config_adapters.py` | `fixtures/copilot/representative/.github/copilot-instructions.md` | @YaoSong808 [#159] |
|
|
214
295
|
|
|
215
296
|
---
|
|
216
297
|
|
|
@@ -302,6 +383,16 @@ to a shared path, or use `--no-registry` for ephemeral scans.
|
|
|
302
383
|
- Python 3.11, 3.12, or 3.13
|
|
303
384
|
- PyYAML (for YAML configuration parsing)
|
|
304
385
|
|
|
386
|
+
### Install from PyPI (recommended)
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
pip install SafeAI-Static-Analyzer
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Unpinned on purpose — this always resolves to the latest stable
|
|
393
|
+
release (see [releases](https://github.com/ikaruscareer/SafeAI/releases)).
|
|
394
|
+
Verify the download with [`docs/reference/VERIFICATION.md`](docs/reference/VERIFICATION.md).
|
|
395
|
+
|
|
305
396
|
### Install from source
|
|
306
397
|
|
|
307
398
|
```bash
|
|
@@ -343,6 +434,7 @@ python -m safeai registry <subcommand> [options]
|
|
|
343
434
|
| `--json` | — | JSON output path |
|
|
344
435
|
| `--html` | — | HTML report output path |
|
|
345
436
|
| `--manifest` | — | Canonical KYA manifest output path (`safeai-manifest.json`) |
|
|
437
|
+
| `--digest-file` | — | With `--manifest`: write `<canonical-sha256> <manifest-basename>` to this path. The digest is the one `safeai manifest verify` reports, not a raw file hash, so it is not `sha256sum -c` compatible |
|
|
346
438
|
| `--baseline` | — | Prior manifest/report for new/existing comparison |
|
|
347
439
|
| `--fail-on-new` | off | With `--baseline`: fail only on new/regressed findings |
|
|
348
440
|
| `--policy` | `.safeai/policy.yml` | Policy-as-code YAML file |
|
|
@@ -450,7 +542,7 @@ jobs:
|
|
|
450
542
|
- uses: actions/checkout@v4
|
|
451
543
|
- uses: actions/setup-python@v5
|
|
452
544
|
with: { python-version: '3.12' }
|
|
453
|
-
- uses: ikaruscareer/SafeAI@
|
|
545
|
+
- uses: ikaruscareer/SafeAI@v2
|
|
454
546
|
with: { path: '.', fail-on: critical }
|
|
455
547
|
- uses: github/codeql-action/upload-sarif@v3
|
|
456
548
|
if: always()
|
|
@@ -504,9 +596,13 @@ contributors who have helped make AI safer:
|
|
|
504
596
|
| [@hadbiaghiles](https://github.com/hadbiaghiles) | AutoGen framework documentation |
|
|
505
597
|
| [@D05TL3](https://github.com/D05TL3) | GitHub Actions scanning example |
|
|
506
598
|
| [@mikemikimike](https://github.com/mikemikimike) | Adapter negative detection tests |
|
|
599
|
+
| [@burakeyler](https://github.com/burakeyler) | `--digest-file` manifest digest sidecar (PR #148) |
|
|
600
|
+
| [@YaoSong808](https://github.com/YaoSong808) | OpenClaw and GitHub Copilot config-file adapters (PR #159) |
|
|
507
601
|
| [@mah](https://github.com/mahirhir) | Claude Code deep analysis documentation |
|
|
508
602
|
| [@asarakhatun17-lgtm](https://github.com/asarakhatun17-lgtm) | Supported frameworks consistency fix |
|
|
509
603
|
| [@yugaaank](https://github.com/yugaaank) | Capability detectors (Docker, Kubernetes, Redis, S3, GCP, Slack, Jira, browser) |
|
|
604
|
+
| [@Teachmeplaycode](https://github.com/Teachmeplaycode) | Benchmark corpus expansion, static subprocess precision gap documentation (PR #174) |
|
|
605
|
+
| [@nikitajos7](https://github.com/nikitajos7) | Policy profile display in terminal and HTML reports (PR #175) |
|
|
510
606
|
|
|
511
607
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
512
608
|
|