cisco-ai-skill-scanner 1.0.0__py3-none-any.whl
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.
- cisco_ai_skill_scanner-1.0.0.dist-info/METADATA +253 -0
- cisco_ai_skill_scanner-1.0.0.dist-info/RECORD +100 -0
- cisco_ai_skill_scanner-1.0.0.dist-info/WHEEL +4 -0
- cisco_ai_skill_scanner-1.0.0.dist-info/entry_points.txt +4 -0
- cisco_ai_skill_scanner-1.0.0.dist-info/licenses/LICENSE +17 -0
- skillanalyzer/__init__.py +45 -0
- skillanalyzer/_version.py +34 -0
- skillanalyzer/api/__init__.py +25 -0
- skillanalyzer/api/api.py +34 -0
- skillanalyzer/api/api_cli.py +78 -0
- skillanalyzer/api/api_server.py +634 -0
- skillanalyzer/api/router.py +527 -0
- skillanalyzer/cli/__init__.py +25 -0
- skillanalyzer/cli/cli.py +816 -0
- skillanalyzer/config/__init__.py +26 -0
- skillanalyzer/config/config.py +149 -0
- skillanalyzer/config/config_parser.py +122 -0
- skillanalyzer/config/constants.py +85 -0
- skillanalyzer/core/__init__.py +24 -0
- skillanalyzer/core/analyzers/__init__.py +75 -0
- skillanalyzer/core/analyzers/aidefense_analyzer.py +872 -0
- skillanalyzer/core/analyzers/base.py +53 -0
- skillanalyzer/core/analyzers/behavioral/__init__.py +30 -0
- skillanalyzer/core/analyzers/behavioral/alignment/__init__.py +45 -0
- skillanalyzer/core/analyzers/behavioral/alignment/alignment_llm_client.py +240 -0
- skillanalyzer/core/analyzers/behavioral/alignment/alignment_orchestrator.py +216 -0
- skillanalyzer/core/analyzers/behavioral/alignment/alignment_prompt_builder.py +422 -0
- skillanalyzer/core/analyzers/behavioral/alignment/alignment_response_validator.py +136 -0
- skillanalyzer/core/analyzers/behavioral/alignment/threat_vulnerability_classifier.py +198 -0
- skillanalyzer/core/analyzers/behavioral_analyzer.py +453 -0
- skillanalyzer/core/analyzers/cross_skill_analyzer.py +490 -0
- skillanalyzer/core/analyzers/llm_analyzer.py +440 -0
- skillanalyzer/core/analyzers/llm_prompt_builder.py +270 -0
- skillanalyzer/core/analyzers/llm_provider_config.py +215 -0
- skillanalyzer/core/analyzers/llm_request_handler.py +284 -0
- skillanalyzer/core/analyzers/llm_response_parser.py +81 -0
- skillanalyzer/core/analyzers/meta_analyzer.py +845 -0
- skillanalyzer/core/analyzers/static.py +1105 -0
- skillanalyzer/core/analyzers/trigger_analyzer.py +341 -0
- skillanalyzer/core/analyzers/virustotal_analyzer.py +463 -0
- skillanalyzer/core/exceptions.py +77 -0
- skillanalyzer/core/loader.py +377 -0
- skillanalyzer/core/models.py +300 -0
- skillanalyzer/core/reporters/__init__.py +26 -0
- skillanalyzer/core/reporters/json_reporter.py +65 -0
- skillanalyzer/core/reporters/markdown_reporter.py +209 -0
- skillanalyzer/core/reporters/sarif_reporter.py +246 -0
- skillanalyzer/core/reporters/table_reporter.py +195 -0
- skillanalyzer/core/rules/__init__.py +19 -0
- skillanalyzer/core/rules/patterns.py +165 -0
- skillanalyzer/core/rules/yara_scanner.py +157 -0
- skillanalyzer/core/scanner.py +437 -0
- skillanalyzer/core/static_analysis/__init__.py +27 -0
- skillanalyzer/core/static_analysis/cfg/__init__.py +21 -0
- skillanalyzer/core/static_analysis/cfg/builder.py +439 -0
- skillanalyzer/core/static_analysis/context_extractor.py +742 -0
- skillanalyzer/core/static_analysis/dataflow/__init__.py +25 -0
- skillanalyzer/core/static_analysis/dataflow/forward_analysis.py +715 -0
- skillanalyzer/core/static_analysis/interprocedural/__init__.py +21 -0
- skillanalyzer/core/static_analysis/interprocedural/call_graph_analyzer.py +406 -0
- skillanalyzer/core/static_analysis/interprocedural/cross_file_analyzer.py +190 -0
- skillanalyzer/core/static_analysis/parser/__init__.py +21 -0
- skillanalyzer/core/static_analysis/parser/python_parser.py +380 -0
- skillanalyzer/core/static_analysis/semantic/__init__.py +28 -0
- skillanalyzer/core/static_analysis/semantic/name_resolver.py +206 -0
- skillanalyzer/core/static_analysis/semantic/type_analyzer.py +200 -0
- skillanalyzer/core/static_analysis/taint/__init__.py +21 -0
- skillanalyzer/core/static_analysis/taint/tracker.py +252 -0
- skillanalyzer/core/static_analysis/types/__init__.py +36 -0
- skillanalyzer/data/__init__.py +30 -0
- skillanalyzer/data/prompts/boilerplate_protection_rule_prompt.md +26 -0
- skillanalyzer/data/prompts/code_alignment_threat_analysis_prompt.md +901 -0
- skillanalyzer/data/prompts/llm_response_schema.json +71 -0
- skillanalyzer/data/prompts/skill_meta_analysis_prompt.md +303 -0
- skillanalyzer/data/prompts/skill_threat_analysis_prompt.md +263 -0
- skillanalyzer/data/prompts/unified_response_schema.md +97 -0
- skillanalyzer/data/rules/signatures.yaml +440 -0
- skillanalyzer/data/yara_rules/autonomy_abuse.yara +66 -0
- skillanalyzer/data/yara_rules/code_execution.yara +61 -0
- skillanalyzer/data/yara_rules/coercive_injection.yara +115 -0
- skillanalyzer/data/yara_rules/command_injection.yara +54 -0
- skillanalyzer/data/yara_rules/credential_harvesting.yara +115 -0
- skillanalyzer/data/yara_rules/prompt_injection.yara +71 -0
- skillanalyzer/data/yara_rules/script_injection.yara +83 -0
- skillanalyzer/data/yara_rules/skill_discovery_abuse.yara +57 -0
- skillanalyzer/data/yara_rules/sql_injection.yara +73 -0
- skillanalyzer/data/yara_rules/system_manipulation.yara +65 -0
- skillanalyzer/data/yara_rules/tool_chaining_abuse.yara +60 -0
- skillanalyzer/data/yara_rules/transitive_trust_abuse.yara +73 -0
- skillanalyzer/data/yara_rules/unicode_steganography.yara +65 -0
- skillanalyzer/hooks/__init__.py +21 -0
- skillanalyzer/hooks/pre_commit.py +450 -0
- skillanalyzer/threats/__init__.py +25 -0
- skillanalyzer/threats/threats.py +480 -0
- skillanalyzer/utils/__init__.py +28 -0
- skillanalyzer/utils/command_utils.py +129 -0
- skillanalyzer/utils/di_container.py +154 -0
- skillanalyzer/utils/file_utils.py +86 -0
- skillanalyzer/utils/logging_config.py +96 -0
- skillanalyzer/utils/logging_utils.py +71 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Configuration management for Claude Skill Analyzer.
|
|
19
|
+
|
|
20
|
+
Mirrors MCP Scanner's config structure.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .config import Config
|
|
24
|
+
from .constants import SkillAnalyzerConstants
|
|
25
|
+
|
|
26
|
+
__all__ = ["Config", "SkillAnalyzerConstants"]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Configuration class for Claude Skill Analyzer.
|
|
19
|
+
|
|
20
|
+
Based on MCP Scanner's Config structure.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class Config:
|
|
30
|
+
"""
|
|
31
|
+
Configuration for Claude Skill Analyzer.
|
|
32
|
+
|
|
33
|
+
Mirrors MCP Scanner's Config class structure.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
# LLM Configuration
|
|
37
|
+
llm_provider_api_key: str | None = None
|
|
38
|
+
llm_model: str = "claude-3-5-sonnet-20241022"
|
|
39
|
+
llm_base_url: str | None = None
|
|
40
|
+
llm_api_version: str | None = None
|
|
41
|
+
llm_max_tokens: int = 4000
|
|
42
|
+
llm_temperature: float = 0.0
|
|
43
|
+
llm_rate_limit_delay: float = 2.0
|
|
44
|
+
llm_max_retries: int = 3
|
|
45
|
+
llm_timeout: int = 120
|
|
46
|
+
|
|
47
|
+
# AWS Bedrock Configuration
|
|
48
|
+
aws_region_name: str = "us-east-1"
|
|
49
|
+
aws_profile_name: str | None = None
|
|
50
|
+
aws_session_token: str | None = None
|
|
51
|
+
|
|
52
|
+
# Analyzer Configuration
|
|
53
|
+
enable_static_analyzer: bool = True
|
|
54
|
+
enable_llm_analyzer: bool = False
|
|
55
|
+
enable_behavioral_analyzer: bool = False
|
|
56
|
+
enable_aidefense: bool = False
|
|
57
|
+
|
|
58
|
+
# VirusTotal Configuration
|
|
59
|
+
virustotal_api_key: str | None = None
|
|
60
|
+
virustotal_upload_files: bool = False
|
|
61
|
+
|
|
62
|
+
# AI Defense Configuration
|
|
63
|
+
aidefense_api_key: str | None = None
|
|
64
|
+
|
|
65
|
+
# Scanning Options
|
|
66
|
+
max_file_size_mb: int = 10
|
|
67
|
+
scan_timeout_seconds: int = 300
|
|
68
|
+
|
|
69
|
+
# Output Options
|
|
70
|
+
output_format: str = "summary"
|
|
71
|
+
detailed_output: bool = False
|
|
72
|
+
|
|
73
|
+
def __post_init__(self):
|
|
74
|
+
"""Load configuration from environment variables if not provided."""
|
|
75
|
+
|
|
76
|
+
# LLM API key from environment
|
|
77
|
+
if self.llm_provider_api_key is None:
|
|
78
|
+
self.llm_provider_api_key = os.getenv("SKILL_SCANNER_LLM_API_KEY")
|
|
79
|
+
|
|
80
|
+
# LLM model from environment (only if still at default)
|
|
81
|
+
if self.llm_model == "claude-3-5-sonnet-20241022":
|
|
82
|
+
if env_model := os.getenv("SKILL_SCANNER_LLM_MODEL"):
|
|
83
|
+
self.llm_model = env_model
|
|
84
|
+
|
|
85
|
+
# AWS configuration from environment
|
|
86
|
+
if env_region := os.getenv("AWS_REGION"):
|
|
87
|
+
self.aws_region_name = env_region
|
|
88
|
+
|
|
89
|
+
if env_profile := os.getenv("AWS_PROFILE"):
|
|
90
|
+
self.aws_profile_name = env_profile
|
|
91
|
+
|
|
92
|
+
if env_session := os.getenv("AWS_SESSION_TOKEN"):
|
|
93
|
+
self.aws_session_token = env_session
|
|
94
|
+
|
|
95
|
+
# Analyzer toggles from environment
|
|
96
|
+
if os.getenv("ENABLE_STATIC_ANALYZER", "").lower() in ("false", "0"):
|
|
97
|
+
self.enable_static_analyzer = False
|
|
98
|
+
|
|
99
|
+
if os.getenv("ENABLE_LLM_ANALYZER", "").lower() in ("true", "1"):
|
|
100
|
+
self.enable_llm_analyzer = True
|
|
101
|
+
|
|
102
|
+
if os.getenv("ENABLE_BEHAVIORAL_ANALYZER", "").lower() in ("true", "1"):
|
|
103
|
+
self.enable_behavioral_analyzer = True
|
|
104
|
+
|
|
105
|
+
if os.getenv("ENABLE_AIDEFENSE", "").lower() in ("true", "1"):
|
|
106
|
+
self.enable_aidefense = True
|
|
107
|
+
|
|
108
|
+
# VirusTotal configuration from environment
|
|
109
|
+
if self.virustotal_api_key is None:
|
|
110
|
+
self.virustotal_api_key = os.getenv("VIRUSTOTAL_API_KEY")
|
|
111
|
+
|
|
112
|
+
if os.getenv("VIRUSTOTAL_UPLOAD_FILES", "").lower() in ("true", "1"):
|
|
113
|
+
self.virustotal_upload_files = True
|
|
114
|
+
|
|
115
|
+
# AI Defense configuration from environment
|
|
116
|
+
if self.aidefense_api_key is None:
|
|
117
|
+
self.aidefense_api_key = os.getenv("AI_DEFENSE_API_KEY")
|
|
118
|
+
|
|
119
|
+
@classmethod
|
|
120
|
+
def from_env(cls) -> "Config":
|
|
121
|
+
"""
|
|
122
|
+
Create configuration from environment variables.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Config instance with values from environment
|
|
126
|
+
"""
|
|
127
|
+
return cls()
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
def from_file(cls, config_file: Path) -> "Config":
|
|
131
|
+
"""
|
|
132
|
+
Load configuration from .env file.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
config_file: Path to .env file
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Config instance
|
|
139
|
+
"""
|
|
140
|
+
# Load .env file
|
|
141
|
+
if config_file.exists():
|
|
142
|
+
with open(config_file) as f:
|
|
143
|
+
for line in f:
|
|
144
|
+
line = line.strip()
|
|
145
|
+
if line and not line.startswith("#") and "=" in line:
|
|
146
|
+
key, value = line.split("=", 1)
|
|
147
|
+
os.environ[key.strip()] = value.strip()
|
|
148
|
+
|
|
149
|
+
return cls.from_env()
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""Configuration parser for Skill Analyzer.
|
|
18
|
+
|
|
19
|
+
This module provides functionality to parse configuration files
|
|
20
|
+
and environment variables for Skill Analyzer.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
from ..utils.logging_config import get_logger
|
|
27
|
+
from .config import Config
|
|
28
|
+
from .constants import SkillAnalyzerConstants
|
|
29
|
+
|
|
30
|
+
logger = get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def parse_config_from_env() -> Config:
|
|
34
|
+
"""Parse configuration from environment variables.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Config instance with values from environment variables.
|
|
38
|
+
"""
|
|
39
|
+
config = Config()
|
|
40
|
+
|
|
41
|
+
# Parse LLM configuration - use SKILL_SCANNER_* env vars only
|
|
42
|
+
config.llm_provider_api_key = os.getenv("SKILL_SCANNER_LLM_API_KEY")
|
|
43
|
+
config.llm_model = os.getenv("SKILL_SCANNER_LLM_MODEL", "claude-3-5-sonnet-20241022")
|
|
44
|
+
|
|
45
|
+
# Parse analyzer flags
|
|
46
|
+
if os.getenv("USE_LLM_ANALYZER", "").lower() == "true":
|
|
47
|
+
config.enable_llm_analyzer = True
|
|
48
|
+
if os.getenv("USE_BEHAVIORAL_ANALYZER", "").lower() == "true":
|
|
49
|
+
config.enable_behavioral_analyzer = True
|
|
50
|
+
|
|
51
|
+
# Parse output format
|
|
52
|
+
output_format = os.getenv("OUTPUT_FORMAT", "summary").lower()
|
|
53
|
+
if output_format in ["json", "markdown", "summary", "table"]:
|
|
54
|
+
config.output_format = output_format
|
|
55
|
+
|
|
56
|
+
# Parse verbosity
|
|
57
|
+
if os.getenv("VERBOSE", "").lower() == "true":
|
|
58
|
+
config.detailed_output = True
|
|
59
|
+
|
|
60
|
+
return config
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def parse_config_file(config_path: str | None = None) -> Config:
|
|
64
|
+
"""Parse configuration from a file.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
config_path: Path to configuration file (optional).
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Config instance with values from file and environment.
|
|
71
|
+
"""
|
|
72
|
+
config = parse_config_from_env()
|
|
73
|
+
|
|
74
|
+
if not config_path:
|
|
75
|
+
# Try to find default config file
|
|
76
|
+
default_paths = [
|
|
77
|
+
Path.home() / ".skillanalyzer" / "config.yaml",
|
|
78
|
+
Path.home() / ".skillanalyzer" / "config.json",
|
|
79
|
+
Path.cwd() / ".skillanalyzer.yaml",
|
|
80
|
+
Path.cwd() / ".skillanalyzer.json",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
for path in default_paths:
|
|
84
|
+
if path.exists():
|
|
85
|
+
config_path = str(path)
|
|
86
|
+
logger.debug(f"Found config file: {config_path}")
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
if config_path and Path(config_path).exists():
|
|
90
|
+
# For now, we'll parse environment variables
|
|
91
|
+
# In the future, this could parse YAML/JSON config files
|
|
92
|
+
logger.debug(f"Loading config from: {config_path}")
|
|
93
|
+
# TODO: Implement file parsing if needed
|
|
94
|
+
|
|
95
|
+
return config
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ConfigParser:
|
|
99
|
+
"""Parser for Skill Analyzer configuration files."""
|
|
100
|
+
|
|
101
|
+
def __init__(self):
|
|
102
|
+
"""Initialize the config parser."""
|
|
103
|
+
self.constants = SkillAnalyzerConstants
|
|
104
|
+
|
|
105
|
+
def parse(self, config_path: str | None = None) -> Config:
|
|
106
|
+
"""Parse configuration from file and environment.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
config_path: Optional path to configuration file.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Parsed Config instance.
|
|
113
|
+
"""
|
|
114
|
+
return parse_config_file(config_path)
|
|
115
|
+
|
|
116
|
+
def get_default_config(self) -> Config:
|
|
117
|
+
"""Get default configuration.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Default Config instance.
|
|
121
|
+
"""
|
|
122
|
+
return Config()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Constants for Claude Skill Analyzer.
|
|
19
|
+
|
|
20
|
+
Mirrors MCP Scanner's constants structure.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SkillAnalyzerConstants:
|
|
27
|
+
"""Constants used throughout the analyzer."""
|
|
28
|
+
|
|
29
|
+
# Version
|
|
30
|
+
VERSION = "0.2.0"
|
|
31
|
+
|
|
32
|
+
# Project paths
|
|
33
|
+
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
34
|
+
PACKAGE_ROOT = Path(__file__).parent.parent
|
|
35
|
+
|
|
36
|
+
# Resource paths
|
|
37
|
+
DATA_DIR = PACKAGE_ROOT / "data"
|
|
38
|
+
PROMPTS_DIR = DATA_DIR / "prompts"
|
|
39
|
+
YARA_RULES_DIR = DATA_DIR / "yara_rules"
|
|
40
|
+
RULES_DIR = PACKAGE_ROOT / "core" / "rules"
|
|
41
|
+
|
|
42
|
+
# Default values
|
|
43
|
+
DEFAULT_MAX_FILE_SIZE_MB = 10
|
|
44
|
+
DEFAULT_SCAN_TIMEOUT = 300
|
|
45
|
+
DEFAULT_LLM_MODEL = "claude-3-5-sonnet-20241022"
|
|
46
|
+
DEFAULT_LLM_MAX_TOKENS = 4000
|
|
47
|
+
DEFAULT_LLM_TEMPERATURE = 0.0
|
|
48
|
+
|
|
49
|
+
# Severity levels
|
|
50
|
+
SEVERITY_CRITICAL = "CRITICAL"
|
|
51
|
+
SEVERITY_HIGH = "HIGH"
|
|
52
|
+
SEVERITY_MEDIUM = "MEDIUM"
|
|
53
|
+
SEVERITY_LOW = "LOW"
|
|
54
|
+
SEVERITY_INFO = "INFO"
|
|
55
|
+
SEVERITY_SAFE = "SAFE"
|
|
56
|
+
|
|
57
|
+
# Threat categories
|
|
58
|
+
THREAT_PROMPT_INJECTION = "prompt_injection"
|
|
59
|
+
THREAT_COMMAND_INJECTION = "command_injection"
|
|
60
|
+
THREAT_DATA_EXFILTRATION = "data_exfiltration"
|
|
61
|
+
THREAT_UNAUTHORIZED_TOOL = "unauthorized_tool_use"
|
|
62
|
+
THREAT_OBFUSCATION = "obfuscation"
|
|
63
|
+
THREAT_HARDCODED_SECRETS = "hardcoded_secrets"
|
|
64
|
+
THREAT_SOCIAL_ENGINEERING = "social_engineering"
|
|
65
|
+
THREAT_RESOURCE_ABUSE = "resource_abuse"
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def get_prompts_path(cls) -> Path:
|
|
69
|
+
"""Get path to prompts directory."""
|
|
70
|
+
return cls.PROMPTS_DIR
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get_rules_path(cls) -> Path:
|
|
74
|
+
"""Get path to rules directory."""
|
|
75
|
+
return cls.RULES_DIR
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def get_data_path(cls) -> Path:
|
|
79
|
+
"""Get path to data directory."""
|
|
80
|
+
return cls.DATA_DIR
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def get_yara_rules_path(cls) -> Path:
|
|
84
|
+
"""Get path to YARA rules directory."""
|
|
85
|
+
return cls.YARA_RULES_DIR
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Core functionality for Claude Skill Analyzer.
|
|
19
|
+
|
|
20
|
+
This module contains the core components including analyzers, scanner engine,
|
|
21
|
+
and data models.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
__all__ = ["analyzers", "scanner", "loader", "models"]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Copyright 2026 Cisco Systems, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
#
|
|
15
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Analyzer modules for detecting security vulnerabilities in Claude Skills.
|
|
19
|
+
|
|
20
|
+
Structure mirrors MCP Scanner's analyzer organization.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .base import BaseAnalyzer
|
|
24
|
+
|
|
25
|
+
__all__ = ["BaseAnalyzer"]
|
|
26
|
+
|
|
27
|
+
# Import available analyzers (re-exported via __all__)
|
|
28
|
+
try:
|
|
29
|
+
from .static import StaticAnalyzer # noqa: F401
|
|
30
|
+
|
|
31
|
+
__all__.append("StaticAnalyzer")
|
|
32
|
+
except (ImportError, ModuleNotFoundError):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
from .llm_analyzer import LLMAnalyzer, LLMProvider # noqa: F401
|
|
37
|
+
|
|
38
|
+
__all__.extend(["LLMAnalyzer", "LLMProvider"])
|
|
39
|
+
except (ImportError, ModuleNotFoundError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
from .behavioral_analyzer import BehavioralAnalyzer # noqa: F401
|
|
44
|
+
|
|
45
|
+
__all__.append("BehavioralAnalyzer")
|
|
46
|
+
except (ImportError, ModuleNotFoundError):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
from .aidefense_analyzer import AIDefenseAnalyzer # noqa: F401
|
|
51
|
+
|
|
52
|
+
__all__.append("AIDefenseAnalyzer")
|
|
53
|
+
except (ImportError, ModuleNotFoundError):
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
from .trigger_analyzer import TriggerAnalyzer # noqa: F401
|
|
58
|
+
|
|
59
|
+
__all__.append("TriggerAnalyzer")
|
|
60
|
+
except (ImportError, ModuleNotFoundError):
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
from .cross_skill_analyzer import CrossSkillAnalyzer # noqa: F401
|
|
65
|
+
|
|
66
|
+
__all__.append("CrossSkillAnalyzer")
|
|
67
|
+
except (ImportError, ModuleNotFoundError):
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
from .meta_analyzer import MetaAnalysisResult, MetaAnalyzer, apply_meta_analysis_to_results # noqa: F401
|
|
72
|
+
|
|
73
|
+
__all__.extend(["MetaAnalyzer", "MetaAnalysisResult", "apply_meta_analysis_to_results"])
|
|
74
|
+
except (ImportError, ModuleNotFoundError):
|
|
75
|
+
pass
|