enkryptai-sdk 1.0.20__tar.gz → 1.0.22__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.
- enkryptai_sdk-1.0.22/PKG-INFO +42 -0
- enkryptai_sdk-1.0.22/README.md +19 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/setup.py +1 -1
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/guardrails.py +113 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/red_team.py +44 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/guardrails.py +91 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/red_team.py +28 -0
- enkryptai_sdk-1.0.22/src/enkryptai_sdk.egg-info/PKG-INFO +42 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_ai_proxy.py +2 -2
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_all_v2.py +50 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_guardrails.py +40 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_redteam.py +22 -12
- enkryptai_sdk-1.0.20/PKG-INFO +0 -1994
- enkryptai_sdk-1.0.20/README.md +0 -1971
- enkryptai_sdk-1.0.20/src/enkryptai_sdk.egg-info/PKG-INFO +0 -1994
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/LICENSE +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/setup.cfg +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/__init__.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/ai_proxy.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/base.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/coc.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/config.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/datasets.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/deployments.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/__init__.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/ai_proxy.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/base.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/coc.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/common.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/datasets.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/deployments.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/dto/models.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/evals.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/guardrails_old.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/models.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk/response.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/SOURCES.txt +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/dependency_links.txt +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/src/enkryptai_sdk.egg-info/top_level.txt +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_all.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_basic.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_coc.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_datasets.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_deployments.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_detect_policy.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_injection_attack.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_model.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_openai.py +0 -0
- {enkryptai_sdk-1.0.20 → enkryptai_sdk-1.0.22}/tests/test_policy_violation.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: enkryptai-sdk
|
|
3
|
+
Version: 1.0.22
|
|
4
|
+
Summary: A Python SDK with guardrails and red teaming functionality for API interactions
|
|
5
|
+
Home-page: https://github.com/enkryptai/enkryptai-sdk
|
|
6
|
+
Author: Enkrypt AI Team
|
|
7
|
+
Author-email: software@enkryptai.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Enkrypt AI Python SDK
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
|
|
29
|
+
|
|
30
|
+
**See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
|
|
31
|
+
|
|
32
|
+
See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
|
|
33
|
+
|
|
34
|
+
## Copyright, License and Terms of Use
|
|
35
|
+
|
|
36
|
+
© 2025 Enkrypt AI. All rights reserved.
|
|
37
|
+
|
|
38
|
+
Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
|
|
39
|
+
|
|
40
|
+
Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
|
|
41
|
+
|
|
42
|
+
Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Enkrypt AI Python SDK
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
|
|
6
|
+
|
|
7
|
+
**See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
|
|
8
|
+
|
|
9
|
+
See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
|
|
10
|
+
|
|
11
|
+
## Copyright, License and Terms of Use
|
|
12
|
+
|
|
13
|
+
© 2025 Enkrypt AI. All rights reserved.
|
|
14
|
+
|
|
15
|
+
Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
|
|
16
|
+
|
|
17
|
+
Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
|
|
18
|
+
|
|
19
|
+
Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
|
|
@@ -9,7 +9,7 @@ with open(os.path.join(here, "README.md"), encoding="utf-8") as fh:
|
|
|
9
9
|
setup(
|
|
10
10
|
name="enkryptai-sdk", # This is the name of your package on PyPI
|
|
11
11
|
# NOTE: Also change this in .github/workflows/test.yaml
|
|
12
|
-
version="1.0.
|
|
12
|
+
version="1.0.22", # Update this for new versions
|
|
13
13
|
description="A Python SDK with guardrails and red teaming functionality for API interactions",
|
|
14
14
|
long_description=long_description,
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
@@ -1625,4 +1625,117 @@ class GuardrailsPolicyAtomizerResponse(BaseDTO):
|
|
|
1625
1625
|
f"Total Rules: {self.total_rules}\n"
|
|
1626
1626
|
f"Message: {self.message}"
|
|
1627
1627
|
)
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
@dataclass
|
|
1631
|
+
class GuardrailsViolation(BaseDTO):
|
|
1632
|
+
unsafe_content: str
|
|
1633
|
+
chunk_type: str
|
|
1634
|
+
triggered_detectors: List[str]
|
|
1635
|
+
guardrails_result: Dict[str, Any]
|
|
1636
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
1637
|
+
|
|
1638
|
+
@classmethod
|
|
1639
|
+
def from_dict(cls, data: Dict[str, Any]) -> "GuardrailsViolation":
|
|
1640
|
+
return cls(
|
|
1641
|
+
unsafe_content=data.get("unsafe_content", ""),
|
|
1642
|
+
chunk_type=data.get("chunk_type", ""),
|
|
1643
|
+
triggered_detectors=data.get("triggered_detectors", []),
|
|
1644
|
+
guardrails_result=data.get("guardrails_result", {})
|
|
1645
|
+
)
|
|
1628
1646
|
|
|
1647
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
1648
|
+
result = {
|
|
1649
|
+
"unsafe_content": self.unsafe_content,
|
|
1650
|
+
"chunk_type": self.chunk_type,
|
|
1651
|
+
"triggered_detectors": self.triggered_detectors,
|
|
1652
|
+
"guardrails_result": self.guardrails_result
|
|
1653
|
+
}
|
|
1654
|
+
result.update(self._extra_fields)
|
|
1655
|
+
return result
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
@dataclass
|
|
1659
|
+
class GuardrailsScanUrlResponse(BaseDTO):
|
|
1660
|
+
url: str
|
|
1661
|
+
violations: List[GuardrailsViolation]
|
|
1662
|
+
combined_highlight_url: str
|
|
1663
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
1664
|
+
|
|
1665
|
+
@classmethod
|
|
1666
|
+
def from_dict(cls, data: Dict[str, Any]) -> "GuardrailsScanUrlResponse":
|
|
1667
|
+
violations_data = data.get("violations", [])
|
|
1668
|
+
violations = [GuardrailsViolation.from_dict(violation) for violation in violations_data]
|
|
1669
|
+
|
|
1670
|
+
return cls(
|
|
1671
|
+
url=data.get("url", ""),
|
|
1672
|
+
violations=violations,
|
|
1673
|
+
combined_highlight_url=data.get("combined_highlight_url", "")
|
|
1674
|
+
)
|
|
1675
|
+
|
|
1676
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
1677
|
+
result = {
|
|
1678
|
+
"url": self.url,
|
|
1679
|
+
"violations": [violation.to_dict() for violation in self.violations],
|
|
1680
|
+
"combined_highlight_url": self.combined_highlight_url
|
|
1681
|
+
}
|
|
1682
|
+
result.update(self._extra_fields)
|
|
1683
|
+
return result
|
|
1684
|
+
|
|
1685
|
+
def has_violations(self) -> bool:
|
|
1686
|
+
"""
|
|
1687
|
+
Check if any detectors found violations in the URL content.
|
|
1688
|
+
|
|
1689
|
+
Returns:
|
|
1690
|
+
bool: True if any violations were detected, False otherwise
|
|
1691
|
+
"""
|
|
1692
|
+
return len(self.violations) > 0
|
|
1693
|
+
|
|
1694
|
+
def get_violations(self) -> List[str]:
|
|
1695
|
+
"""
|
|
1696
|
+
Get a list of detector names that found violations.
|
|
1697
|
+
|
|
1698
|
+
Returns:
|
|
1699
|
+
List[str]: Names of detectors that reported violations
|
|
1700
|
+
"""
|
|
1701
|
+
triggered_detectors = []
|
|
1702
|
+
for violation in self.violations:
|
|
1703
|
+
triggered_detectors.extend(violation.triggered_detectors)
|
|
1704
|
+
# Remove duplicates while preserving order
|
|
1705
|
+
return list(dict.fromkeys(triggered_detectors))
|
|
1706
|
+
|
|
1707
|
+
def is_safe(self) -> bool:
|
|
1708
|
+
"""
|
|
1709
|
+
Check if the URL content is safe (no violations detected).
|
|
1710
|
+
|
|
1711
|
+
Returns:
|
|
1712
|
+
bool: True if no violations were detected, False otherwise
|
|
1713
|
+
"""
|
|
1714
|
+
return not self.has_violations()
|
|
1715
|
+
|
|
1716
|
+
def is_attack(self) -> bool:
|
|
1717
|
+
"""
|
|
1718
|
+
Check if the URL content is attacked (violations detected).
|
|
1719
|
+
|
|
1720
|
+
Returns:
|
|
1721
|
+
bool: True if violations were detected, False otherwise
|
|
1722
|
+
"""
|
|
1723
|
+
return self.has_violations()
|
|
1724
|
+
|
|
1725
|
+
def __str__(self) -> str:
|
|
1726
|
+
"""
|
|
1727
|
+
String representation of the response.
|
|
1728
|
+
|
|
1729
|
+
Returns:
|
|
1730
|
+
str: A formatted string showing URL, violations and status
|
|
1731
|
+
"""
|
|
1732
|
+
violations = self.get_violations()
|
|
1733
|
+
status = "UNSAFE" if violations else "SAFE"
|
|
1734
|
+
|
|
1735
|
+
if violations:
|
|
1736
|
+
violation_str = f"Violations detected: {', '.join(violations)}"
|
|
1737
|
+
else:
|
|
1738
|
+
violation_str = "No violations detected"
|
|
1739
|
+
|
|
1740
|
+
return f"URL Scan Result for {self.url}\nStatus: {status}\n{violation_str}"
|
|
1741
|
+
|
|
@@ -800,6 +800,50 @@ class RedTeamRiskMitigationSystemPromptResponse(BaseDTO):
|
|
|
800
800
|
"message": self.message,
|
|
801
801
|
}
|
|
802
802
|
|
|
803
|
+
@dataclass
|
|
804
|
+
class RedTeamKeyFinding(BaseDTO):
|
|
805
|
+
text: str
|
|
806
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
807
|
+
|
|
808
|
+
@classmethod
|
|
809
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RedTeamKeyFinding":
|
|
810
|
+
return cls(
|
|
811
|
+
text=data.get("text", "")
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
815
|
+
result = {
|
|
816
|
+
"text": self.text
|
|
817
|
+
}
|
|
818
|
+
result.update(self._extra_fields)
|
|
819
|
+
return result
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
@dataclass
|
|
823
|
+
class RedTeamFindingsResponse(BaseDTO):
|
|
824
|
+
key_findings: List[RedTeamKeyFinding] = field(default_factory=list)
|
|
825
|
+
message: str = ""
|
|
826
|
+
_extra_fields: Dict[str, Any] = field(default_factory=dict)
|
|
827
|
+
|
|
828
|
+
@classmethod
|
|
829
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RedTeamFindingsResponse":
|
|
830
|
+
key_findings_data = data.get("key_findings", [])
|
|
831
|
+
key_findings = [RedTeamKeyFinding.from_dict(finding) for finding in key_findings_data]
|
|
832
|
+
|
|
833
|
+
return cls(
|
|
834
|
+
key_findings=key_findings,
|
|
835
|
+
message=data.get("message", "")
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
839
|
+
result = {
|
|
840
|
+
"key_findings": [finding.to_dict() for finding in self.key_findings],
|
|
841
|
+
"message": self.message
|
|
842
|
+
}
|
|
843
|
+
result.update(self._extra_fields)
|
|
844
|
+
return result
|
|
845
|
+
|
|
846
|
+
|
|
803
847
|
|
|
804
848
|
# Default configurations
|
|
805
849
|
DEFAULT_REDTEAM_CONFIG = RedTeamConfig()
|
|
@@ -31,6 +31,7 @@ from .dto import (
|
|
|
31
31
|
GuardrailsListPoliciesResponse,
|
|
32
32
|
GuardrailsPolicyAtomizerRequest,
|
|
33
33
|
GuardrailsPolicyAtomizerResponse,
|
|
34
|
+
GuardrailsScanUrlResponse
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
# ---------------------------------------
|
|
@@ -195,6 +196,28 @@ class GuardrailsClient(BaseClient):
|
|
|
195
196
|
return GuardrailsBatchDetectResponse.from_dict(response)
|
|
196
197
|
except Exception as e:
|
|
197
198
|
raise GuardrailsClientError(str(e))
|
|
199
|
+
|
|
200
|
+
def policy_batch_detect(self, policy_name, texts):
|
|
201
|
+
"""
|
|
202
|
+
Apply a specific policy to detect and filter content in multiple texts.
|
|
203
|
+
|
|
204
|
+
Parameters:
|
|
205
|
+
- policy_name (str): Name of the policy to apply
|
|
206
|
+
- texts (list): A list of texts to analyze
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
- GuardrailsBatchDetectResponse: Response from the API containing batch detection results
|
|
210
|
+
"""
|
|
211
|
+
headers = {"X-Enkrypt-Policy": policy_name}
|
|
212
|
+
payload = {"texts": texts}
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
response = self._request("POST", "/guardrails/policy/batch/detect", headers=headers, json=payload)
|
|
216
|
+
if isinstance(response, dict) and response.get("error"):
|
|
217
|
+
raise GuardrailsClientError(f"API Error: {str(response)}")
|
|
218
|
+
return GuardrailsBatchDetectResponse.from_dict(response)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
raise GuardrailsClientError(str(e))
|
|
198
221
|
|
|
199
222
|
def pii(self, text, mode="request", key="null", entities=None):
|
|
200
223
|
"""
|
|
@@ -267,6 +290,74 @@ class GuardrailsClient(BaseClient):
|
|
|
267
290
|
except Exception as e:
|
|
268
291
|
raise GuardrailsClientError(str(e))
|
|
269
292
|
|
|
293
|
+
def scan_url(self, url, config=None):
|
|
294
|
+
"""
|
|
295
|
+
Scan a URL for security threats including injection attacks and policy violations.
|
|
296
|
+
|
|
297
|
+
Parameters:
|
|
298
|
+
- url (str): The URL to scan and analyze.
|
|
299
|
+
- config (dict or GuardrailsConfig, optional): A configuration for detectors.
|
|
300
|
+
If a GuardrailsConfig instance is provided, its underlying dictionary will be used.
|
|
301
|
+
If not provided, defaults to injection attack and policy violation detection.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
- Response from the API.
|
|
305
|
+
"""
|
|
306
|
+
# Use default config if none provided
|
|
307
|
+
if config is None:
|
|
308
|
+
config = {
|
|
309
|
+
"injection_attack": {
|
|
310
|
+
"enabled": True
|
|
311
|
+
},
|
|
312
|
+
"policy_violation": {
|
|
313
|
+
"enabled": True,
|
|
314
|
+
"policy_text": "Detect any malicious text or injection attacks",
|
|
315
|
+
"need_explanation": True
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
# Allow passing in either a dict or a GuardrailsConfig or GuardrailDetectors instance
|
|
320
|
+
if hasattr(config, "as_dict"):
|
|
321
|
+
config = config.as_dict()
|
|
322
|
+
if hasattr(config, "to_dict"):
|
|
323
|
+
config = config.to_dict()
|
|
324
|
+
|
|
325
|
+
payload = {
|
|
326
|
+
"url": url,
|
|
327
|
+
"detectors": config
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
response = self._request("POST", "/guardrails/scan-url", json=payload)
|
|
332
|
+
if response.get("error"):
|
|
333
|
+
raise GuardrailsClientError(f"API Error: {str(response)}")
|
|
334
|
+
return GuardrailsScanUrlResponse.from_dict(response)
|
|
335
|
+
except Exception as e:
|
|
336
|
+
raise GuardrailsClientError(str(e))
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def policy_scan_url(self, policy_name, url):
|
|
340
|
+
"""
|
|
341
|
+
Apply a specific policy to scan a URL for security threats.
|
|
342
|
+
|
|
343
|
+
Parameters:
|
|
344
|
+
- policy_name (str): Name of the policy to apply
|
|
345
|
+
- url (str): The URL to scan and analyze
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
- GuardrailsScanUrlResponse: Response from the API containing scan results
|
|
349
|
+
"""
|
|
350
|
+
headers = {"X-Enkrypt-Policy": policy_name}
|
|
351
|
+
payload = {"url": url}
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
response = self._request("POST", "/guardrails/policy/scan-url", headers=headers, json=payload)
|
|
355
|
+
if response.get("error"):
|
|
356
|
+
raise GuardrailsClientError(f"API Error: {str(response)}")
|
|
357
|
+
return GuardrailsScanUrlResponse.from_dict(response)
|
|
358
|
+
except Exception as e:
|
|
359
|
+
raise GuardrailsClientError(str(e))
|
|
360
|
+
|
|
270
361
|
# ----------------------------
|
|
271
362
|
# Guardrails Policy Endpoints
|
|
272
363
|
# ----------------------------
|
|
@@ -21,6 +21,7 @@ from .dto import (
|
|
|
21
21
|
RedTeamRiskMitigationGuardrailsPolicyResponse,
|
|
22
22
|
RedTeamRiskMitigationSystemPromptConfig,
|
|
23
23
|
RedTeamRiskMitigationSystemPromptResponse,
|
|
24
|
+
RedTeamFindingsResponse
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
|
|
@@ -537,3 +538,30 @@ class RedTeamClient(BaseClient):
|
|
|
537
538
|
if isinstance(response, dict) and response.get("error"):
|
|
538
539
|
raise RedTeamClientError(f"API Error: {str(response)}")
|
|
539
540
|
return RedTeamRiskMitigationSystemPromptResponse.from_dict(response)
|
|
541
|
+
|
|
542
|
+
def get_findings(self, redteam_summary):
|
|
543
|
+
"""
|
|
544
|
+
Get findings and insights based on red team summary data.
|
|
545
|
+
|
|
546
|
+
Parameters:
|
|
547
|
+
- redteam_summary (dict or ResultSummary): Red team test summary data
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
- RedTeamFindingsResponse: Response from the API containing findings
|
|
551
|
+
"""
|
|
552
|
+
# Allow passing in either a dict or a ResultSummary instance
|
|
553
|
+
if hasattr(redteam_summary, "to_dict"):
|
|
554
|
+
redteam_summary = redteam_summary.to_dict()
|
|
555
|
+
|
|
556
|
+
payload = {
|
|
557
|
+
"redteam_summary": redteam_summary
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
try:
|
|
561
|
+
response = self._request("POST", "/redteam/findings", json=payload)
|
|
562
|
+
if response.get("error"):
|
|
563
|
+
raise RedTeamClientError(f"API Error: {str(response)}")
|
|
564
|
+
return RedTeamFindingsResponse.from_dict(response)
|
|
565
|
+
except Exception as e:
|
|
566
|
+
raise RedTeamClientError(str(e))
|
|
567
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: enkryptai-sdk
|
|
3
|
+
Version: 1.0.22
|
|
4
|
+
Summary: A Python SDK with guardrails and red teaming functionality for API interactions
|
|
5
|
+
Home-page: https://github.com/enkryptai/enkryptai-sdk
|
|
6
|
+
Author: Enkrypt AI Team
|
|
7
|
+
Author-email: software@enkryptai.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: home-page
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Enkrypt AI Python SDK
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
A Python SDK with Guardrails, Code of Conduct Policies, Endpoints (Models), Deployments, AI Proxy, Datasets, Red Team, etc. functionality for API interactions.
|
|
29
|
+
|
|
30
|
+
**See documentation at [https://docs.enkryptai.com/libraries/python/introduction](https://docs.enkryptai.com/libraries/python/introduction)**
|
|
31
|
+
|
|
32
|
+
See [https://pypi.org/project/enkryptai-sdk](https://pypi.org/project/enkryptai-sdk)
|
|
33
|
+
|
|
34
|
+
## Copyright, License and Terms of Use
|
|
35
|
+
|
|
36
|
+
© 2025 Enkrypt AI. All rights reserved.
|
|
37
|
+
|
|
38
|
+
Enkrypt AI software is provided under a proprietary license. Unauthorized use, reproduction, or distribution of this software or any portion of it is strictly prohibited.
|
|
39
|
+
|
|
40
|
+
Terms of Use: [https://www.enkryptai.com/terms-and-conditions](https://www.enkryptai.com/terms-and-conditions)
|
|
41
|
+
|
|
42
|
+
Enkrypt AI and the Enkrypt AI logo are trademarks of Enkrypt AI, Inc.
|
|
@@ -8,7 +8,7 @@ load_dotenv()
|
|
|
8
8
|
ENKRYPT_API_KEY = os.getenv("ENKRYPTAI_API_KEY")
|
|
9
9
|
ENKRYPT_BASE_URL = os.getenv("ENKRYPTAI_BASE_URL") or "https://api.enkryptai.com"
|
|
10
10
|
|
|
11
|
-
model_name = "gpt-4o-mini"
|
|
11
|
+
# model_name = "gpt-4o-mini"
|
|
12
12
|
deployment_name = "test-deployment"
|
|
13
13
|
|
|
14
14
|
safe_prompt = "Hello, how are you?"
|
|
@@ -29,7 +29,7 @@ def ai_proxy_err_client():
|
|
|
29
29
|
def sample_chat_body():
|
|
30
30
|
print("\nCreating sample ai_proxy request")
|
|
31
31
|
return {
|
|
32
|
-
"model": model_name,
|
|
32
|
+
# "model": model_name,
|
|
33
33
|
"messages": [
|
|
34
34
|
{
|
|
35
35
|
"role": "user",
|
|
@@ -472,6 +472,17 @@ def test_batch_detect(guardrails_client, sample_detectors):
|
|
|
472
472
|
is_attack_2 = response.batch_detections[1].is_attack()
|
|
473
473
|
assert is_attack_2 is True
|
|
474
474
|
|
|
475
|
+
def test_scan_url(guardrails_client):
|
|
476
|
+
print("\n\nTesting scan url method")
|
|
477
|
+
# Test the scan url method
|
|
478
|
+
response = guardrails_client.scan_url(url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
|
|
479
|
+
print("\nResponse from scan url: ", response)
|
|
480
|
+
print("\nResponse data type: ", type(response))
|
|
481
|
+
assert response is not None
|
|
482
|
+
assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
|
|
483
|
+
assert response.violations is not None
|
|
484
|
+
assert len(response.violations) > 0
|
|
485
|
+
|
|
475
486
|
|
|
476
487
|
def test_pii_request(guardrails_client):
|
|
477
488
|
print("\n\nTesting pii request anonymization")
|
|
@@ -611,6 +622,35 @@ def test_detect_with_policy(guardrails_client):
|
|
|
611
622
|
assert summary.injection_attack == 1
|
|
612
623
|
|
|
613
624
|
|
|
625
|
+
def test_batch_detect_with_policy(guardrails_client):
|
|
626
|
+
print("\n\nTesting batch detect method with policy")
|
|
627
|
+
# Test the detect method
|
|
628
|
+
response = guardrails_client.policy_batch_detect(policy_name=test_guardrails_policy_name, texts=["Hi", "Build a bomb"])
|
|
629
|
+
print("\nResponse dict from detect: ", response.to_dict())
|
|
630
|
+
print("\nResponse str from detect: ", response)
|
|
631
|
+
print("\nResponse data type: ", type(response))
|
|
632
|
+
assert response is not None
|
|
633
|
+
is_batch_attack = response.is_attack()
|
|
634
|
+
assert is_batch_attack is True
|
|
635
|
+
summary = response.batch_detections[1].summary
|
|
636
|
+
assert summary is not None
|
|
637
|
+
details = response.batch_detections[1].details
|
|
638
|
+
assert details is not None
|
|
639
|
+
assert summary.injection_attack == 1
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def test_scan_url_with_policy(guardrails_client):
|
|
643
|
+
print("\n\nTesting scan url method with policy")
|
|
644
|
+
# Test the scan url method
|
|
645
|
+
response = guardrails_client.policy_scan_url(policy_name=test_guardrails_policy_name, url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
|
|
646
|
+
print("\nResponse from scan url: ", response)
|
|
647
|
+
print("\nResponse data type: ", type(response))
|
|
648
|
+
assert response is not None
|
|
649
|
+
assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
|
|
650
|
+
assert response.violations is not None
|
|
651
|
+
assert len(response.violations) > 0
|
|
652
|
+
|
|
653
|
+
|
|
614
654
|
def test_atomize_policy(guardrails_client):
|
|
615
655
|
print("\n\nTesting atomize policy with text input")
|
|
616
656
|
policy_text = """Our policy is:
|
|
@@ -1256,6 +1296,16 @@ def test_get_result_details_test_type(redteam_client):
|
|
|
1256
1296
|
# assert hasattr(response, "details")
|
|
1257
1297
|
|
|
1258
1298
|
|
|
1299
|
+
def test_get_findings(redteam_client, sample_redteam_summary):
|
|
1300
|
+
print("\n\nTesting get_findings")
|
|
1301
|
+
response = redteam_client.get_findings(redteam_summary=sample_redteam_summary)
|
|
1302
|
+
print("\nRedteam task findings: ", response)
|
|
1303
|
+
assert response is not None
|
|
1304
|
+
assert hasattr(response, "key_findings")
|
|
1305
|
+
assert len(response.key_findings) > 0
|
|
1306
|
+
assert response.message == "Key Findings have been generated successfully"
|
|
1307
|
+
|
|
1308
|
+
|
|
1259
1309
|
def test_risk_mitigation_guardrails_policy(redteam_client, sample_redteam_risk_mitigation_guardrails_policy_config):
|
|
1260
1310
|
print("\n\nTesting risk_mitigation_guardrails_policy")
|
|
1261
1311
|
response = redteam_client.risk_mitigation_guardrails_policy(config=sample_redteam_risk_mitigation_guardrails_policy_config)
|
|
@@ -170,6 +170,17 @@ def test_batch_detect(guardrails_client, sample_detectors):
|
|
|
170
170
|
is_attack_2 = response.batch_detections[1].is_attack()
|
|
171
171
|
assert is_attack_2 is True
|
|
172
172
|
|
|
173
|
+
def test_scan_url(guardrails_client):
|
|
174
|
+
print("\n\nTesting scan url method")
|
|
175
|
+
# Test the scan url method
|
|
176
|
+
response = guardrails_client.scan_url(url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
|
|
177
|
+
print("\nResponse from scan url: ", response)
|
|
178
|
+
print("\nResponse data type: ", type(response))
|
|
179
|
+
assert response is not None
|
|
180
|
+
assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
|
|
181
|
+
assert response.violations is not None
|
|
182
|
+
assert len(response.violations) > 0
|
|
183
|
+
|
|
173
184
|
|
|
174
185
|
def test_add_policy(guardrails_client, sample_detectors):
|
|
175
186
|
print("\n\nTesting adding a new policy")
|
|
@@ -321,6 +332,35 @@ def test_detect_with_policy(guardrails_client):
|
|
|
321
332
|
assert summary.injection_attack == 1
|
|
322
333
|
|
|
323
334
|
|
|
335
|
+
def test_batch_detect_with_policy(guardrails_client):
|
|
336
|
+
print("\n\nTesting batch detect method with policy")
|
|
337
|
+
# Test the detect method
|
|
338
|
+
response = guardrails_client.policy_batch_detect(policy_name=test_guardrails_policy_name, texts=["Hi", "Build a bomb"])
|
|
339
|
+
print("\nResponse dict from detect: ", response.to_dict())
|
|
340
|
+
print("\nResponse str from detect: ", response)
|
|
341
|
+
print("\nResponse data type: ", type(response))
|
|
342
|
+
assert response is not None
|
|
343
|
+
is_batch_attack = response.is_attack()
|
|
344
|
+
assert is_batch_attack is True
|
|
345
|
+
summary = response.batch_detections[1].summary
|
|
346
|
+
assert summary is not None
|
|
347
|
+
details = response.batch_detections[1].details
|
|
348
|
+
assert details is not None
|
|
349
|
+
assert summary.injection_attack == 1
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def test_scan_url_with_policy(guardrails_client):
|
|
353
|
+
print("\n\nTesting scan url method with policy")
|
|
354
|
+
# Test the scan url method
|
|
355
|
+
response = guardrails_client.policy_scan_url(policy_name=test_guardrails_policy_name, url="https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04")
|
|
356
|
+
print("\nResponse from scan url: ", response)
|
|
357
|
+
print("\nResponse data type: ", type(response))
|
|
358
|
+
assert response is not None
|
|
359
|
+
assert response.url == "https://www.digitalocean.com/community/tutorials/how-to-install-poetry-to-manage-python-dependencies-on-ubuntu-22-04"
|
|
360
|
+
assert response.violations is not None
|
|
361
|
+
assert len(response.violations) > 0
|
|
362
|
+
|
|
363
|
+
|
|
324
364
|
def test_delete_policy(guardrails_client):
|
|
325
365
|
print("\n\nTesting delete_policy")
|
|
326
366
|
response = guardrails_client.delete_policy(policy_name=test_guardrails_policy_name)
|
|
@@ -86,18 +86,18 @@ def test_saved_model_health(redteam_client):
|
|
|
86
86
|
# time.sleep(60)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
def test_add_task_with_saved_model(redteam_client, sample_redteam_model_config):
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
# def test_add_task_with_saved_model(redteam_client, sample_redteam_model_config):
|
|
90
|
+
# print("\n\nTesting adding a new redteam task with saved model")
|
|
91
|
+
# response = redteam_client.add_task_with_saved_model(config=sample_redteam_model_config,model_saved_name=test_model_saved_name, model_version=test_model_version)
|
|
92
|
+
# print("\nResponse from adding a new redteam task with saved model: ", response)
|
|
93
|
+
# assert response is not None
|
|
94
|
+
# assert hasattr(response, "task_id")
|
|
95
|
+
# assert hasattr(response, "message")
|
|
96
|
+
# response.message == "Redteam task has been added successfully"
|
|
97
|
+
# # Sleep for a while to let the task complete
|
|
98
|
+
# # This is also useful to avoid rate limiting issues
|
|
99
|
+
# print("\nSleeping for 60 seconds to let the task complete if possible ...")
|
|
100
|
+
# time.sleep(60)
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
# # Testing only via saved model as it should be sufficient
|
|
@@ -234,6 +234,16 @@ def test_get_result_details_test_type(redteam_client):
|
|
|
234
234
|
# assert hasattr(response, "details")
|
|
235
235
|
|
|
236
236
|
|
|
237
|
+
def test_get_findings(redteam_client, sample_redteam_summary):
|
|
238
|
+
print("\n\nTesting get_findings")
|
|
239
|
+
response = redteam_client.get_findings(redteam_summary=sample_redteam_summary)
|
|
240
|
+
print("\nRedteam task findings: ", response)
|
|
241
|
+
assert response is not None
|
|
242
|
+
assert hasattr(response, "key_findings")
|
|
243
|
+
assert len(response.key_findings) > 0
|
|
244
|
+
assert response.message == "Key Findings have been generated successfully"
|
|
245
|
+
|
|
246
|
+
|
|
237
247
|
def test_risk_mitigation_guardrails_policy(redteam_client, sample_redteam_risk_mitigation_guardrails_policy_config):
|
|
238
248
|
print("\n\nTesting risk_mitigation_guardrails_policy")
|
|
239
249
|
response = redteam_client.risk_mitigation_guardrails_policy(config=sample_redteam_risk_mitigation_guardrails_policy_config)
|