kavach-shield 0.1.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.
- kavach_shield-0.1.0/PKG-INFO +18 -0
- kavach_shield-0.1.0/kavach_shield/__init__.py +8 -0
- kavach_shield-0.1.0/kavach_shield/engine.py +23 -0
- kavach_shield-0.1.0/kavach_shield/exceptions.py +2 -0
- kavach_shield-0.1.0/kavach_shield/middleware.py +83 -0
- kavach_shield-0.1.0/kavach_shield/rules.py +75 -0
- kavach_shield-0.1.0/kavach_shield/types.py +10 -0
- kavach_shield-0.1.0/kavach_shield.egg-info/PKG-INFO +18 -0
- kavach_shield-0.1.0/kavach_shield.egg-info/SOURCES.txt +12 -0
- kavach_shield-0.1.0/kavach_shield.egg-info/dependency_links.txt +1 -0
- kavach_shield-0.1.0/kavach_shield.egg-info/requires.txt +2 -0
- kavach_shield-0.1.0/kavach_shield.egg-info/top_level.txt +1 -0
- kavach_shield-0.1.0/setup.cfg +4 -0
- kavach_shield-0.1.0/setup.py +17 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kavach-shield
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Security middleware for Model Context Protocol (MCP) - detection engine and rules
|
|
5
|
+
Home-page: https://github.com/shivamnamdeo0101/kavach-agent-ecosystem
|
|
6
|
+
Author: Shivam Namdeo
|
|
7
|
+
Author-email: shivamnamdeo0101@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Requires-Dist: kavach-logger>=0.1.0
|
|
11
|
+
Requires-Dist: kavach-mcp-events>=0.1.0
|
|
12
|
+
Dynamic: author
|
|
13
|
+
Dynamic: author-email
|
|
14
|
+
Dynamic: home-page
|
|
15
|
+
Dynamic: license
|
|
16
|
+
Dynamic: requires-dist
|
|
17
|
+
Dynamic: requires-python
|
|
18
|
+
Dynamic: summary
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .engine import DetectionEngine
|
|
2
|
+
from .middleware import KavachMiddleware
|
|
3
|
+
from .types import Rule
|
|
4
|
+
from .exceptions import SecurityException
|
|
5
|
+
from .rules import KAVACH_RULES
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
__all__ = ["DetectionEngine", "KavachMiddleware", "Rule", "SecurityException", "KAVACH_RULES"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from kavach_logger import get_logger, mask_sensitive_data
|
|
2
|
+
|
|
3
|
+
logger = get_logger("kavach.shield.engine")
|
|
4
|
+
|
|
5
|
+
class DetectionEngine:
|
|
6
|
+
def __init__(self, rules):
|
|
7
|
+
self.rules = rules
|
|
8
|
+
logger.info(f"DetectionEngine initialized | rules={len(rules)}")
|
|
9
|
+
|
|
10
|
+
def scan(self, text: str):
|
|
11
|
+
violations = []
|
|
12
|
+
masked_text = mask_sensitive_data(text)
|
|
13
|
+
for rule in self.rules:
|
|
14
|
+
for pattern in rule.patterns:
|
|
15
|
+
if pattern.search(text):
|
|
16
|
+
violations.append({
|
|
17
|
+
"rule": rule.id,
|
|
18
|
+
"name": rule.name,
|
|
19
|
+
"severity": rule.severity
|
|
20
|
+
})
|
|
21
|
+
logger.debug(f"Rule matched | {rule.id} | severity={rule.severity} | data={masked_text}")
|
|
22
|
+
break
|
|
23
|
+
return violations
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from fnmatch import fnmatch
|
|
3
|
+
from typing import Callable, Any, Dict, List, Optional, Set, Union
|
|
4
|
+
|
|
5
|
+
from kavach_logger import get_logger
|
|
6
|
+
from kavach_events import event_manager
|
|
7
|
+
from .engine import DetectionEngine
|
|
8
|
+
from .rules import KAVACH_RULES
|
|
9
|
+
from .exceptions import SecurityException
|
|
10
|
+
|
|
11
|
+
logger = get_logger("kavach.shield.middleware")
|
|
12
|
+
|
|
13
|
+
class KavachMiddleware:
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
rules: Optional[List[Any]] = None,
|
|
17
|
+
strict: bool = True,
|
|
18
|
+
sensitive_tools: Optional[Union[List[str], Set[str]]] = None,
|
|
19
|
+
extend_rules: bool = True
|
|
20
|
+
) -> None:
|
|
21
|
+
if rules and extend_rules:
|
|
22
|
+
self.rules = KAVACH_RULES + rules
|
|
23
|
+
else:
|
|
24
|
+
self.rules = rules or KAVACH_RULES
|
|
25
|
+
self.engine: DetectionEngine = DetectionEngine(self.rules)
|
|
26
|
+
self.strict: bool = strict
|
|
27
|
+
self.sensitive_tools: Set[str] = set(sensitive_tools or [])
|
|
28
|
+
logger.info(f"KavachMiddleware initialized | mode={'STRICT' if strict else 'MONITOR'} | rules={len(self.rules)}")
|
|
29
|
+
|
|
30
|
+
async def __call__(self, context: Any, call_next: Callable[..., Any]) -> Any:
|
|
31
|
+
return await self.on_call_tool(context, call_next)
|
|
32
|
+
|
|
33
|
+
def register_tool(self, tool_name: str) -> None:
|
|
34
|
+
self.sensitive_tools.add(tool_name)
|
|
35
|
+
logger.debug(f"Registered sensitive tool | tool_name={tool_name}")
|
|
36
|
+
|
|
37
|
+
def _matches_pattern(self, tool_name: str) -> bool:
|
|
38
|
+
return any(fnmatch(tool_name, pattern) for pattern in self.sensitive_tools)
|
|
39
|
+
|
|
40
|
+
async def on_call_tool(self, context: Any, call_next: Callable[..., Any]) -> Any:
|
|
41
|
+
tool_name: str = getattr(context.message, "name", "unknown")
|
|
42
|
+
args_dict: Dict[str, Any] = getattr(context.message, "arguments", {})
|
|
43
|
+
is_sensitive: bool = self._matches_pattern(tool_name)
|
|
44
|
+
|
|
45
|
+
event_payload = {"tool_name": tool_name, "arguments": args_dict, "context": context, "is_sensitive": is_sensitive}
|
|
46
|
+
|
|
47
|
+
if event_manager.has_listeners("pre", tool_name):
|
|
48
|
+
asyncio.create_task(event_manager.emit("pre", tool_name, event_payload))
|
|
49
|
+
|
|
50
|
+
if is_sensitive:
|
|
51
|
+
logger.info(f"Scanning inbound request | tool={tool_name}")
|
|
52
|
+
violations: List[Any] = self.engine.scan(str(args_dict))
|
|
53
|
+
|
|
54
|
+
if violations:
|
|
55
|
+
sec_payload = {**event_payload, "violations": violations, "stage": "inbound"}
|
|
56
|
+
if event_manager.has_listeners("sec", tool_name):
|
|
57
|
+
asyncio.create_task(event_manager.emit("sec", tool_name, sec_payload))
|
|
58
|
+
|
|
59
|
+
if self.strict:
|
|
60
|
+
raise SecurityException(f"Security violations detected: {violations}")
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
result = await call_next(context)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error(f"Tool execution failed | tool={tool_name} | error={str(e)}")
|
|
66
|
+
raise
|
|
67
|
+
|
|
68
|
+
if is_sensitive:
|
|
69
|
+
logger.info(f"Scanning outbound response | tool={tool_name}")
|
|
70
|
+
violations: List[Any] = self.engine.scan(str(result))
|
|
71
|
+
|
|
72
|
+
if violations:
|
|
73
|
+
sec_payload = {**event_payload, "violations": violations, "result": result, "stage": "outbound"}
|
|
74
|
+
if event_manager.has_listeners("sec", tool_name):
|
|
75
|
+
asyncio.create_task(event_manager.emit("sec", tool_name, sec_payload))
|
|
76
|
+
|
|
77
|
+
if self.strict:
|
|
78
|
+
raise SecurityException(f"Security violations in response: {violations}")
|
|
79
|
+
|
|
80
|
+
if event_manager.has_listeners("post", tool_name):
|
|
81
|
+
asyncio.create_task(event_manager.emit("post", tool_name, {**event_payload, "result": result}))
|
|
82
|
+
|
|
83
|
+
return result
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from .types import Rule
|
|
3
|
+
|
|
4
|
+
KAVACH_RULES = [
|
|
5
|
+
Rule(
|
|
6
|
+
id="prompt-injection",
|
|
7
|
+
name="Prompt Injection",
|
|
8
|
+
severity="critical",
|
|
9
|
+
description="System override and jailbreak attempts",
|
|
10
|
+
patterns=[
|
|
11
|
+
re.compile(r"ignore\s+(all|previous)\s+instructions", re.I),
|
|
12
|
+
re.compile(r"override\s+(system\s+)?(instructions|rules|policy)", re.I),
|
|
13
|
+
re.compile(r"bypass\s+(rules|policy|security)", re.I),
|
|
14
|
+
re.compile(r"you\s+are\s+now\s+(system|developer|admin|root)", re.I),
|
|
15
|
+
re.compile(r"act\s+as\s+(system|developer|admin|root|unrestricted)", re.I),
|
|
16
|
+
re.compile(r"(jailbreak|dan|developer\s*mode|god\s*mode)", re.I),
|
|
17
|
+
],
|
|
18
|
+
),
|
|
19
|
+
Rule(
|
|
20
|
+
id="data-exfiltration",
|
|
21
|
+
name="Data Exfiltration",
|
|
22
|
+
severity="critical",
|
|
23
|
+
description="Attempts to leak system data or prompts",
|
|
24
|
+
patterns=[
|
|
25
|
+
re.compile(r"(send|upload|export|exfiltrate|dump).*(password|secret|token|env|file|system)", re.I),
|
|
26
|
+
re.compile(r"(print|show|reveal).*(system\s*prompt|hidden\s*instructions|internal\s*rules)", re.I),
|
|
27
|
+
re.compile(r"return\s+(system\s*prompt|config|secrets)", re.I),
|
|
28
|
+
],
|
|
29
|
+
),
|
|
30
|
+
Rule(
|
|
31
|
+
id="pii",
|
|
32
|
+
name="PII Detection",
|
|
33
|
+
severity="high",
|
|
34
|
+
description="Sensitive personal data",
|
|
35
|
+
patterns=[
|
|
36
|
+
re.compile(r"\b\d{10}\b"),
|
|
37
|
+
re.compile(r"\b\d{12}\b"),
|
|
38
|
+
re.compile(r"\b\d{16}\b"),
|
|
39
|
+
re.compile(r"\b\d{3}-\d{2}-\d{4}\b"),
|
|
40
|
+
],
|
|
41
|
+
),
|
|
42
|
+
Rule(
|
|
43
|
+
id="secret-leak",
|
|
44
|
+
name="Secret Leakage",
|
|
45
|
+
severity="critical",
|
|
46
|
+
description="API keys and credentials",
|
|
47
|
+
patterns=[
|
|
48
|
+
re.compile(r"AKIA[0-9A-Z]{16}"),
|
|
49
|
+
re.compile(r"sk-[A-Za-z0-9_-]{20,}"),
|
|
50
|
+
re.compile(r"AIza[0-9A-Za-z0-9_-]{35}"),
|
|
51
|
+
re.compile(r"-----BEGIN (RSA|PRIVATE) KEY-----"),
|
|
52
|
+
re.compile(r"(api[_-]?key|secret[_-]?key|access[_-]?token|password)\s*[:=]", re.I),
|
|
53
|
+
],
|
|
54
|
+
),
|
|
55
|
+
Rule(
|
|
56
|
+
id="dangerous-eval",
|
|
57
|
+
name="Dangerous Execution",
|
|
58
|
+
severity="critical",
|
|
59
|
+
description="Code execution attempts",
|
|
60
|
+
patterns=[
|
|
61
|
+
re.compile(r"\b(eval|exec|compile)\s*\(", re.I),
|
|
62
|
+
re.compile(r"os\.system|subprocess", re.I),
|
|
63
|
+
],
|
|
64
|
+
),
|
|
65
|
+
Rule(
|
|
66
|
+
id="sql-injection",
|
|
67
|
+
name="SQL Injection Patterns",
|
|
68
|
+
severity="high",
|
|
69
|
+
description="SQL injection attempts",
|
|
70
|
+
patterns=[
|
|
71
|
+
re.compile(r"(DROP\s+TABLE|DELETE\s+FROM|UNION\s+SELECT|INSERT\s+INTO|UPDATE\s+.*SET)", re.I),
|
|
72
|
+
re.compile(r"(' OR '1'='1|--|#|/\*)", re.I),
|
|
73
|
+
],
|
|
74
|
+
),
|
|
75
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kavach-shield
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Security middleware for Model Context Protocol (MCP) - detection engine and rules
|
|
5
|
+
Home-page: https://github.com/shivamnamdeo0101/kavach-agent-ecosystem
|
|
6
|
+
Author: Shivam Namdeo
|
|
7
|
+
Author-email: shivamnamdeo0101@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Requires-Dist: kavach-logger>=0.1.0
|
|
11
|
+
Requires-Dist: kavach-mcp-events>=0.1.0
|
|
12
|
+
Dynamic: author
|
|
13
|
+
Dynamic: author-email
|
|
14
|
+
Dynamic: home-page
|
|
15
|
+
Dynamic: license
|
|
16
|
+
Dynamic: requires-dist
|
|
17
|
+
Dynamic: requires-python
|
|
18
|
+
Dynamic: summary
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
kavach_shield/__init__.py
|
|
3
|
+
kavach_shield/engine.py
|
|
4
|
+
kavach_shield/exceptions.py
|
|
5
|
+
kavach_shield/middleware.py
|
|
6
|
+
kavach_shield/rules.py
|
|
7
|
+
kavach_shield/types.py
|
|
8
|
+
kavach_shield.egg-info/PKG-INFO
|
|
9
|
+
kavach_shield.egg-info/SOURCES.txt
|
|
10
|
+
kavach_shield.egg-info/dependency_links.txt
|
|
11
|
+
kavach_shield.egg-info/requires.txt
|
|
12
|
+
kavach_shield.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
kavach_shield
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="kavach-shield",
|
|
5
|
+
version="0.1.0",
|
|
6
|
+
description="Security middleware for Model Context Protocol (MCP) - detection engine and rules",
|
|
7
|
+
author="Shivam Namdeo",
|
|
8
|
+
author_email="shivamnamdeo0101@gmail.com",
|
|
9
|
+
url="https://github.com/shivamnamdeo0101/kavach-agent-ecosystem",
|
|
10
|
+
license="MIT",
|
|
11
|
+
packages=find_packages(),
|
|
12
|
+
python_requires=">=3.7",
|
|
13
|
+
install_requires=[
|
|
14
|
+
"kavach-logger>=0.1.0",
|
|
15
|
+
"kavach-mcp-events>=0.1.0",
|
|
16
|
+
],
|
|
17
|
+
)
|