CableProbe 0.3.6__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.
- cableprobe-0.3.6/CableProbe.egg-info/PKG-INFO +371 -0
- cableprobe-0.3.6/CableProbe.egg-info/SOURCES.txt +51 -0
- cableprobe-0.3.6/CableProbe.egg-info/dependency_links.txt +1 -0
- cableprobe-0.3.6/CableProbe.egg-info/entry_points.txt +2 -0
- cableprobe-0.3.6/CableProbe.egg-info/requires.txt +12 -0
- cableprobe-0.3.6/CableProbe.egg-info/top_level.txt +1 -0
- cableprobe-0.3.6/LICENSE +21 -0
- cableprobe-0.3.6/PKG-INFO +371 -0
- cableprobe-0.3.6/README.md +339 -0
- cableprobe-0.3.6/cableprobe/__init__.py +22 -0
- cableprobe-0.3.6/cableprobe/advice.py +208 -0
- cableprobe-0.3.6/cableprobe/analysis.py +240 -0
- cableprobe-0.3.6/cableprobe/cli.py +467 -0
- cableprobe-0.3.6/cableprobe/config.py +126 -0
- cableprobe-0.3.6/cableprobe/data/__init__.py +4 -0
- cableprobe-0.3.6/cableprobe/data/default_rules.yaml +564 -0
- cableprobe-0.3.6/cableprobe/logging_config.py +48 -0
- cableprobe-0.3.6/cableprobe/models.py +187 -0
- cableprobe-0.3.6/cableprobe/probes/__init__.py +21 -0
- cableprobe-0.3.6/cableprobe/probes/base.py +138 -0
- cableprobe-0.3.6/cableprobe/probes/block.py +94 -0
- cableprobe-0.3.6/cableprobe/probes/input_devices.py +172 -0
- cableprobe-0.3.6/cableprobe/probes/kernel_log.py +141 -0
- cableprobe-0.3.6/cableprobe/probes/keystroke_cadence.py +237 -0
- cableprobe-0.3.6/cableprobe/probes/media_devices.py +230 -0
- cableprobe-0.3.6/cableprobe/probes/network.py +99 -0
- cableprobe-0.3.6/cableprobe/probes/network_state.py +298 -0
- cableprobe-0.3.6/cableprobe/probes/processes.py +103 -0
- cableprobe-0.3.6/cableprobe/probes/registry.py +69 -0
- cableprobe-0.3.6/cableprobe/probes/serial_devices.py +144 -0
- cableprobe-0.3.6/cableprobe/probes/system_state.py +254 -0
- cableprobe-0.3.6/cableprobe/probes/udev_monitor.py +238 -0
- cableprobe-0.3.6/cableprobe/probes/usb.py +163 -0
- cableprobe-0.3.6/cableprobe/probes/usb_sysfs.py +295 -0
- cableprobe-0.3.6/cableprobe/probes/usbc_pd.py +176 -0
- cableprobe-0.3.6/cableprobe/probes/wifi_scan.py +246 -0
- cableprobe-0.3.6/cableprobe/report.py +247 -0
- cableprobe-0.3.6/cableprobe/rules.py +201 -0
- cableprobe-0.3.6/cableprobe/sanitize.py +59 -0
- cableprobe-0.3.6/cableprobe/session.py +254 -0
- cableprobe-0.3.6/cableprobe/system_info.py +65 -0
- cableprobe-0.3.6/pyproject.toml +57 -0
- cableprobe-0.3.6/setup.cfg +4 -0
- cableprobe-0.3.6/tests/test_advice.py +88 -0
- cableprobe-0.3.6/tests/test_analysis.py +126 -0
- cableprobe-0.3.6/tests/test_cli.py +229 -0
- cableprobe-0.3.6/tests/test_config.py +78 -0
- cableprobe-0.3.6/tests/test_probes_new.py +892 -0
- cableprobe-0.3.6/tests/test_probes_parsing.py +133 -0
- cableprobe-0.3.6/tests/test_report.py +116 -0
- cableprobe-0.3.6/tests/test_rules.py +290 -0
- cableprobe-0.3.6/tests/test_sanitize.py +70 -0
- cableprobe-0.3.6/tests/test_session.py +201 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CableProbe
|
|
3
|
+
Version: 0.3.6
|
|
4
|
+
Summary: Open-source defensive USB cable analysis tool for Linux
|
|
5
|
+
Author-email: Stable State Consulting Ltd <contributors@cableprobe.com>
|
|
6
|
+
Maintainer-email: Stable State Consulting Ltd <contributors@cableprobe.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://www.cableprobe.com
|
|
9
|
+
Project-URL: Source, https://github.com/rosscooney/CableProbe
|
|
10
|
+
Project-URL: Download, https://github.com/rosscooney/CableProbe/releases
|
|
11
|
+
Project-URL: Issues, https://github.com/rosscooney/CableProbe/issues
|
|
12
|
+
Keywords: usb,usb-c,security,defensive,raspberry-pi,hardware
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: typer>=0.12
|
|
23
|
+
Requires-Dist: pydantic>=2.6
|
|
24
|
+
Requires-Dist: pyudev>=0.24; sys_platform == "linux"
|
|
25
|
+
Requires-Dist: psutil>=5.9
|
|
26
|
+
Requires-Dist: PyYAML>=6.0
|
|
27
|
+
Requires-Dist: rich>=13.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# CableProbe
|
|
34
|
+
|
|
35
|
+
**CableProbe is an open-source defensive USB cable analysis tool for Linux**
|
|
36
|
+
(developed and tested on Raspberry Pi OS / Debian, and reasonably portable to
|
|
37
|
+
other Debian/Ubuntu systems).
|
|
38
|
+
|
|
39
|
+
- Home page: <https://www.cableprobe.com>
|
|
40
|
+
- Source & downloads: <https://github.com/rosscooney/CableProbe>
|
|
41
|
+
([releases](https://github.com/rosscooney/CableProbe/releases))
|
|
42
|
+
- Package: [`cableprobe` on PyPI](https://pypi.org/project/cableprobe/)
|
|
43
|
+
|
|
44
|
+
CableProbe watches a sacrificial Linux host while you connect an *unknown* USB
|
|
45
|
+
cable — USB-C **or** USB-A, charge-only or data — then compares before, during
|
|
46
|
+
and after to surface hidden HID devices, rogue network gadgets, mass storage,
|
|
47
|
+
serial channels, transient enumeration and kernel errors.
|
|
48
|
+
|
|
49
|
+
CableProbe **only observes, records and reports**. It does not inject payloads,
|
|
50
|
+
exploit anything, capture credentials, establish persistence or provide remote
|
|
51
|
+
access. It is a monitoring tool for a sacrificial test host.
|
|
52
|
+
|
|
53
|
+
> ⚠️ CableProbe **cannot prove that a cable is safe or uncompromised.** A clean
|
|
54
|
+
> report means CableProbe did not observe anything notable during that session,
|
|
55
|
+
> not that the cable is benign. Use it as one input to your own judgement.
|
|
56
|
+
|
|
57
|
+
> ⚠️ Run this on a dedicated, disposable Raspberry Pi that holds no sensitive
|
|
58
|
+
> data and is isolated from networks you care about. Treat any cable under test
|
|
59
|
+
> as hostile hardware.
|
|
60
|
+
|
|
61
|
+
## How it works
|
|
62
|
+
|
|
63
|
+
A session has three phases:
|
|
64
|
+
|
|
65
|
+
| Phase | What happens |
|
|
66
|
+
|-------------|--------------------------------------------------------------------------|
|
|
67
|
+
| `baseline` | Observe the Pi *before* the unknown cable is connected. |
|
|
68
|
+
| `test` | You connect / power the unknown cable; CableProbe keeps observing. |
|
|
69
|
+
| `post_test` | You disconnect the cable; CableProbe observes the return to baseline. |
|
|
70
|
+
|
|
71
|
+
CableProbe then compares the three phases and writes a structured JSON report
|
|
72
|
+
describing everything that **appeared, disappeared or changed** in correlation
|
|
73
|
+
with the cable, and runs a set of YAML-configurable detection rules over those
|
|
74
|
+
differences to produce prioritised findings. The console summary ends with a
|
|
75
|
+
plain-language **"What this means"** box — an overall read of the session and
|
|
76
|
+
what to do next, written for a moderately technical reader rather than a USB
|
|
77
|
+
specialist.
|
|
78
|
+
|
|
79
|
+
Connector type does not matter — CableProbe watches how the host reacts, not the
|
|
80
|
+
plug. Any cable you can get one end of into a port on the test Pi works: USB-C or
|
|
81
|
+
USB-A, either orientation, with a passive adapter if you need one. The `usbc_pd`
|
|
82
|
+
probe additionally reports Type-C power-delivery state when the Pi exposes a
|
|
83
|
+
Type-C port, and simply skips otherwise.
|
|
84
|
+
|
|
85
|
+
### Probes (observation only)
|
|
86
|
+
|
|
87
|
+
| Probe | Observes |
|
|
88
|
+
|-------------------|---------------------------------------------------------------------------------|
|
|
89
|
+
| `udev_monitor` | Live udev add/remove/change events across all subsystems. |
|
|
90
|
+
| `usb` | USB device inventory (vendor/model, interface classes, HID, hub). |
|
|
91
|
+
| `usb_descriptors` | Per-interface USB descriptors from sysfs (class/subclass/driver/endpoints). |
|
|
92
|
+
| `usb_topology` | USB hub/port tree — hub count, device count, depth, per-hub inventory. |
|
|
93
|
+
| `usbc_pd` | USB-C / Power Delivery port + partner state: data/power roles, alt modes. |
|
|
94
|
+
| `block` | Block devices and their transport (`lsblk`). |
|
|
95
|
+
| `mounts` | Filesystem mounts backed by a device or under removable-media paths. |
|
|
96
|
+
| `network` | Network interfaces, drivers, USB-ness, addresses. |
|
|
97
|
+
| `routing` | Default route and DNS resolvers (gateway / resolver hijack). |
|
|
98
|
+
| `listeners` | TCP `LISTEN` sockets on fixed (non-ephemeral) ports; owning process when `ss` is present. |
|
|
99
|
+
| `input` | Input / HID devices (keyboards, mice, tablets). |
|
|
100
|
+
| `serial` | Serial / modem (TTY) devices, including USB serial (CDC-ACM, FTDI, cp210x). |
|
|
101
|
+
| `audio` | Audio (sound-card) devices, including USB audio class. |
|
|
102
|
+
| `video` | video4linux camera / capture devices, including UVC. |
|
|
103
|
+
| `pci` | PCI and Thunderbolt devices (USB4/TBT PCIe-tunnel / DMA surface). |
|
|
104
|
+
| `kernel_modules` | Loaded kernel modules — catches gadget drivers loaded on connect. |
|
|
105
|
+
| `wifi_scan` | Wi-Fi APs in range (an implant cable may run its own AP). Active scan, boundary-only. |
|
|
106
|
+
| `keystroke_cadence` | Key-press *timing* per input device — flags superhuman / robotic typing. |
|
|
107
|
+
| `process` | New userspace processes started after the session began (kernel threads excluded). |
|
|
108
|
+
| `kernel_log` | USB-relevant kernel / journal lines emitted during the session. |
|
|
109
|
+
|
|
110
|
+
Probes that need hardware or kernel interfaces the host does not expose (no
|
|
111
|
+
Type-C class, no `/sys/bus/pci`, …) are skipped automatically. `cableprobe
|
|
112
|
+
check` lists them as `FAIL` with the reason, and a run notes them once as
|
|
113
|
+
`skipped: … (interface not present on this host)` — that is expected, not an
|
|
114
|
+
error. Raspberry Pi 4, for example, has no `usbc_pd` (its USB-C port is
|
|
115
|
+
power-only); Raspberry Pi 5 does. To silence a skip entirely, drop the probe
|
|
116
|
+
from `probes.enabled` in your config.
|
|
117
|
+
|
|
118
|
+
Two probes have side effects worth knowing about:
|
|
119
|
+
|
|
120
|
+
- `wifi_scan` runs an **active** Wi-Fi scan (`iw` / `nmcli`) at each phase
|
|
121
|
+
boundary, which briefly interrupts any Wi-Fi association on that interface. It
|
|
122
|
+
never associates with a discovered AP.
|
|
123
|
+
- `keystroke_cadence` reads `/dev/input/event*` for key-press **timing only** —
|
|
124
|
+
the key `code` of every event is discarded before anything is stored, so it
|
|
125
|
+
never learns which keys were pressed. Set `capture_keystroke_timing: false`
|
|
126
|
+
to disable it.
|
|
127
|
+
|
|
128
|
+
## Install
|
|
129
|
+
|
|
130
|
+
Requires Python 3.11+. See [DISTRIBUTING.md](DISTRIBUTING.md) for the full
|
|
131
|
+
picture; the short version:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# 1. pip / pipx on an existing Raspberry Pi OS / Debian host
|
|
135
|
+
pipx install cableprobe
|
|
136
|
+
sudo apt install usbutils util-linux iw # CLI tools CableProbe shells out to
|
|
137
|
+
# note: this puts `cableprobe` in ~/.local/bin, which is NOT on root's PATH,
|
|
138
|
+
# so `sudo cableprobe` needs a full path (see "command not found" under Usage).
|
|
139
|
+
|
|
140
|
+
# 2. one command on a Pi (isolated venv under /opt/cableprobe) — RECOMMENDED for
|
|
141
|
+
# a test rig: links /usr/local/bin/cableprobe so `sudo cableprobe` just works,
|
|
142
|
+
# and apt-installs the helper CLIs (usbutils, util-linux, iw, pciutils)
|
|
143
|
+
sudo ./scripts/install.sh # sudo scripts/uninstall.sh to remove
|
|
144
|
+
|
|
145
|
+
# 3. from a checkout, for development
|
|
146
|
+
git clone https://github.com/rosscooney/CableProbe cableprobe && cd cableprobe
|
|
147
|
+
python3 -m venv .venv && . .venv/bin/activate
|
|
148
|
+
pip install -e ".[dev]"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For a **disposable Raspberry Pi image**, build your own from stock Raspberry Pi
|
|
152
|
+
OS using the pi-gen custom stage in [`packaging/pi-gen/`](packaging/pi-gen/) —
|
|
153
|
+
CableProbe ships the recipe, not a prebuilt image.
|
|
154
|
+
|
|
155
|
+
`pyudev` needs `libudev` (present on Raspberry Pi OS / Debian). On non-Linux
|
|
156
|
+
hosts CableProbe still installs and its `--help` / `check` / `report` commands
|
|
157
|
+
work, but the live probes are unavailable.
|
|
158
|
+
|
|
159
|
+
## Upgrading
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# 1a. pipx — to the latest *published* release on PyPI
|
|
163
|
+
pipx upgrade cableprobe
|
|
164
|
+
pipx upgrade-all # everything pipx manages
|
|
165
|
+
pipx install --force cableprobe==0.3.6 # pin / roll back to a specific release
|
|
166
|
+
|
|
167
|
+
# 1b. pipx — to the latest development code (main), ahead of the last release
|
|
168
|
+
pipx install --force "git+https://github.com/rosscooney/CableProbe"
|
|
169
|
+
pipx install --force "cableprobe @ git+https://github.com/rosscooney/CableProbe@main"
|
|
170
|
+
|
|
171
|
+
# 2. scripts/install.sh — re-run against a fresh checkout; reinstalls
|
|
172
|
+
# into /opt/cableprobe/venv in place
|
|
173
|
+
git -C cableprobe pull && sudo ./cableprobe/scripts/install.sh
|
|
174
|
+
|
|
175
|
+
# 3. development checkout
|
|
176
|
+
git pull && pip install -e ".[dev]"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Check what you have and that the host is still ready afterwards:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cableprobe --version
|
|
183
|
+
cableprobe check
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`pipx upgrade cableprobe` only moves you to a **higher version number on PyPI**.
|
|
187
|
+
`cableprobe is already at latest version 0.3.6` means there is no newer release
|
|
188
|
+
— publish one first (bump `version` in `pyproject.toml`, tag, push to PyPI), or
|
|
189
|
+
use the `git+https://…` form above to track `main`. If a new version drops a
|
|
190
|
+
probe or changes report fields it is called out in the GitHub release notes;
|
|
191
|
+
saved `.cableprobe.json` reports from older versions still open with
|
|
192
|
+
`cableprobe report`.
|
|
193
|
+
|
|
194
|
+
## Usage
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Check the host is ready
|
|
198
|
+
cableprobe check
|
|
199
|
+
|
|
200
|
+
# Run a session (you will be prompted before each phase; a progress bar
|
|
201
|
+
# tracks each phase's timer)
|
|
202
|
+
sudo cableprobe run --name "suspect-cable-01" \
|
|
203
|
+
--baseline 30 --test 90 --post-test 30
|
|
204
|
+
|
|
205
|
+
# Unattended / rig mode: advance phases on a timer instead of prompts
|
|
206
|
+
sudo cableprobe run --auto --baseline 20 --test 60 --post-test 20
|
|
207
|
+
|
|
208
|
+
# Inspect a saved report
|
|
209
|
+
cableprobe report cableprobe-sessions/2026*.cableprobe.json
|
|
210
|
+
cableprobe report <file> --format json | jq .
|
|
211
|
+
|
|
212
|
+
# See / customise detection rules
|
|
213
|
+
cableprobe rules
|
|
214
|
+
cableprobe rules my-rules.yaml
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Running with `sudo` is strongly recommended: without root the kernel-log,
|
|
218
|
+
udev-attribute, USB-descriptor, keystroke-timing and raw-socket probes see much
|
|
219
|
+
less detail and some are skipped entirely. `cableprobe run` detects this and, in
|
|
220
|
+
interactive mode, prints the `sudo` command and asks whether to continue anyway;
|
|
221
|
+
`--auto` just warns and proceeds. `cableprobe check` flags it too.
|
|
222
|
+
|
|
223
|
+
**`sudo: cableprobe: command not found`?** A `pipx` / `pip install --user`
|
|
224
|
+
install puts `cableprobe` in `~/.local/bin`, which is not on root's `PATH`. Run
|
|
225
|
+
it by absolute path (`sudo "$(which cableprobe)" check`), preserve your `PATH`
|
|
226
|
+
(`sudo env "PATH=$PATH" cableprobe check`), or install it on root's `PATH` once
|
|
227
|
+
with `sudo ./scripts/install.sh` (below) — that is the recommended setup for a
|
|
228
|
+
test rig. The not-root warning now prints whichever of these applies to your
|
|
229
|
+
install.
|
|
230
|
+
|
|
231
|
+
### Exit codes
|
|
232
|
+
|
|
233
|
+
`cableprobe run --fail-on-findings` exits `10` / `20` / `30` for the highest
|
|
234
|
+
finding severity (`medium` / `high` / `critical`), otherwise `0`. Without the
|
|
235
|
+
flag, `run` always exits `0` on a completed session.
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
Optional YAML config (`--config cableprobe.yaml`):
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
session:
|
|
243
|
+
baseline_seconds: 30
|
|
244
|
+
test_seconds: 90
|
|
245
|
+
post_test_seconds: 30
|
|
246
|
+
sample_interval_seconds: 2.0
|
|
247
|
+
probes:
|
|
248
|
+
# default: all probes; list a subset to narrow the session
|
|
249
|
+
enabled: [udev_monitor, usb, usb_descriptors, usb_topology, usbc_pd, block,
|
|
250
|
+
mounts, network, routing, listeners, input, serial, audio, video,
|
|
251
|
+
pci, kernel_modules, wifi_scan, keystroke_cadence, process, kernel_log]
|
|
252
|
+
kernel_log_backend: auto # auto | journalctl | dmesg
|
|
253
|
+
kernel_log_keywords: [] # extra case-insensitive substrings to keep
|
|
254
|
+
capture_process_cmdline: true # false => store only the executable name
|
|
255
|
+
capture_keystroke_timing: true # false => disable the keystroke_cadence probe
|
|
256
|
+
rules_file: null # null => packaged default rules
|
|
257
|
+
output_dir: ./cableprobe-sessions
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Reports are written with mode `0600` (they can contain host details, MAC
|
|
261
|
+
addresses and process command lines). All device-supplied text (USB descriptor
|
|
262
|
+
strings, device names, kernel log lines) is stripped of control characters and
|
|
263
|
+
length-bounded before it is stored or shown, so a hostile cable cannot inject
|
|
264
|
+
terminal escape sequences via the report or the console summary.
|
|
265
|
+
|
|
266
|
+
### Detection rules
|
|
267
|
+
|
|
268
|
+
Rules live in YAML (see `cableprobe/data/default_rules.yaml`). Each rule matches
|
|
269
|
+
a phase *delta* and raises a finding:
|
|
270
|
+
|
|
271
|
+
```yaml
|
|
272
|
+
- id: hid-keyboard-appeared-on-connect
|
|
273
|
+
title: HID keyboard appeared while the unknown cable was connected
|
|
274
|
+
severity: high
|
|
275
|
+
rationale: >
|
|
276
|
+
A keyboard-class HID device that enumerates only when the cable is
|
|
277
|
+
connected is the classic BadUSB signature.
|
|
278
|
+
match:
|
|
279
|
+
change: appeared # appeared | disappeared | modified
|
|
280
|
+
first_seen_phase: test # baseline | test | post_test
|
|
281
|
+
kind: [input_device, hid_device]
|
|
282
|
+
attributes:
|
|
283
|
+
any:
|
|
284
|
+
- { key: ID_INPUT_KEYBOARD, equals: "1" }
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Match keys: `change`, `kind`, `first_seen_phase`, `reverted_after_disconnect`,
|
|
288
|
+
`transient`, `label_regex`, `event_action`, and `attributes.all` / `attributes.any`
|
|
289
|
+
(conditions: `equals`, `not_equals`, `exists`, `contains`, `not_contains`, `regex`).
|
|
290
|
+
|
|
291
|
+
## Report structure
|
|
292
|
+
|
|
293
|
+
```jsonc
|
|
294
|
+
{
|
|
295
|
+
"metadata": { "session_name", "host", "config", "probes_used", "probe_warnings", ... },
|
|
296
|
+
"phases": { "baseline": {...}, "test": {...}, "post_test": {...} },
|
|
297
|
+
"deltas": [ { "change", "kind", "identity", "label",
|
|
298
|
+
"first_seen_phase", "present_in",
|
|
299
|
+
"reverted_after_disconnect", "transient",
|
|
300
|
+
"attributes", "attribute_changes", "related_events" } ],
|
|
301
|
+
"findings": [ { "rule_id", "title", "severity", "rationale", "evidence" } ],
|
|
302
|
+
"summary": { "delta_count", "cable_correlated_change_count",
|
|
303
|
+
"findings_by_severity", "highest_severity", ... }
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Development
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
pip install -e ".[dev]"
|
|
311
|
+
pytest
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
The analysis, rules and report layers are pure and fully unit-tested without
|
|
315
|
+
hardware. Each probe keeps a pure parser (of `lsusb` / `lsblk` / `/proc`
|
|
316
|
+
output) or sysfs-tree scanner that is tested against captured samples or a
|
|
317
|
+
fake `/sys` tree — see `tests/test_probes_parsing.py` and
|
|
318
|
+
`tests/test_probes_new.py`.
|
|
319
|
+
|
|
320
|
+
The source lives at <https://github.com/rosscooney/CableProbe>. See
|
|
321
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute,
|
|
322
|
+
[SECURITY.md](SECURITY.md) for how to report vulnerabilities privately, and
|
|
323
|
+
[RELEASING.md](RELEASING.md) for how maintainers cut a release to PyPI.
|
|
324
|
+
|
|
325
|
+
## Scope / non-goals
|
|
326
|
+
|
|
327
|
+
* CLI only — no web dashboard.
|
|
328
|
+
* The `usbc_pd` probe reads the kernel's USB-C / Power Delivery port state
|
|
329
|
+
(data/power roles, alternate modes); CableProbe does **not** do electrical
|
|
330
|
+
measurement of the cable itself — no voltage/current sampling, no e-marker
|
|
331
|
+
interrogation.
|
|
332
|
+
* No offensive capability of any kind, by design.
|
|
333
|
+
|
|
334
|
+
## Third-party dependencies
|
|
335
|
+
|
|
336
|
+
CableProbe does not copy or vendor third-party source code. It depends on a
|
|
337
|
+
small set of Python libraries and, at runtime, invokes standard Linux
|
|
338
|
+
command-line tools as separate, independently installed programs. See
|
|
339
|
+
[NOTICE.md](NOTICE.md) and the "Third-party licensing" note below in the repo
|
|
340
|
+
history / `docs`.
|
|
341
|
+
|
|
342
|
+
Direct Python dependencies and their licences:
|
|
343
|
+
|
|
344
|
+
| Package | Licence | Notes |
|
|
345
|
+
|------------------|--------------------|------------------------------------------------|
|
|
346
|
+
| typer | MIT | CLI framework |
|
|
347
|
+
| pydantic | MIT | data models |
|
|
348
|
+
| psutil | BSD-3-Clause | process / network inventory |
|
|
349
|
+
| PyYAML | MIT | config and rules parsing |
|
|
350
|
+
| rich | MIT | console rendering |
|
|
351
|
+
| pyudev | **LGPL-2.1-or-later** | Linux-only; imported as a library — see note |
|
|
352
|
+
| pytest, pytest-asyncio (dev only) | MIT, Apache-2.0 | test suite |
|
|
353
|
+
|
|
354
|
+
**Note on `pyudev`:** `pyudev` is LGPL-2.1-or-later. It is a normal, separately
|
|
355
|
+
installed Python dependency that CableProbe imports; it is not vendored or
|
|
356
|
+
modified. Distributing an MIT-licensed project that depends on an unmodified
|
|
357
|
+
LGPL library is standard practice, provided `pyudev` remains replaceable and its
|
|
358
|
+
source stays available (it is, from PyPI). If you redistribute CableProbe as a
|
|
359
|
+
bundled binary/image, keep `pyudev` as a replaceable component and include its
|
|
360
|
+
licence text. The Linux CLI tools CableProbe shells out to (`lsusb`/usbutils,
|
|
361
|
+
`lsblk`/`dmesg`/util-linux — GPL-2.0; `journalctl`/systemd — LGPL-2.1) are
|
|
362
|
+
invoked as independent programs and do not affect CableProbe's MIT licensing.
|
|
363
|
+
|
|
364
|
+
## Licence
|
|
365
|
+
|
|
366
|
+
CableProbe is open-source software created by Stable State Consulting Ltd and
|
|
367
|
+
released under the MIT License.
|
|
368
|
+
|
|
369
|
+
Copyright © 2026 Stable State Consulting Ltd.
|
|
370
|
+
|
|
371
|
+
See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
CableProbe.egg-info/PKG-INFO
|
|
5
|
+
CableProbe.egg-info/SOURCES.txt
|
|
6
|
+
CableProbe.egg-info/dependency_links.txt
|
|
7
|
+
CableProbe.egg-info/entry_points.txt
|
|
8
|
+
CableProbe.egg-info/requires.txt
|
|
9
|
+
CableProbe.egg-info/top_level.txt
|
|
10
|
+
cableprobe/__init__.py
|
|
11
|
+
cableprobe/advice.py
|
|
12
|
+
cableprobe/analysis.py
|
|
13
|
+
cableprobe/cli.py
|
|
14
|
+
cableprobe/config.py
|
|
15
|
+
cableprobe/logging_config.py
|
|
16
|
+
cableprobe/models.py
|
|
17
|
+
cableprobe/report.py
|
|
18
|
+
cableprobe/rules.py
|
|
19
|
+
cableprobe/sanitize.py
|
|
20
|
+
cableprobe/session.py
|
|
21
|
+
cableprobe/system_info.py
|
|
22
|
+
cableprobe/data/__init__.py
|
|
23
|
+
cableprobe/data/default_rules.yaml
|
|
24
|
+
cableprobe/probes/__init__.py
|
|
25
|
+
cableprobe/probes/base.py
|
|
26
|
+
cableprobe/probes/block.py
|
|
27
|
+
cableprobe/probes/input_devices.py
|
|
28
|
+
cableprobe/probes/kernel_log.py
|
|
29
|
+
cableprobe/probes/keystroke_cadence.py
|
|
30
|
+
cableprobe/probes/media_devices.py
|
|
31
|
+
cableprobe/probes/network.py
|
|
32
|
+
cableprobe/probes/network_state.py
|
|
33
|
+
cableprobe/probes/processes.py
|
|
34
|
+
cableprobe/probes/registry.py
|
|
35
|
+
cableprobe/probes/serial_devices.py
|
|
36
|
+
cableprobe/probes/system_state.py
|
|
37
|
+
cableprobe/probes/udev_monitor.py
|
|
38
|
+
cableprobe/probes/usb.py
|
|
39
|
+
cableprobe/probes/usb_sysfs.py
|
|
40
|
+
cableprobe/probes/usbc_pd.py
|
|
41
|
+
cableprobe/probes/wifi_scan.py
|
|
42
|
+
tests/test_advice.py
|
|
43
|
+
tests/test_analysis.py
|
|
44
|
+
tests/test_cli.py
|
|
45
|
+
tests/test_config.py
|
|
46
|
+
tests/test_probes_new.py
|
|
47
|
+
tests/test_probes_parsing.py
|
|
48
|
+
tests/test_report.py
|
|
49
|
+
tests/test_rules.py
|
|
50
|
+
tests/test_sanitize.py
|
|
51
|
+
tests/test_session.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cableprobe
|
cableprobe-0.3.6/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stable State Consulting Ltd
|
|
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.
|