spidercob 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.
- spidercob-0.1.0/.gitignore +3 -0
- spidercob-0.1.0/PKG-INFO +149 -0
- spidercob-0.1.0/README.md +128 -0
- spidercob-0.1.0/pyproject.toml +38 -0
- spidercob-0.1.0/src/spidercob/__init__.py +37 -0
- spidercob-0.1.0/src/spidercob/_client.py +255 -0
spidercob-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spidercob
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the Spidercob DLP API — scan, detect, and remediate sensitive data at scale
|
|
5
|
+
Project-URL: Homepage, https://spidercob.com
|
|
6
|
+
Project-URL: Repository, https://github.com/SpiderCob/spidercob-python
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/SpiderCob/spidercob-python/issues
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
Keywords: compliance,data-loss-prevention,dlp,gdpr,hipaa,pci-dss,pii,privacy,secrets,security,spidercob
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Security
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
19
|
+
Requires-Dist: responses>=0.25; extra == 'dev'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# spidercob
|
|
23
|
+
|
|
24
|
+
Python SDK for the [Spidercob](https://spidercob.com) DLP API.
|
|
25
|
+
|
|
26
|
+
Scan text, files, and data pipelines for PII, secrets, and sensitive data. Get AI-powered analysis, compliance alerts, and remediation guidance — all from a single API call.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from spidercob import Client
|
|
30
|
+
|
|
31
|
+
client = Client(api_key="your-api-key")
|
|
32
|
+
result = client.scan("postgresql://admin:s3cr3t@prod-db:5432/mydb")
|
|
33
|
+
|
|
34
|
+
print(result.highest_severity) # CRITICAL
|
|
35
|
+
print(result.critical[0].type) # db_connection_string
|
|
36
|
+
print(result.ai_insight) # CISO-grade analysis
|
|
37
|
+
print(result.compliance_alerts) # ["PCI-DSS", "SOC2"]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install spidercob
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Zero dependencies. Python 3.9+.
|
|
47
|
+
|
|
48
|
+
Get your API key at [spidercob.com/settings](https://spidercob.com/settings).
|
|
49
|
+
|
|
50
|
+
## Authentication
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
# Pass directly
|
|
54
|
+
client = Client(api_key="your-api-key")
|
|
55
|
+
|
|
56
|
+
# Or set environment variable
|
|
57
|
+
export SPIDERCOB_API_KEY=your-api-key
|
|
58
|
+
client = Client()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Scan text
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
result = client.scan("My SSN is 432-78-9012 and AWS key AKIAIOSFODNN7EXAMPLE")
|
|
65
|
+
|
|
66
|
+
result.has_findings # True
|
|
67
|
+
result.highest_severity # "CRITICAL"
|
|
68
|
+
result.critical # list[Finding]
|
|
69
|
+
result.high
|
|
70
|
+
result.medium
|
|
71
|
+
result.low
|
|
72
|
+
|
|
73
|
+
# Each Finding:
|
|
74
|
+
f = result.critical[0]
|
|
75
|
+
f.type # "aws_access_key"
|
|
76
|
+
f.description # "AWS Access Key ID"
|
|
77
|
+
f.value # masked value
|
|
78
|
+
f.severity # "CRITICAL"
|
|
79
|
+
f.position # "char 10-30"
|
|
80
|
+
f.remediation # "Rotate this key immediately in AWS IAM"
|
|
81
|
+
|
|
82
|
+
# AI analysis
|
|
83
|
+
result.ai_insight # CISO-grade explanation
|
|
84
|
+
result.compliance_alerts # ["PCI-DSS 3.2", "SOC 2 CC6"]
|
|
85
|
+
result.threat_score # 0-100
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Scan a file
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
result = client.scan_file("src/config.py")
|
|
92
|
+
if result.has_findings:
|
|
93
|
+
print(result.to_dict())
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Retrieve past scans
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
# Get a scan by ID
|
|
100
|
+
result = client.get_scan(scan_id=1234)
|
|
101
|
+
|
|
102
|
+
# List recent scans
|
|
103
|
+
scans = client.list_scans(limit=20)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Use in CI
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import sys
|
|
110
|
+
from spidercob import Client
|
|
111
|
+
|
|
112
|
+
client = Client()
|
|
113
|
+
result = client.scan_file("config.py")
|
|
114
|
+
|
|
115
|
+
if result.critical:
|
|
116
|
+
for f in result.critical:
|
|
117
|
+
print(f"CRITICAL: {f.type} at {f.position}")
|
|
118
|
+
print(f" Remediation: {f.remediation}")
|
|
119
|
+
sys.exit(1)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Error handling
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from spidercob import Client, AuthenticationError, RateLimitError, SpidercobError
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
result = client.scan(text)
|
|
129
|
+
except AuthenticationError:
|
|
130
|
+
print("Invalid API key")
|
|
131
|
+
except RateLimitError:
|
|
132
|
+
print("Rate limit hit — slow down or upgrade plan")
|
|
133
|
+
except SpidercobError as e:
|
|
134
|
+
print(f"API error {e.status_code}: {e}")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Free tier — no API key needed
|
|
138
|
+
|
|
139
|
+
Want to scan locally without an API key? Use [dlp-patterns](https://github.com/SpiderCob/dlp-patterns) — the open source pattern engine this SDK is built on:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pip install dlp-patterns
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The SDK adds: AI-powered CISO analysis, compliance mapping (GDPR/HIPAA/PCI-DSS/SOC2), audit logs, dashboard, team management, and policy enforcement.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
Apache 2.0
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# spidercob
|
|
2
|
+
|
|
3
|
+
Python SDK for the [Spidercob](https://spidercob.com) DLP API.
|
|
4
|
+
|
|
5
|
+
Scan text, files, and data pipelines for PII, secrets, and sensitive data. Get AI-powered analysis, compliance alerts, and remediation guidance — all from a single API call.
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from spidercob import Client
|
|
9
|
+
|
|
10
|
+
client = Client(api_key="your-api-key")
|
|
11
|
+
result = client.scan("postgresql://admin:s3cr3t@prod-db:5432/mydb")
|
|
12
|
+
|
|
13
|
+
print(result.highest_severity) # CRITICAL
|
|
14
|
+
print(result.critical[0].type) # db_connection_string
|
|
15
|
+
print(result.ai_insight) # CISO-grade analysis
|
|
16
|
+
print(result.compliance_alerts) # ["PCI-DSS", "SOC2"]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install spidercob
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Zero dependencies. Python 3.9+.
|
|
26
|
+
|
|
27
|
+
Get your API key at [spidercob.com/settings](https://spidercob.com/settings).
|
|
28
|
+
|
|
29
|
+
## Authentication
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
# Pass directly
|
|
33
|
+
client = Client(api_key="your-api-key")
|
|
34
|
+
|
|
35
|
+
# Or set environment variable
|
|
36
|
+
export SPIDERCOB_API_KEY=your-api-key
|
|
37
|
+
client = Client()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Scan text
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
result = client.scan("My SSN is 432-78-9012 and AWS key AKIAIOSFODNN7EXAMPLE")
|
|
44
|
+
|
|
45
|
+
result.has_findings # True
|
|
46
|
+
result.highest_severity # "CRITICAL"
|
|
47
|
+
result.critical # list[Finding]
|
|
48
|
+
result.high
|
|
49
|
+
result.medium
|
|
50
|
+
result.low
|
|
51
|
+
|
|
52
|
+
# Each Finding:
|
|
53
|
+
f = result.critical[0]
|
|
54
|
+
f.type # "aws_access_key"
|
|
55
|
+
f.description # "AWS Access Key ID"
|
|
56
|
+
f.value # masked value
|
|
57
|
+
f.severity # "CRITICAL"
|
|
58
|
+
f.position # "char 10-30"
|
|
59
|
+
f.remediation # "Rotate this key immediately in AWS IAM"
|
|
60
|
+
|
|
61
|
+
# AI analysis
|
|
62
|
+
result.ai_insight # CISO-grade explanation
|
|
63
|
+
result.compliance_alerts # ["PCI-DSS 3.2", "SOC 2 CC6"]
|
|
64
|
+
result.threat_score # 0-100
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Scan a file
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
result = client.scan_file("src/config.py")
|
|
71
|
+
if result.has_findings:
|
|
72
|
+
print(result.to_dict())
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Retrieve past scans
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Get a scan by ID
|
|
79
|
+
result = client.get_scan(scan_id=1234)
|
|
80
|
+
|
|
81
|
+
# List recent scans
|
|
82
|
+
scans = client.list_scans(limit=20)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Use in CI
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import sys
|
|
89
|
+
from spidercob import Client
|
|
90
|
+
|
|
91
|
+
client = Client()
|
|
92
|
+
result = client.scan_file("config.py")
|
|
93
|
+
|
|
94
|
+
if result.critical:
|
|
95
|
+
for f in result.critical:
|
|
96
|
+
print(f"CRITICAL: {f.type} at {f.position}")
|
|
97
|
+
print(f" Remediation: {f.remediation}")
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Error handling
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from spidercob import Client, AuthenticationError, RateLimitError, SpidercobError
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
result = client.scan(text)
|
|
108
|
+
except AuthenticationError:
|
|
109
|
+
print("Invalid API key")
|
|
110
|
+
except RateLimitError:
|
|
111
|
+
print("Rate limit hit — slow down or upgrade plan")
|
|
112
|
+
except SpidercobError as e:
|
|
113
|
+
print(f"API error {e.status_code}: {e}")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Free tier — no API key needed
|
|
117
|
+
|
|
118
|
+
Want to scan locally without an API key? Use [dlp-patterns](https://github.com/SpiderCob/dlp-patterns) — the open source pattern engine this SDK is built on:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install dlp-patterns
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The SDK adds: AI-powered CISO analysis, compliance mapping (GDPR/HIPAA/PCI-DSS/SOC2), audit logs, dashboard, team management, and policy enforcement.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
Apache 2.0
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "spidercob"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the Spidercob DLP API — scan, detect, and remediate sensitive data at scale"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "Apache-2.0" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
dependencies = []
|
|
13
|
+
keywords = [
|
|
14
|
+
"dlp", "data-loss-prevention", "pii", "secrets", "security",
|
|
15
|
+
"privacy", "compliance", "gdpr", "hipaa", "pci-dss", "spidercob",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: Apache Software License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Security",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://spidercob.com"
|
|
28
|
+
Repository = "https://github.com/SpiderCob/spidercob-python"
|
|
29
|
+
"Bug Tracker" = "https://github.com/SpiderCob/spidercob-python/issues"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = ["pytest>=7", "responses>=0.25"]
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["src/spidercob"]
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
spidercob — Python SDK for the Spidercob DLP API.
|
|
3
|
+
|
|
4
|
+
Quick start::
|
|
5
|
+
|
|
6
|
+
from spidercob import Client
|
|
7
|
+
|
|
8
|
+
client = Client(api_key="your-api-key")
|
|
9
|
+
result = client.scan("My AWS key is AKIAIOSFODNN7EXAMPLE")
|
|
10
|
+
|
|
11
|
+
print(result.highest_severity) # CRITICAL
|
|
12
|
+
print(result.critical[0].type) # aws_access_key
|
|
13
|
+
print(result.ai_insight) # CISO-grade analysis
|
|
14
|
+
print(result.compliance_alerts) # ["PCI-DSS", "SOC2"]
|
|
15
|
+
|
|
16
|
+
Full docs: https://github.com/SpiderCob/spidercob-python
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from spidercob._client import (
|
|
20
|
+
Client,
|
|
21
|
+
ScanResult,
|
|
22
|
+
Finding,
|
|
23
|
+
SpidercobError,
|
|
24
|
+
AuthenticationError,
|
|
25
|
+
RateLimitError,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__version__ = "0.1.0"
|
|
29
|
+
__all__ = [
|
|
30
|
+
"Client",
|
|
31
|
+
"ScanResult",
|
|
32
|
+
"Finding",
|
|
33
|
+
"SpidercobError",
|
|
34
|
+
"AuthenticationError",
|
|
35
|
+
"RateLimitError",
|
|
36
|
+
"__version__",
|
|
37
|
+
]
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""Spidercob API client."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
|
+
from urllib.error import HTTPError
|
|
9
|
+
from urllib.request import Request, urlopen
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
BASE_URL = "https://spidercob.com"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class Finding:
|
|
18
|
+
type: str
|
|
19
|
+
description: str
|
|
20
|
+
value: str
|
|
21
|
+
severity: str
|
|
22
|
+
position: str
|
|
23
|
+
context: str = ""
|
|
24
|
+
remediation: str = ""
|
|
25
|
+
context_score: float = 0.0
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def _from_dict(cls, d: Dict[str, Any]) -> "Finding":
|
|
29
|
+
return cls(
|
|
30
|
+
type=d.get("type", ""),
|
|
31
|
+
description=d.get("description", ""),
|
|
32
|
+
value=d.get("value", ""),
|
|
33
|
+
severity=d.get("severity", ""),
|
|
34
|
+
position=d.get("position", ""),
|
|
35
|
+
context=d.get("context", ""),
|
|
36
|
+
remediation=d.get("remediation", ""),
|
|
37
|
+
context_score=d.get("context_score", 0.0),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class ScanResult:
|
|
43
|
+
id: int
|
|
44
|
+
status: str
|
|
45
|
+
risk_level: Optional[str]
|
|
46
|
+
verdict: Optional[str]
|
|
47
|
+
threat_score: int
|
|
48
|
+
findings: List[Finding]
|
|
49
|
+
scan_duration_ms: int
|
|
50
|
+
ai_insight: Optional[str]
|
|
51
|
+
compliance_alerts: List[str]
|
|
52
|
+
remediations: List[str]
|
|
53
|
+
created_at: str
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def has_findings(self) -> bool:
|
|
57
|
+
return len(self.findings) > 0
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def critical(self) -> List[Finding]:
|
|
61
|
+
return [f for f in self.findings if f.severity.upper() == "CRITICAL"]
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def high(self) -> List[Finding]:
|
|
65
|
+
return [f for f in self.findings if f.severity.upper() == "HIGH"]
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def medium(self) -> List[Finding]:
|
|
69
|
+
return [f for f in self.findings if f.severity.upper() == "MEDIUM"]
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def low(self) -> List[Finding]:
|
|
73
|
+
return [f for f in self.findings if f.severity.upper() == "LOW"]
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def highest_severity(self) -> Optional[str]:
|
|
77
|
+
for sev in ("CRITICAL", "HIGH", "MEDIUM", "LOW"):
|
|
78
|
+
if any(f.severity.upper() == sev for f in self.findings):
|
|
79
|
+
return sev
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
83
|
+
result: Dict[str, Any] = {}
|
|
84
|
+
for sev in ("CRITICAL", "HIGH", "MEDIUM", "LOW"):
|
|
85
|
+
items = [f for f in self.findings if f.severity.upper() == sev]
|
|
86
|
+
if items:
|
|
87
|
+
result[sev] = [
|
|
88
|
+
{
|
|
89
|
+
"type": f.type,
|
|
90
|
+
"description": f.description,
|
|
91
|
+
"value": f.value,
|
|
92
|
+
"position": f.position,
|
|
93
|
+
"remediation": f.remediation,
|
|
94
|
+
}
|
|
95
|
+
for f in items
|
|
96
|
+
]
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def _from_dict(cls, d: Dict[str, Any]) -> "ScanResult":
|
|
101
|
+
findings = [Finding._from_dict(f) for f in (d.get("findings") or [])]
|
|
102
|
+
return cls(
|
|
103
|
+
id=d.get("id", 0),
|
|
104
|
+
status=d.get("status", ""),
|
|
105
|
+
risk_level=d.get("risk_level"),
|
|
106
|
+
verdict=d.get("verdict"),
|
|
107
|
+
threat_score=d.get("threat_score", 0),
|
|
108
|
+
findings=findings,
|
|
109
|
+
scan_duration_ms=d.get("scan_duration_ms") or d.get("duration", 0),
|
|
110
|
+
ai_insight=d.get("aiInsight"),
|
|
111
|
+
compliance_alerts=d.get("compliance_alerts", []),
|
|
112
|
+
remediations=d.get("remediations", []),
|
|
113
|
+
created_at=d.get("created_at", ""),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class SpidercobError(Exception):
|
|
118
|
+
def __init__(self, message: str, status_code: Optional[int] = None):
|
|
119
|
+
super().__init__(message)
|
|
120
|
+
self.status_code = status_code
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class AuthenticationError(SpidercobError):
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class RateLimitError(SpidercobError):
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class Client:
|
|
132
|
+
"""
|
|
133
|
+
Spidercob API client.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
api_key:
|
|
138
|
+
Your Spidercob API key. Falls back to the ``SPIDERCOB_API_KEY``
|
|
139
|
+
environment variable if not provided.
|
|
140
|
+
base_url:
|
|
141
|
+
Override the default API base URL. Useful for self-hosted deployments.
|
|
142
|
+
timeout:
|
|
143
|
+
Request timeout in seconds (default: 30).
|
|
144
|
+
|
|
145
|
+
Examples
|
|
146
|
+
--------
|
|
147
|
+
>>> from spidercob import Client
|
|
148
|
+
>>> client = Client(api_key="your-api-key")
|
|
149
|
+
>>> result = client.scan("My AWS key is AKIAIOSFODNN7EXAMPLE")
|
|
150
|
+
>>> print(result.highest_severity)
|
|
151
|
+
CRITICAL
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
def __init__(
|
|
155
|
+
self,
|
|
156
|
+
api_key: Optional[str] = None,
|
|
157
|
+
base_url: str = BASE_URL,
|
|
158
|
+
timeout: int = 30,
|
|
159
|
+
) -> None:
|
|
160
|
+
self.api_key = api_key or os.environ.get("SPIDERCOB_API_KEY")
|
|
161
|
+
if not self.api_key:
|
|
162
|
+
raise AuthenticationError(
|
|
163
|
+
"No API key provided. Pass api_key= or set the SPIDERCOB_API_KEY environment variable. "
|
|
164
|
+
"Get your key at https://spidercob.com/settings"
|
|
165
|
+
)
|
|
166
|
+
self.base_url = base_url.rstrip("/")
|
|
167
|
+
self.timeout = timeout
|
|
168
|
+
|
|
169
|
+
def _request(self, method: str, path: str, body: Optional[Dict] = None) -> Dict:
|
|
170
|
+
url = f"{self.base_url}{path}"
|
|
171
|
+
data = json.dumps(body).encode() if body else None
|
|
172
|
+
req = Request(
|
|
173
|
+
url,
|
|
174
|
+
data=data,
|
|
175
|
+
method=method,
|
|
176
|
+
headers={
|
|
177
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
178
|
+
"Content-Type": "application/json",
|
|
179
|
+
"Accept": "application/json",
|
|
180
|
+
"User-Agent": "spidercob-python/0.1.0",
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
try:
|
|
184
|
+
with urlopen(req, timeout=self.timeout) as resp:
|
|
185
|
+
return json.loads(resp.read().decode())
|
|
186
|
+
except HTTPError as exc:
|
|
187
|
+
body_text = exc.read().decode(errors="replace")
|
|
188
|
+
if exc.code == 401:
|
|
189
|
+
raise AuthenticationError("Invalid API key. Check your key at https://spidercob.com/settings") from exc
|
|
190
|
+
if exc.code == 429:
|
|
191
|
+
raise RateLimitError("Rate limit exceeded. Slow down requests or upgrade your plan.") from exc
|
|
192
|
+
try:
|
|
193
|
+
detail = json.loads(body_text).get("detail", body_text)
|
|
194
|
+
except Exception:
|
|
195
|
+
detail = body_text
|
|
196
|
+
raise SpidercobError(f"API error {exc.code}: {detail}", status_code=exc.code) from exc
|
|
197
|
+
|
|
198
|
+
def scan(
|
|
199
|
+
self,
|
|
200
|
+
text: str,
|
|
201
|
+
source: str = "SDK",
|
|
202
|
+
) -> ScanResult:
|
|
203
|
+
"""
|
|
204
|
+
Scan text for PII, secrets, and sensitive data.
|
|
205
|
+
|
|
206
|
+
Parameters
|
|
207
|
+
----------
|
|
208
|
+
text:
|
|
209
|
+
The content to scan — plain text, source code, log output, etc.
|
|
210
|
+
source:
|
|
211
|
+
Label for the scan source shown in the Spidercob dashboard.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
ScanResult
|
|
216
|
+
Findings grouped by severity with AI analysis and compliance alerts.
|
|
217
|
+
|
|
218
|
+
Examples
|
|
219
|
+
--------
|
|
220
|
+
>>> result = client.scan("postgresql://admin:s3cr3t@prod-db:5432/mydb")
|
|
221
|
+
>>> result.highest_severity
|
|
222
|
+
'CRITICAL'
|
|
223
|
+
>>> result.critical[0].type
|
|
224
|
+
'db_connection_string'
|
|
225
|
+
"""
|
|
226
|
+
payload = {"content": text, "source": source}
|
|
227
|
+
data = self._request("POST", "/api/scans/", payload)
|
|
228
|
+
return ScanResult._from_dict(data)
|
|
229
|
+
|
|
230
|
+
def scan_file(self, path: str, source: str = "SDK") -> ScanResult:
|
|
231
|
+
"""
|
|
232
|
+
Scan a file for PII, secrets, and sensitive data.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
path:
|
|
237
|
+
Path to the file to scan.
|
|
238
|
+
source:
|
|
239
|
+
Label for the scan source shown in the Spidercob dashboard.
|
|
240
|
+
"""
|
|
241
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
242
|
+
text = fh.read()
|
|
243
|
+
return self.scan(text, source=source or path)
|
|
244
|
+
|
|
245
|
+
def get_scan(self, scan_id: int) -> ScanResult:
|
|
246
|
+
"""Retrieve a previously run scan by ID."""
|
|
247
|
+
data = self._request("GET", f"/api/scans/{scan_id}")
|
|
248
|
+
return ScanResult._from_dict(data)
|
|
249
|
+
|
|
250
|
+
def list_scans(self, limit: int = 20) -> List[ScanResult]:
|
|
251
|
+
"""List recent scans from your account."""
|
|
252
|
+
data = self._request("GET", f"/api/scans/?limit={limit}")
|
|
253
|
+
if isinstance(data, list):
|
|
254
|
+
return [ScanResult._from_dict(d) for d in data]
|
|
255
|
+
return []
|