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.
Files changed (53) hide show
  1. cableprobe-0.3.6/CableProbe.egg-info/PKG-INFO +371 -0
  2. cableprobe-0.3.6/CableProbe.egg-info/SOURCES.txt +51 -0
  3. cableprobe-0.3.6/CableProbe.egg-info/dependency_links.txt +1 -0
  4. cableprobe-0.3.6/CableProbe.egg-info/entry_points.txt +2 -0
  5. cableprobe-0.3.6/CableProbe.egg-info/requires.txt +12 -0
  6. cableprobe-0.3.6/CableProbe.egg-info/top_level.txt +1 -0
  7. cableprobe-0.3.6/LICENSE +21 -0
  8. cableprobe-0.3.6/PKG-INFO +371 -0
  9. cableprobe-0.3.6/README.md +339 -0
  10. cableprobe-0.3.6/cableprobe/__init__.py +22 -0
  11. cableprobe-0.3.6/cableprobe/advice.py +208 -0
  12. cableprobe-0.3.6/cableprobe/analysis.py +240 -0
  13. cableprobe-0.3.6/cableprobe/cli.py +467 -0
  14. cableprobe-0.3.6/cableprobe/config.py +126 -0
  15. cableprobe-0.3.6/cableprobe/data/__init__.py +4 -0
  16. cableprobe-0.3.6/cableprobe/data/default_rules.yaml +564 -0
  17. cableprobe-0.3.6/cableprobe/logging_config.py +48 -0
  18. cableprobe-0.3.6/cableprobe/models.py +187 -0
  19. cableprobe-0.3.6/cableprobe/probes/__init__.py +21 -0
  20. cableprobe-0.3.6/cableprobe/probes/base.py +138 -0
  21. cableprobe-0.3.6/cableprobe/probes/block.py +94 -0
  22. cableprobe-0.3.6/cableprobe/probes/input_devices.py +172 -0
  23. cableprobe-0.3.6/cableprobe/probes/kernel_log.py +141 -0
  24. cableprobe-0.3.6/cableprobe/probes/keystroke_cadence.py +237 -0
  25. cableprobe-0.3.6/cableprobe/probes/media_devices.py +230 -0
  26. cableprobe-0.3.6/cableprobe/probes/network.py +99 -0
  27. cableprobe-0.3.6/cableprobe/probes/network_state.py +298 -0
  28. cableprobe-0.3.6/cableprobe/probes/processes.py +103 -0
  29. cableprobe-0.3.6/cableprobe/probes/registry.py +69 -0
  30. cableprobe-0.3.6/cableprobe/probes/serial_devices.py +144 -0
  31. cableprobe-0.3.6/cableprobe/probes/system_state.py +254 -0
  32. cableprobe-0.3.6/cableprobe/probes/udev_monitor.py +238 -0
  33. cableprobe-0.3.6/cableprobe/probes/usb.py +163 -0
  34. cableprobe-0.3.6/cableprobe/probes/usb_sysfs.py +295 -0
  35. cableprobe-0.3.6/cableprobe/probes/usbc_pd.py +176 -0
  36. cableprobe-0.3.6/cableprobe/probes/wifi_scan.py +246 -0
  37. cableprobe-0.3.6/cableprobe/report.py +247 -0
  38. cableprobe-0.3.6/cableprobe/rules.py +201 -0
  39. cableprobe-0.3.6/cableprobe/sanitize.py +59 -0
  40. cableprobe-0.3.6/cableprobe/session.py +254 -0
  41. cableprobe-0.3.6/cableprobe/system_info.py +65 -0
  42. cableprobe-0.3.6/pyproject.toml +57 -0
  43. cableprobe-0.3.6/setup.cfg +4 -0
  44. cableprobe-0.3.6/tests/test_advice.py +88 -0
  45. cableprobe-0.3.6/tests/test_analysis.py +126 -0
  46. cableprobe-0.3.6/tests/test_cli.py +229 -0
  47. cableprobe-0.3.6/tests/test_config.py +78 -0
  48. cableprobe-0.3.6/tests/test_probes_new.py +892 -0
  49. cableprobe-0.3.6/tests/test_probes_parsing.py +133 -0
  50. cableprobe-0.3.6/tests/test_report.py +116 -0
  51. cableprobe-0.3.6/tests/test_rules.py +290 -0
  52. cableprobe-0.3.6/tests/test_sanitize.py +70 -0
  53. 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,2 @@
1
+ [console_scripts]
2
+ cableprobe = cableprobe.cli:app
@@ -0,0 +1,12 @@
1
+ typer>=0.12
2
+ pydantic>=2.6
3
+ psutil>=5.9
4
+ PyYAML>=6.0
5
+ rich>=13.0
6
+
7
+ [:sys_platform == "linux"]
8
+ pyudev>=0.24
9
+
10
+ [dev]
11
+ pytest>=8.0
12
+ pytest-asyncio>=0.23
@@ -0,0 +1 @@
1
+ cableprobe
@@ -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.