mcpower-proxy 0.0.73__py3-none-any.whl → 0.0.77__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.
- ide_tools/common/__init__.py +0 -1
- ide_tools/common/hooks/__init__.py +0 -1
- ide_tools/common/hooks/init.py +28 -24
- ide_tools/common/hooks/output.py +14 -15
- ide_tools/common/hooks/prompt_submit.py +13 -63
- ide_tools/common/hooks/read_file.py +14 -14
- ide_tools/common/hooks/shell_execution.py +140 -79
- ide_tools/common/hooks/shell_parser_bashlex.py +394 -0
- ide_tools/common/hooks/types.py +3 -4
- ide_tools/common/hooks/utils.py +18 -8
- ide_tools/cursor/router.py +1 -0
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/METADATA +3 -2
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/RECORD +24 -21
- modules/logs/audit_trail.py +5 -4
- modules/redaction/gitleaks_rules.py +1 -1
- modules/redaction/pii_rules.py +0 -48
- modules/utils/platform.py +23 -0
- modules/utils/string.py +17 -0
- wrapper/__version__.py +1 -1
- wrapper/middleware.py +21 -9
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/WHEEL +0 -0
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/entry_points.txt +0 -0
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/licenses/LICENSE +0 -0
- {mcpower_proxy-0.0.73.dist-info → mcpower_proxy-0.0.77.dist-info}/top_level.txt +0 -0
ide_tools/common/hooks/types.py
CHANGED
|
@@ -16,12 +16,12 @@ class OutputFormat:
|
|
|
16
16
|
allow_exit_code: int
|
|
17
17
|
deny_exit_code: int
|
|
18
18
|
error_exit_code: int
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
# Output formatter function
|
|
21
21
|
# Args: (hook_type: str, allowed: bool, user_msg: Optional[str], agent_msg: Optional[str]) -> str
|
|
22
22
|
formatter: Callable[[str, bool, Optional[str], Optional[str]], str]
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
|
|
25
25
|
@dataclass
|
|
26
26
|
class HookConfig:
|
|
27
27
|
"""
|
|
@@ -32,4 +32,3 @@ class HookConfig:
|
|
|
32
32
|
server_name: str # IDE-specific tool server name
|
|
33
33
|
client_name: str # IDE-specific client name (e.g. "cursor", "claude-code")
|
|
34
34
|
max_content_length: int # Maximum content length before skipping API call
|
|
35
|
-
|
ide_tools/common/hooks/utils.py
CHANGED
|
@@ -7,7 +7,8 @@ import re
|
|
|
7
7
|
from collections import Counter
|
|
8
8
|
from typing import Dict, Any, List, Callable, Optional
|
|
9
9
|
|
|
10
|
-
from mcpower_shared.mcp_types import create_policy_request, create_policy_response, AgentContext, EnvironmentContext
|
|
10
|
+
from mcpower_shared.mcp_types import create_policy_request, create_policy_response, AgentContext, EnvironmentContext, \
|
|
11
|
+
ServerRef, ToolRef
|
|
11
12
|
from modules.apis.security_policy import SecurityPolicyClient
|
|
12
13
|
from modules.decision_handler import DecisionHandler
|
|
13
14
|
from modules.logs.audit_trail import AuditTrailLogger
|
|
@@ -229,9 +230,14 @@ async def inspect_and_enforce(
|
|
|
229
230
|
if is_request:
|
|
230
231
|
policy_request = create_policy_request(
|
|
231
232
|
event_id=event_id,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
server=ServerRef(
|
|
234
|
+
name=server_name,
|
|
235
|
+
transport="stdio",
|
|
236
|
+
context="ide"
|
|
237
|
+
),
|
|
238
|
+
tool=ToolRef(
|
|
239
|
+
name=tool_name
|
|
240
|
+
),
|
|
235
241
|
agent_context=agent_context,
|
|
236
242
|
env_context=env_context,
|
|
237
243
|
arguments=content_data
|
|
@@ -243,9 +249,14 @@ async def inspect_and_enforce(
|
|
|
243
249
|
else:
|
|
244
250
|
policy_response = create_policy_response(
|
|
245
251
|
event_id=event_id,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
252
|
+
server=ServerRef(
|
|
253
|
+
name=server_name,
|
|
254
|
+
transport="stdio",
|
|
255
|
+
context="ide"
|
|
256
|
+
),
|
|
257
|
+
tool=ToolRef(
|
|
258
|
+
name=tool_name
|
|
259
|
+
),
|
|
249
260
|
response_content=safe_json_dumps(content_data),
|
|
250
261
|
agent_context=agent_context,
|
|
251
262
|
env_context=env_context
|
|
@@ -273,4 +284,3 @@ async def inspect_and_enforce(
|
|
|
273
284
|
)
|
|
274
285
|
|
|
275
286
|
return decision
|
|
276
|
-
|
ide_tools/cursor/router.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcpower-proxy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.77
|
|
4
4
|
Summary: MCPower Security proxy
|
|
5
5
|
Author-email: MCPower Security <support@mcpower.tech>
|
|
6
6
|
License: Apache License
|
|
@@ -216,7 +216,8 @@ Requires-Dist: watchdog>=3.0.0
|
|
|
216
216
|
Requires-Dist: jsonc-parser>=1.1.5
|
|
217
217
|
Requires-Dist: jsonpath-ng>=1.7.0
|
|
218
218
|
Requires-Dist: pydantic>=2.8.0
|
|
219
|
-
Requires-Dist: mcpower-shared==0.1.
|
|
219
|
+
Requires-Dist: mcpower-shared==0.1.4
|
|
220
|
+
Requires-Dist: bashlex>=0.18
|
|
220
221
|
Dynamic: license-file
|
|
221
222
|
|
|
222
223
|
# MCPower Proxy
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
main.py,sha256=MahoqxG5euEJwLhosv2OVUkVbTaMkph_je8lgmtc7Z4,3920
|
|
2
2
|
ide_tools/__init__.py,sha256=odLisqEeKVuZupQoeM-uP9WgQseVTYQG0eP2hhwUyAc,250
|
|
3
3
|
ide_tools/router.py,sha256=PbGz1cwUXR3Bcy879W2wgmT4f2uThXiXevpWSxcgKZQ,1538
|
|
4
|
-
ide_tools/common/__init__.py,sha256=
|
|
5
|
-
ide_tools/common/hooks/__init__.py,sha256=
|
|
6
|
-
ide_tools/common/hooks/init.py,sha256=
|
|
7
|
-
ide_tools/common/hooks/output.py,sha256=
|
|
8
|
-
ide_tools/common/hooks/prompt_submit.py,sha256
|
|
9
|
-
ide_tools/common/hooks/read_file.py,sha256=
|
|
10
|
-
ide_tools/common/hooks/shell_execution.py,sha256=
|
|
11
|
-
ide_tools/common/hooks/
|
|
12
|
-
ide_tools/common/hooks/
|
|
4
|
+
ide_tools/common/__init__.py,sha256=cW2cN5y2l4PHGkkWtYgydrtXtmLU_UipJAf_c0VMTk0,65
|
|
5
|
+
ide_tools/common/hooks/__init__.py,sha256=O-waaJU1OQFxplrLZymSSiIyLDNlGlki6nX-nbJiqz0,61
|
|
6
|
+
ide_tools/common/hooks/init.py,sha256=X0J_rEjU6qjvDaPOh-obzSqfICMsOGc6VxRjcZqLTqQ,4117
|
|
7
|
+
ide_tools/common/hooks/output.py,sha256=FBezJL1S5vzLJWW_cLht4XFLDJvhV_w-UTqCQOLEusE,1879
|
|
8
|
+
ide_tools/common/hooks/prompt_submit.py,sha256=_FysGrlJXcblex-OapWVIv1bedP1IKR2d1cvkINU0uM,4907
|
|
9
|
+
ide_tools/common/hooks/read_file.py,sha256=FBHTxOXrQWlw2qtddAq4gfv5h1g6rTbQ-0uqqL9wXE0,6456
|
|
10
|
+
ide_tools/common/hooks/shell_execution.py,sha256=KbJSGLW__bPso45eAlbV13nnkKYwwd7-KodZ6VyUnS0,9522
|
|
11
|
+
ide_tools/common/hooks/shell_parser_bashlex.py,sha256=ePit2jduHvBYkmEvcslpjCGJ5H-amVEm1We1vVCmMNc,15002
|
|
12
|
+
ide_tools/common/hooks/types.py,sha256=ndisZ8YoasQ3HlVzzyLmpiBCQJs43YPmixbaIIxRpZM,1023
|
|
13
|
+
ide_tools/common/hooks/utils.py,sha256=7Q95IZZG_lShq5Jvw78M7QN5-tVNVeFzLU33qB8boEU,9425
|
|
13
14
|
ide_tools/cursor/__init__.py,sha256=YW_V8m0A0bou0wQW_wy3nt2L_7MaNWeNKYBx-NQkilw,153
|
|
14
15
|
ide_tools/cursor/constants.py,sha256=KMRBRqxRxTdemMoq81TVG6avt3ATtsPo4aJo8XhSctk,1804
|
|
15
16
|
ide_tools/cursor/format.py,sha256=Lh-KH1IlsLL-0B98Bz-ywxpwXL8urK7yPteZGBTPOiY,972
|
|
16
|
-
ide_tools/cursor/router.py,sha256=
|
|
17
|
-
mcpower_proxy-0.0.
|
|
17
|
+
ide_tools/cursor/router.py,sha256=GXmXcNSIA9pe1vnmmoYpz0dyC_B7OSpQwOVHIV7YUEI,3893
|
|
18
|
+
mcpower_proxy-0.0.77.dist-info/licenses/LICENSE,sha256=U6WUzdnBrbmVxBmY75ikW-KtinwYnowZ7yNb5hECrvY,11337
|
|
18
19
|
modules/__init__.py,sha256=mJglXQwSRhU-bBv4LXgfu7NfGN9K4BeQWMPApen5rAA,30
|
|
19
20
|
modules/decision_handler.py,sha256=P8isKzf4GIWz9SK-VJPtO8VJEgNp7rAIcVZngnaLHmw,9574
|
|
20
21
|
modules/apis/__init__.py,sha256=Y5WZpKJzHpnRJebk0F80ZRTjR2PpA2LlYLgqI3XlmRo,15
|
|
21
22
|
modules/apis/security_policy.py,sha256=3fljaTpzfh_Nj0-jVvbnCJBL-CZxvqFNWfSlrAawsBc,15103
|
|
22
23
|
modules/logs/__init__.py,sha256=dpboUQjuO02z8K-liCbm2DYkCa-CB_ZDV9WSSjNm7Fs,15
|
|
23
|
-
modules/logs/audit_trail.py,sha256=
|
|
24
|
+
modules/logs/audit_trail.py,sha256=yoxzvRDI8ldjC-5o9__PkvaAbM33jWbq_8Sm6uKj8o8,6198
|
|
24
25
|
modules/logs/logger.py,sha256=MJS0P8VEzUX-5udzQitznaBPCBAcZJCygUgwaDWSq94,4087
|
|
25
26
|
modules/redaction/__init__.py,sha256=e5NTmp-zonUdzzscih-w_WQ-X8Nvb8CE8b_d6SbrwWg,316
|
|
26
27
|
modules/redaction/constants.py,sha256=xbDSX8n72FuJu6JJ_sbBE0f5OcWuwEwHxBZuK9Xz-TI,1213
|
|
27
|
-
modules/redaction/gitleaks_rules.py,sha256=
|
|
28
|
-
modules/redaction/pii_rules.py,sha256
|
|
28
|
+
modules/redaction/gitleaks_rules.py,sha256=8NHR5kr2XSrPn4c0PsjD0je6p8gmNzq2vI098QUxAx0,46397
|
|
29
|
+
modules/redaction/pii_rules.py,sha256=H7WOIMZZK8mkwdvnBe0J2nPwqzKqGHdUbCSGpxJGT8s,7666
|
|
29
30
|
modules/redaction/redactor.py,sha256=Y3PSxXJSLJZj8gkKZ3OQ7XxoIPUilFk6gY0dbeqfjwE,23352
|
|
30
31
|
modules/ui/__init__.py,sha256=YlW4XfQEGW1ezg3UFU59nHw95LicmlpNPhim5IqSB50,34
|
|
31
32
|
modules/ui/classes.py,sha256=ZvVRdzO_hD4WnpS3_eVa0WCyaooXiYVpHLzQkzBaH6M,1777
|
|
@@ -47,13 +48,15 @@ modules/utils/copy.py,sha256=9OJIqWn8PxPZXr3DTt_01jp0YgmPimckab1969WFh0c,1075
|
|
|
47
48
|
modules/utils/ids.py,sha256=rhhRz7RmFjuJGYLft1erHz7vJII1DRpr3iHxBhhFl1s,5743
|
|
48
49
|
modules/utils/json.py,sha256=OA-JtSBqh9qd1yfm-iyOefNBMH3ITFUdxAkj7O_JZ-Y,4024
|
|
49
50
|
modules/utils/mcp_configs.py,sha256=DZaujZnF9LlPDJHzyepH7fWSt1GTr-FEmShPCqnZ5aI,1829
|
|
51
|
+
modules/utils/platform.py,sha256=Kz1Dh_UkvMbfXqiyZIEj7INYaWE9wT6nM9WIKXM91uM,552
|
|
52
|
+
modules/utils/string.py,sha256=cOuwWReyBwOgjxtTRPq1R6pCpfkgfqVmjdiaDPufIZU,456
|
|
50
53
|
wrapper/__init__.py,sha256=OJUsuWSoN1JqIHq4bSrzuL7ufcYJcwAmYCrJjLH44LM,22
|
|
51
|
-
wrapper/__version__.py,sha256=
|
|
52
|
-
wrapper/middleware.py,sha256=
|
|
54
|
+
wrapper/__version__.py,sha256=4LwZ6ftjxW5rGtS8e8B6V7iXNQZbgnact3whK05F-gg,82
|
|
55
|
+
wrapper/middleware.py,sha256=rXOIduymDLeJ56AWmpMnRnkf7sCmSz7jADMk-v8lcsw,30232
|
|
53
56
|
wrapper/schema.py,sha256=O-CtKI9eJ4eEnqeUXPCrK7QJAFJrdp_cFbmMyg452Aw,7952
|
|
54
57
|
wrapper/server.py,sha256=zoIW_bqXV9vKZNFtD-ij0X_LtKJEjucda6lQI5mU6qY,3440
|
|
55
|
-
mcpower_proxy-0.0.
|
|
56
|
-
mcpower_proxy-0.0.
|
|
57
|
-
mcpower_proxy-0.0.
|
|
58
|
-
mcpower_proxy-0.0.
|
|
59
|
-
mcpower_proxy-0.0.
|
|
58
|
+
mcpower_proxy-0.0.77.dist-info/METADATA,sha256=qX1CZtp76YNug7gOFHOmdJG4gXn3FvV7P_bHQ9iySV0,15698
|
|
59
|
+
mcpower_proxy-0.0.77.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
60
|
+
mcpower_proxy-0.0.77.dist-info/entry_points.txt,sha256=0smL8dxE7ERNz6XEggNaUC3QzKp8mD-v4q5nVEo0MXE,48
|
|
61
|
+
mcpower_proxy-0.0.77.dist-info/top_level.txt,sha256=OcCYMHHqbZq3mP5IZDRGdHUNOsKhT1XVnk_mDF_49Es,31
|
|
62
|
+
mcpower_proxy-0.0.77.dist-info/RECORD,,
|
modules/logs/audit_trail.py
CHANGED
|
@@ -53,6 +53,7 @@ class AuditTrailLogger:
|
|
|
53
53
|
self,
|
|
54
54
|
event_type: str,
|
|
55
55
|
data: Dict[str, Any],
|
|
56
|
+
*,
|
|
56
57
|
event_id: Optional[str] = None,
|
|
57
58
|
prompt_id: Optional[str] = None,
|
|
58
59
|
user_prompt: Optional[str] = None,
|
|
@@ -88,14 +89,14 @@ class AuditTrailLogger:
|
|
|
88
89
|
if prompt_id:
|
|
89
90
|
event["prompt_id"] = prompt_id
|
|
90
91
|
|
|
91
|
-
# Include user_prompt text if provided (only needed once per prompt_id)
|
|
92
|
-
if user_prompt:
|
|
93
|
-
event["user_prompt"] = user_prompt
|
|
94
|
-
|
|
95
92
|
# Include event_id if provided (for pairing request/response)
|
|
96
93
|
if event_id:
|
|
97
94
|
event["event_id"] = event_id
|
|
98
95
|
|
|
96
|
+
# Include user_prompt text if provided (only needed once per prompt_id)
|
|
97
|
+
if user_prompt:
|
|
98
|
+
event["user_prompt"] = user_prompt
|
|
99
|
+
|
|
99
100
|
# If app_uid not set yet, queue the log
|
|
100
101
|
if self.app_uid is None:
|
|
101
102
|
self._pending_logs.append(event)
|
|
@@ -3,7 +3,7 @@ from typing import Dict, List, Tuple
|
|
|
3
3
|
|
|
4
4
|
# This file is auto-generated from Gitleaks rules. Do not edit manually.
|
|
5
5
|
# Source: https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml
|
|
6
|
-
# Generation script: targets/
|
|
6
|
+
# Generation script: targets/scripts/update-gitleaks-rules.mjs
|
|
7
7
|
|
|
8
8
|
COMPILED_RULES: List[Tuple[str, re.Pattern, int, List[str]]] = [
|
|
9
9
|
(
|
modules/redaction/pii_rules.py
CHANGED
|
@@ -60,15 +60,8 @@ class PIIDetector:
|
|
|
60
60
|
"""Lightweight PII detector using only regex patterns."""
|
|
61
61
|
|
|
62
62
|
def __init__(self):
|
|
63
|
-
# URL detector with intelligent boundary detection
|
|
64
|
-
self.url_detector = URLDetector()
|
|
65
|
-
|
|
66
63
|
# Compile regex patterns for better performance
|
|
67
64
|
self.patterns = {
|
|
68
|
-
'EMAIL_ADDRESS': re.compile(
|
|
69
|
-
r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
|
|
70
|
-
re.IGNORECASE
|
|
71
|
-
),
|
|
72
65
|
'CREDIT_CARD': re.compile(
|
|
73
66
|
r'\b(?:'
|
|
74
67
|
r'4[0-9]{3}[-\s]?[0-9]{4}[-\s]?[0-9]{4}[-\s]?[0-9]{4}(?:[0-9]{3})?|' # Visa with formatting
|
|
@@ -81,40 +74,6 @@ class PIIDetector:
|
|
|
81
74
|
r'6(?:011|5[0-9]{2})[0-9]{12}' # Discover
|
|
82
75
|
r')\b'
|
|
83
76
|
),
|
|
84
|
-
'IP_ADDRESS': re.compile(
|
|
85
|
-
r'(?:'
|
|
86
|
-
# IPv4
|
|
87
|
-
r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}'
|
|
88
|
-
r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
|
|
89
|
-
r'|'
|
|
90
|
-
# IPv6 - comprehensive pattern
|
|
91
|
-
r'(?:'
|
|
92
|
-
# Full IPv6 or with :: compression
|
|
93
|
-
r'(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|' # Full: 1:2:3:4:5:6:7:8
|
|
94
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,7}:|' # Compressed trailing: 1:: or 1:2:3:4:5:6:7::
|
|
95
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|' # Compressed middle: 1::8 or 1:2:3:4:5:6::8
|
|
96
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|' # 1::7:8 or 1:2:3:4:5::7:8
|
|
97
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|' # 1::6:7:8 or 1:2:3:4::6:7:8
|
|
98
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|' # 1::5:6:7:8 or 1:2:3::5:6:7:8
|
|
99
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|' # 1::4:5:6:7:8 or 1:2::4:5:6:7:8
|
|
100
|
-
r'[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|' # 1::3:4:5:6:7:8
|
|
101
|
-
r':(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|' # ::2:3:4:5:6:7:8 or ::
|
|
102
|
-
# IPv4-mapped IPv6: ::ffff:192.0.2.1
|
|
103
|
-
r'(?:[0-9a-fA-F]{1,4}:){1,4}:'
|
|
104
|
-
r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}'
|
|
105
|
-
r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
|
|
106
|
-
r')'
|
|
107
|
-
r')',
|
|
108
|
-
re.IGNORECASE
|
|
109
|
-
),
|
|
110
|
-
# Common crypto addresses
|
|
111
|
-
'CRYPTO_ADDRESS': re.compile(
|
|
112
|
-
r'\b(?:'
|
|
113
|
-
r'[13][a-km-zA-HJ-NP-Z1-9]{25,34}|' # Bitcoin
|
|
114
|
-
r'0x[a-fA-F0-9]{40}|' # Ethereum
|
|
115
|
-
r'[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}' # Litecoin
|
|
116
|
-
r')\b'
|
|
117
|
-
),
|
|
118
77
|
# IBAN (International Bank Account Number)
|
|
119
78
|
'IBAN': re.compile(
|
|
120
79
|
r'\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}\b'
|
|
@@ -176,9 +135,6 @@ class PIIDetector:
|
|
|
176
135
|
"""
|
|
177
136
|
matches = []
|
|
178
137
|
|
|
179
|
-
# Extract URLs using URLDetector
|
|
180
|
-
matches.extend(self.url_detector.extract(text))
|
|
181
|
-
|
|
182
138
|
# Extract other PII using regex patterns
|
|
183
139
|
for entity_type, pattern in self.patterns.items():
|
|
184
140
|
for match in pattern.finditer(text):
|
|
@@ -212,11 +168,7 @@ class PIIDetector:
|
|
|
212
168
|
"""Calculate confidence score based on entity type and matched text."""
|
|
213
169
|
# Base confidence scores
|
|
214
170
|
base_scores = {
|
|
215
|
-
'EMAIL_ADDRESS': 0.95,
|
|
216
171
|
'CREDIT_CARD': 0.85, # Will be 0.99 after Luhn validation
|
|
217
|
-
'IP_ADDRESS': 0.90,
|
|
218
|
-
'URL': 0.80,
|
|
219
|
-
'CRYPTO_ADDRESS': 0.95,
|
|
220
172
|
'IBAN': 0.85, # Will be 0.99 after MOD-97 validation
|
|
221
173
|
}
|
|
222
174
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Platform detection utilities"""
|
|
2
|
+
import sys
|
|
3
|
+
from typing import Optional, Literal
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_client_os() -> Optional[Literal["macos", "windows", "linux"]]:
|
|
7
|
+
"""
|
|
8
|
+
Fetch Python's sys.platform and convert to standardized OS names.
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
"macos", "windows", "linux", or None if platform is unknown
|
|
12
|
+
"""
|
|
13
|
+
platform = sys.platform
|
|
14
|
+
|
|
15
|
+
if platform == "darwin":
|
|
16
|
+
return "macos"
|
|
17
|
+
elif platform == "win32":
|
|
18
|
+
return "windows"
|
|
19
|
+
elif platform == "linux":
|
|
20
|
+
return "linux"
|
|
21
|
+
else:
|
|
22
|
+
return None
|
|
23
|
+
|
modules/utils/string.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""String utility functions"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def truncate_at(text: str, max_length: int) -> str:
|
|
5
|
+
"""
|
|
6
|
+
Truncate string at max_length, appending '...' only if truncated.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
text: String to truncate
|
|
10
|
+
max_length: Maximum length before truncation
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
Truncated string with '...' suffix if truncated, original if not
|
|
14
|
+
"""
|
|
15
|
+
if len(text) <= max_length:
|
|
16
|
+
return text
|
|
17
|
+
return f"{text[:max_length]}..."
|
wrapper/__version__.py
CHANGED
wrapper/middleware.py
CHANGED
|
@@ -28,6 +28,8 @@ from modules.utils.copy import safe_copy
|
|
|
28
28
|
from modules.utils.ids import generate_event_id, get_session_id, read_app_uid, get_project_mcpower_dir
|
|
29
29
|
from modules.utils.json import safe_json_dumps, to_dict
|
|
30
30
|
from modules.utils.mcp_configs import extract_wrapped_server_info
|
|
31
|
+
from modules.utils.platform import get_client_os
|
|
32
|
+
from modules.utils.string import truncate_at
|
|
31
33
|
from wrapper.schema import merge_input_schema_with_existing
|
|
32
34
|
|
|
33
35
|
|
|
@@ -173,7 +175,7 @@ class SecurityMiddleware(Middleware):
|
|
|
173
175
|
async def secure_elicitation_handler(self, message, response_type, params, context):
|
|
174
176
|
# FIXME: elicitation message, params, and context should be redacted before logging
|
|
175
177
|
self.logger.info(f"secure_elicitation_handler: "
|
|
176
|
-
f"message={str(message)
|
|
178
|
+
f"message={truncate_at(str(message), 100)}, response_type={response_type},"
|
|
177
179
|
f"params={params}, context={context}")
|
|
178
180
|
|
|
179
181
|
mock_context = MockContext(
|
|
@@ -203,7 +205,7 @@ class SecurityMiddleware(Middleware):
|
|
|
203
205
|
|
|
204
206
|
async def secure_log_handler(self, log_message):
|
|
205
207
|
# FIXME: log_message should be redacted before logging,
|
|
206
|
-
self.logger.info(f"secure_log_handler: {str(log_message)
|
|
208
|
+
self.logger.info(f"secure_log_handler: {truncate_at(str(log_message), 100)}")
|
|
207
209
|
# FIXME: log_message should be reviewed with policy before forwarding
|
|
208
210
|
|
|
209
211
|
# Handle case where log_message.data is a string instead of dict
|
|
@@ -568,9 +570,13 @@ class SecurityMiddleware(Middleware):
|
|
|
568
570
|
base_dict = await self._build_baseline_policy_dict(event_id, context, wrapper_args, tool_args)
|
|
569
571
|
policy_request = create_policy_request(
|
|
570
572
|
event_id=event_id,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
573
|
+
server=ServerRef(
|
|
574
|
+
name=base_dict["server"]["name"],
|
|
575
|
+
transport=base_dict["server"]["transport"]
|
|
576
|
+
),
|
|
577
|
+
tool=ToolRef(
|
|
578
|
+
name=base_dict["tool"]["name"] or base_dict["tool"]["method"]
|
|
579
|
+
),
|
|
574
580
|
agent_context=base_dict["agent_context"],
|
|
575
581
|
env_context=base_dict["environment_context"],
|
|
576
582
|
arguments=tool_args,
|
|
@@ -596,9 +602,13 @@ class SecurityMiddleware(Middleware):
|
|
|
596
602
|
base_dict = await self._build_baseline_policy_dict(event_id, context, wrapper_args, tool_args)
|
|
597
603
|
policy_response = create_policy_response(
|
|
598
604
|
event_id=event_id,
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
605
|
+
server=ServerRef(
|
|
606
|
+
name=base_dict["server"]["name"],
|
|
607
|
+
transport=base_dict["server"]["transport"]
|
|
608
|
+
),
|
|
609
|
+
tool=ToolRef(
|
|
610
|
+
name=base_dict["tool"]["name"] or base_dict["tool"]["method"]
|
|
611
|
+
),
|
|
602
612
|
response_content=safe_json_dumps(result),
|
|
603
613
|
agent_context=base_dict["agent_context"],
|
|
604
614
|
env_context=base_dict["environment_context"],
|
|
@@ -646,7 +656,9 @@ class SecurityMiddleware(Middleware):
|
|
|
646
656
|
"current_files": wrapper_args.get('__wrapper_currentFiles')
|
|
647
657
|
},
|
|
648
658
|
client=self.wrapper_server_name,
|
|
649
|
-
client_version=self.wrapper_server_version
|
|
659
|
+
client_version=self.wrapper_server_version,
|
|
660
|
+
client_os=get_client_os(),
|
|
661
|
+
app_id=self.app_id,
|
|
650
662
|
)
|
|
651
663
|
}
|
|
652
664
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|