sentineldeck 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.
- sentineldeck-0.1.0/LICENSE +21 -0
- sentineldeck-0.1.0/PKG-INFO +356 -0
- sentineldeck-0.1.0/README.md +323 -0
- sentineldeck-0.1.0/pyproject.toml +73 -0
- sentineldeck-0.1.0/setup.cfg +4 -0
- sentineldeck-0.1.0/src/sentineldeck/__init__.py +3 -0
- sentineldeck-0.1.0/src/sentineldeck/alerts.py +72 -0
- sentineldeck-0.1.0/src/sentineldeck/cli.py +217 -0
- sentineldeck-0.1.0/src/sentineldeck/diff.py +156 -0
- sentineldeck-0.1.0/src/sentineldeck/models.py +59 -0
- sentineldeck-0.1.0/src/sentineldeck/monitor.py +52 -0
- sentineldeck-0.1.0/src/sentineldeck/py.typed +0 -0
- sentineldeck-0.1.0/src/sentineldeck/remediation.py +278 -0
- sentineldeck-0.1.0/src/sentineldeck/reporters/__init__.py +1 -0
- sentineldeck-0.1.0/src/sentineldeck/reporters/badge.py +126 -0
- sentineldeck-0.1.0/src/sentineldeck/reporters/diff_report.py +168 -0
- sentineldeck-0.1.0/src/sentineldeck/reporters/html_report.py +383 -0
- sentineldeck-0.1.0/src/sentineldeck/reporters/json_report.py +24 -0
- sentineldeck-0.1.0/src/sentineldeck/risk/__init__.py +1 -0
- sentineldeck-0.1.0/src/sentineldeck/risk/scoring.py +546 -0
- sentineldeck-0.1.0/src/sentineldeck/scanner.py +87 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/__init__.py +1 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/dns_hygiene.py +24 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/dns_lookup.py +255 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/domain.py +27 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/domain_intel.py +69 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/email_security.py +117 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/http_headers.py +179 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/subdomains.py +102 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/takeover.py +104 -0
- sentineldeck-0.1.0/src/sentineldeck/scanners/tls.py +166 -0
- sentineldeck-0.1.0/src/sentineldeck/suppressions.py +36 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/PKG-INFO +356 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/SOURCES.txt +60 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/dependency_links.txt +1 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/entry_points.txt +2 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/requires.txt +6 -0
- sentineldeck-0.1.0/src/sentineldeck.egg-info/top_level.txt +1 -0
- sentineldeck-0.1.0/tests/test_alerts.py +58 -0
- sentineldeck-0.1.0/tests/test_badge.py +63 -0
- sentineldeck-0.1.0/tests/test_cli.py +7 -0
- sentineldeck-0.1.0/tests/test_cli_diff.py +61 -0
- sentineldeck-0.1.0/tests/test_cli_monitor.py +57 -0
- sentineldeck-0.1.0/tests/test_cli_report.py +59 -0
- sentineldeck-0.1.0/tests/test_cli_scan.py +57 -0
- sentineldeck-0.1.0/tests/test_diff.py +189 -0
- sentineldeck-0.1.0/tests/test_dns_hygiene.py +33 -0
- sentineldeck-0.1.0/tests/test_dns_lookup.py +157 -0
- sentineldeck-0.1.0/tests/test_domain.py +12 -0
- sentineldeck-0.1.0/tests/test_domain_intel.py +52 -0
- sentineldeck-0.1.0/tests/test_email_security.py +142 -0
- sentineldeck-0.1.0/tests/test_html_report.py +106 -0
- sentineldeck-0.1.0/tests/test_http_headers.py +65 -0
- sentineldeck-0.1.0/tests/test_json_report.py +37 -0
- sentineldeck-0.1.0/tests/test_monitor.py +55 -0
- sentineldeck-0.1.0/tests/test_remediation.py +106 -0
- sentineldeck-0.1.0/tests/test_scanner.py +31 -0
- sentineldeck-0.1.0/tests/test_scoring.py +128 -0
- sentineldeck-0.1.0/tests/test_subdomains.py +90 -0
- sentineldeck-0.1.0/tests/test_suppressions.py +68 -0
- sentineldeck-0.1.0/tests/test_takeover.py +110 -0
- sentineldeck-0.1.0/tests/test_tls.py +88 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sanmaxdev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sentineldeck
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Passive attack-surface visibility and client-ready security reports for small businesses.
|
|
5
|
+
Author: sanmaxdev
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sanmaxdev/SentinelDeck
|
|
8
|
+
Project-URL: Repository, https://github.com/sanmaxdev/SentinelDeck
|
|
9
|
+
Project-URL: Issues, https://github.com/sanmaxdev/SentinelDeck/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/sanmaxdev/SentinelDeck/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: security,attack-surface,osint,headers,ssl,sme
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Security
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: dnspython>=2.0
|
|
28
|
+
Requires-Dist: cryptography>=41.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
<div align="center">
|
|
35
|
+
|
|
36
|
+
<img src="assets/banner.svg" alt="SentinelDeck" width="820">
|
|
37
|
+
|
|
38
|
+
<p>
|
|
39
|
+
<strong>Passive attack-surface radar for small businesses, agencies, and security consultants.</strong><br>
|
|
40
|
+
One safe scan turns a domain into a clear risk grade, structured JSON, and a client-ready report.
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<table>
|
|
46
|
+
<tr>
|
|
47
|
+
<td><b>Testing</b></td>
|
|
48
|
+
<td>
|
|
49
|
+
<a href="https://github.com/sanmaxdev/SentinelDeck/actions/workflows/ci.yml"><img alt="tests" src="https://img.shields.io/github/actions/workflow/status/sanmaxdev/SentinelDeck/ci.yml?style=flat-square&labelColor=0a0a0f&color=dc2626&label=tests"></a>
|
|
50
|
+
</td>
|
|
51
|
+
</tr>
|
|
52
|
+
<tr>
|
|
53
|
+
<td><b>Code quality</b></td>
|
|
54
|
+
<td>
|
|
55
|
+
<a href="https://github.com/sanmaxdev/SentinelDeck/actions/workflows/security.yml"><img alt="security" src="https://img.shields.io/github/actions/workflow/status/sanmaxdev/SentinelDeck/security.yml?style=flat-square&labelColor=0a0a0f&color=dc2626&label=security"></a>
|
|
56
|
+
<a href="https://github.com/sanmaxdev/SentinelDeck/blob/main/.pre-commit-config.yaml"><img alt="pre-commit" src="https://img.shields.io/badge/pre--commit-enabled-dc2626?style=flat-square&labelColor=0a0a0f&logo=pre-commit&logoColor=white"></a>
|
|
57
|
+
</td>
|
|
58
|
+
</tr>
|
|
59
|
+
<tr>
|
|
60
|
+
<td><b>Code style</b></td>
|
|
61
|
+
<td>
|
|
62
|
+
<a href="https://github.com/astral-sh/ruff"><img alt="ruff" src="https://img.shields.io/badge/code%20style-ruff-dc2626?style=flat-square&labelColor=0a0a0f"></a>
|
|
63
|
+
<img alt="typed" src="https://img.shields.io/badge/typed-PEP%20561-dc2626?style=flat-square&labelColor=0a0a0f">
|
|
64
|
+
</td>
|
|
65
|
+
</tr>
|
|
66
|
+
<tr>
|
|
67
|
+
<td><b>Package</b></td>
|
|
68
|
+
<td>
|
|
69
|
+
<a href="https://pypi.org/project/sentineldeck/"><img alt="pypi" src="https://img.shields.io/pypi/v/sentineldeck?style=flat-square&labelColor=0a0a0f&color=dc2626&label=pypi"></a>
|
|
70
|
+
<img alt="downloads" src="https://img.shields.io/pypi/dm/sentineldeck?style=flat-square&labelColor=0a0a0f&color=dc2626&label=downloads">
|
|
71
|
+
<img alt="status" src="https://img.shields.io/badge/status-alpha-dc2626?style=flat-square&labelColor=0a0a0f">
|
|
72
|
+
<img alt="python" src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-dc2626?style=flat-square&labelColor=0a0a0f">
|
|
73
|
+
<a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-dc2626?style=flat-square&labelColor=0a0a0f"></a>
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
<tr>
|
|
77
|
+
<td><b>Safety</b></td>
|
|
78
|
+
<td>
|
|
79
|
+
<img alt="passive" src="https://img.shields.io/badge/scans-passive%20only-dc2626?style=flat-square&labelColor=0a0a0f">
|
|
80
|
+
<a href="SECURITY.md"><img alt="security policy" src="https://img.shields.io/badge/security-policy-dc2626?style=flat-square&labelColor=0a0a0f"></a>
|
|
81
|
+
</td>
|
|
82
|
+
</tr>
|
|
83
|
+
</table>
|
|
84
|
+
|
|
85
|
+
SentinelDeck inspects the public-facing posture of a domain across DNS, HTTP,
|
|
86
|
+
TLS, email authentication, and its certificate-transparency footprint, using
|
|
87
|
+
only the kind of normal lookups any browser or mail server would make. There is
|
|
88
|
+
no intrusive scanning, no exploitation, and nothing a domain owner would not
|
|
89
|
+
expect. The result is a risk score, an A to F grade, and a set of prioritised
|
|
90
|
+
findings, each with a concrete copy-paste fix.
|
|
91
|
+
|
|
92
|
+
It is built for the people who need that picture fast: an agency qualifying a
|
|
93
|
+
prospect, a consultant producing a client report, or a small team checking its
|
|
94
|
+
own footprint.
|
|
95
|
+
|
|
96
|
+
## Contents
|
|
97
|
+
|
|
98
|
+
- [Features](#features)
|
|
99
|
+
- [What it checks](#what-it-checks)
|
|
100
|
+
- [Installation](#installation)
|
|
101
|
+
- [Usage](#usage)
|
|
102
|
+
- [Example output](#example-output)
|
|
103
|
+
- [How it works](#how-it-works)
|
|
104
|
+
- [Development](#development)
|
|
105
|
+
- [Safety model](#safety-model)
|
|
106
|
+
- [Support](#support)
|
|
107
|
+
- [License](#license)
|
|
108
|
+
|
|
109
|
+
## Features
|
|
110
|
+
|
|
111
|
+
<table>
|
|
112
|
+
<tr>
|
|
113
|
+
<td width="50%" valign="top">
|
|
114
|
+
<h3>Passive and safe by design</h3>
|
|
115
|
+
Only standard DNS, HTTP, TLS, and email lookups, the same requests any
|
|
116
|
+
browser or mail server makes. Run it against any domain you are authorised
|
|
117
|
+
to assess.
|
|
118
|
+
</td>
|
|
119
|
+
<td width="50%" valign="top">
|
|
120
|
+
<h3>Accurate, with a confidence model</h3>
|
|
121
|
+
DNS is resolved in-process and certificates are parsed directly. Any check
|
|
122
|
+
that cannot be confirmed is marked unverified and kept out of the score, so
|
|
123
|
+
a client never sees a guess presented as fact.
|
|
124
|
+
</td>
|
|
125
|
+
</tr>
|
|
126
|
+
<tr>
|
|
127
|
+
<td width="50%" valign="top">
|
|
128
|
+
<h3>Five surfaces in one pass</h3>
|
|
129
|
+
DNS hygiene, HTTP security headers, TLS certificate quality, email
|
|
130
|
+
authentication, and domain registration intelligence, scored together into
|
|
131
|
+
a single picture.
|
|
132
|
+
</td>
|
|
133
|
+
<td width="50%" valign="top">
|
|
134
|
+
<h3>Clear risk score and grade</h3>
|
|
135
|
+
Every finding is weighted by severity into a 0 to 100 risk score and an A to
|
|
136
|
+
F grade, each paired with a prioritised, plain-language remediation step.
|
|
137
|
+
</td>
|
|
138
|
+
</tr>
|
|
139
|
+
<tr>
|
|
140
|
+
<td width="50%" valign="top">
|
|
141
|
+
<h3>Copy-paste remediation</h3>
|
|
142
|
+
Every finding ships the exact fix, not just advice: the precise DNS record,
|
|
143
|
+
HTTP header, or server config that resolves it, each with an authoritative
|
|
144
|
+
reference. Carried in both the JSON and the HTML report.
|
|
145
|
+
</td>
|
|
146
|
+
<td width="50%" valign="top">
|
|
147
|
+
<h3>Interactive remediation simulator</h3>
|
|
148
|
+
The HTML report lets a client tick off the fixes they plan to make and
|
|
149
|
+
watch the projected score and grade climb live, with one-click "quick wins"
|
|
150
|
+
that picks the shortest path to grade A.
|
|
151
|
+
</td>
|
|
152
|
+
</tr>
|
|
153
|
+
<tr>
|
|
154
|
+
<td width="50%" valign="top">
|
|
155
|
+
<h3>Attack-surface mapping</h3>
|
|
156
|
+
Reads certificate transparency logs to discover the domain's public
|
|
157
|
+
subdomains, flags potentially sensitive names (dev, staging, admin, vpn),
|
|
158
|
+
and detects dangling CNAMEs an attacker could take over.
|
|
159
|
+
</td>
|
|
160
|
+
<td width="50%" valign="top">
|
|
161
|
+
<h3>Monitoring and alerts</h3>
|
|
162
|
+
Diff any two scans, or run the monitor command on a schedule to scan,
|
|
163
|
+
compare against the last run, and post a webhook alert (Slack, Discord, or
|
|
164
|
+
custom) the moment a domain's posture regresses.
|
|
165
|
+
</td>
|
|
166
|
+
</tr>
|
|
167
|
+
<tr>
|
|
168
|
+
<td width="50%" valign="top">
|
|
169
|
+
<h3>Report-ready outputs</h3>
|
|
170
|
+
Structured JSON for automation, a polished dark and red HTML report for
|
|
171
|
+
clients, a shareable score card, an embeddable grade badge, and an HTML
|
|
172
|
+
change report.
|
|
173
|
+
</td>
|
|
174
|
+
<td width="50%" valign="top">
|
|
175
|
+
<h3>Resilient by design</h3>
|
|
176
|
+
Two certificate-transparency sources (crt.sh with a CertSpotter fallback)
|
|
177
|
+
and a DNS-over-HTTPS fallback for blocked networks, so a scan keeps working
|
|
178
|
+
where a naive tool would silently fail.
|
|
179
|
+
</td>
|
|
180
|
+
</tr>
|
|
181
|
+
</table>
|
|
182
|
+
|
|
183
|
+
## What it checks
|
|
184
|
+
|
|
185
|
+
| Area | Checks |
|
|
186
|
+
| --- | --- |
|
|
187
|
+
| **DNS** | Resolution, CAA issuance control, DNSSEC |
|
|
188
|
+
| **HTTP** | HTTPS reachability, HTTP to HTTPS redirect, security-header presence **and** value quality, security.txt, cookie flags, version disclosure |
|
|
189
|
+
| **TLS** | Trust and failure reason (expired, self-signed, hostname mismatch, untrusted), expiry, protocol version, key strength, signature algorithm, hostname match |
|
|
190
|
+
| **Email** | MX, SPF (policy, multiple records, 10-lookup limit), DMARC (policy, subdomain policy, enforcement coverage), DKIM, MTA-STS, TLS-RPT, BIMI |
|
|
191
|
+
| **Domain** | Registrar, registration age, and expiry via RDAP |
|
|
192
|
+
| **Subdomains** | Public subdomain discovery via certificate transparency (crt.sh, CertSpotter), sensitive-name flagging, and dangling-CNAME takeover detection |
|
|
193
|
+
|
|
194
|
+
Every issue is scored by severity into a 0 to 100 risk score and an A to F grade.
|
|
195
|
+
|
|
196
|
+
## Installation
|
|
197
|
+
|
|
198
|
+
SentinelDeck requires **Python 3.10 or newer**.
|
|
199
|
+
|
|
200
|
+
From PyPI (available once the first release is published, see
|
|
201
|
+
[RELEASING.md](RELEASING.md)):
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pip install sentineldeck
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
From source:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
git clone https://github.com/sanmaxdev/SentinelDeck.git
|
|
211
|
+
cd SentinelDeck
|
|
212
|
+
python3 -m venv .venv
|
|
213
|
+
. .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
214
|
+
pip install -e .
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Either way, this puts the `sentineldeck` command on your path. To verify:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
sentineldeck --version
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
For development, install the dev extras (pytest and ruff):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
pip install -e ".[dev]"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Usage
|
|
230
|
+
|
|
231
|
+
Scan a domain and write a JSON report:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
sentineldeck scan example.com --output reports/example.json
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Accept findings you have already reviewed so they stop affecting the score, by
|
|
238
|
+
listing their ids in a suppressions file:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
sentineldeck scan example.com --suppress .sentineldeck-ignore
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Each line is a finding id (globs allowed, e.g. `subdomain-takeover:*`), and `#`
|
|
245
|
+
starts a comment. Accepted findings still appear under "Accepted" in the report
|
|
246
|
+
but are kept out of the risk score, so a known and accepted risk does not drag
|
|
247
|
+
the grade down on every re-scan.
|
|
248
|
+
|
|
249
|
+
Render a client-ready HTML report, a shareable score card, and a badge. The HTML
|
|
250
|
+
report includes the attack-surface map and the interactive remediation
|
|
251
|
+
simulator:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
sentineldeck report reports/example.json \
|
|
255
|
+
--html reports/example.html \
|
|
256
|
+
--svg reports/example-card.svg \
|
|
257
|
+
--badge reports/example-badge.svg
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Track how a domain's posture changes between two scans:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
sentineldeck diff reports/example-may.json reports/example-june.json \
|
|
264
|
+
--html reports/example-change.html
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The `diff` command shows what is new, what was resolved, score and grade
|
|
268
|
+
movement, and any severity escalations. It exits non-zero with `--exit-code`
|
|
269
|
+
when the posture regresses (a new high or critical finding, or a higher score),
|
|
270
|
+
so it drops straight into a cron job or CI step for scheduled monitoring.
|
|
271
|
+
|
|
272
|
+
Watch a domain on a schedule and get alerted when it regresses:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
sentineldeck monitor example.com --webhook https://hooks.slack.com/services/...
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
The `monitor` command scans, compares against the previous run (stored under
|
|
279
|
+
`.sentineldeck/` by default), and saves the new report as the latest, so a cron
|
|
280
|
+
job or scheduled task becomes a standing watch. With `--webhook` it posts an
|
|
281
|
+
alert (Slack, Discord, or any custom endpoint) when the posture regresses. The
|
|
282
|
+
first run establishes a baseline; use `--alert-on change` to hear about any
|
|
283
|
+
change, and `--exit-code` to fail a job on regression.
|
|
284
|
+
|
|
285
|
+
Useful flags: `--pretty` prints the full JSON to stdout, `--timeout` bounds the
|
|
286
|
+
HTTP and TLS probes, and `diff --json` or `diff -o` emit the structured delta.
|
|
287
|
+
|
|
288
|
+
## Example output
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"target": "example.com",
|
|
293
|
+
"risk_score": 27,
|
|
294
|
+
"grade": "B",
|
|
295
|
+
"findings": [
|
|
296
|
+
{ "id": "dmarc-missing", "severity": "medium", "confidence": "confirmed", "...": "..." }
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## How it works
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
src/sentineldeck/
|
|
305
|
+
├── scanner.py # runs every probe concurrently and assembles the report
|
|
306
|
+
├── scanners/ # one module per surface: dns, dns_hygiene, tls, http_headers,
|
|
307
|
+
│ # email_security, domain_intel, subdomains, takeover
|
|
308
|
+
├── risk/scoring.py # turns raw check results into scored findings
|
|
309
|
+
├── remediation.py # maps each finding to a concrete copy-paste fix
|
|
310
|
+
├── diff.py # compares two reports into a structured change delta
|
|
311
|
+
├── monitor.py # scan, compare to the last run, and persist state
|
|
312
|
+
├── alerts.py # webhook delivery on regression
|
|
313
|
+
├── reporters/ # json, html, svg (card + badge), and diff renderers
|
|
314
|
+
└── models.py # Finding and ScanReport data models
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Each scanner is independent and keeps its network call injectable, so the whole
|
|
318
|
+
suite is tested offline with mocked DNS, HTTP, and certificate-transparency data.
|
|
319
|
+
|
|
320
|
+
## Development
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
pip install -e ".[dev]"
|
|
324
|
+
ruff check .
|
|
325
|
+
pytest -q
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Optionally enable the pre-commit hooks so linting runs on every commit:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
pip install pre-commit && pre-commit install
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
CI runs ruff and the full test suite on Python 3.10, 3.11, and 3.12, and CodeQL
|
|
335
|
+
scans the codebase for security issues on every push.
|
|
336
|
+
|
|
337
|
+
## Safety model
|
|
338
|
+
|
|
339
|
+
SentinelDeck is **passive-first**. It performs only normal DNS lookups and
|
|
340
|
+
standard HTTP and TLS metadata requests against the supplied domain, plus public
|
|
341
|
+
certificate-transparency queries. It does not probe, fuzz, or exploit anything.
|
|
342
|
+
Use it only on domains you own or are authorised to assess.
|
|
343
|
+
|
|
344
|
+
## Support
|
|
345
|
+
|
|
346
|
+
- **Questions and bug reports**: open an issue on the
|
|
347
|
+
[issue tracker](https://github.com/sanmaxdev/SentinelDeck/issues).
|
|
348
|
+
- **Security issues**: please follow the [security policy](SECURITY.md) instead
|
|
349
|
+
of filing a public issue.
|
|
350
|
+
- **Contributing**: see [CONTRIBUTING.md](CONTRIBUTING.md). New checks must be
|
|
351
|
+
passive-safe and come with tests. This project follows a
|
|
352
|
+
[Code of Conduct](CODE_OF_CONDUCT.md).
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
[MIT](LICENSE)
|