A modular CLI security toolkit in Python. Combines an offensive scan/automation module (eJPT-style) with a defensive SOC/hardening auditor behind a single, clean CLI.
Built and maintained by knklinux as part of his security learning journey — the same journey behind Aion Sincro, an open-source AI assistant for pentesting and red-team training. CyberGuard is the "hands-on" toolkit; Aion Sincro is the AI companion that helps you master it.
- Runs Nmap with service/version detection (
-sV -sC). - Saves an XML archive of every scan for later re-parsing.
- Programmatically extracts each
(host, port, protocol, service, version)tuple. - Feeds the service banner straight into searchsploit to surface known public exploits from your local Exploit-DB archive.
- Returns a structured
ScanReportplus a colourised summary.
- Read-only audit of
/proc/sys/...sysctl values against a CIS-style baseline. - Parses
sshd_configagainst an opinionated hardening baseline (PermitRootLogin,PasswordAuthentication,MaxAuthTries, …). - Produces a colourised stdout summary and an optional plain-text report.
- Exit codes are CI/CD-friendly:
0clean,1vulnerable,2partial error.
- Zero runtime dependencies — runs on a stock Python 3.9+ install (ideal for containers, jump hosts and air-gapped environments).
- Modular package layout (
offensive.py,defensive.py,utils.py), designed so additional modules (web, wireless, reporting, …) can be plugged in next to the existing two. argparse-based CLI with sub-commands (offensive,defensive).dataclass-based result objects — easy to consume from notebooks or web dashboards.- Defensive auditor never mutates system state.
├── cyberguard/
│ ├── __init__.py # Package metadata
│ ├── __main__.py # Allows `python -m cyberguard`
│ ├── cli.py # argparse CLI entry point
│ ├── config.py # Hardening baselines & defaults
│ ├── defensive.py # sysctl + sshd_config auditor
│ ├── offensive.py # nmap + searchsploit pipeline
│ └── utils.py # Colours, subprocess helpers, XML parsing
├── main.py # Convenience shim → `python main.py …`
├── requirements.txt # Intentionally empty (zero deps)
├── tests/
│ ├── __init__.py
│ └── test_smoke.py # unittest smoke tests (no root/nmap needed)
└── README.md # ← you are here
# 1. Clone
git clone https://github.com/knklinux/ciberguard.git
cd ciberguard
# 2. (Optional but recommended) create and activate a virtualenv
python3 -m venv .venv
source .venv/bin/activate
# 3. Install the external tools the modules call into
# - nmap : https://nmap.org/download.html
# - searchsploit: ships with exploit-db (`sudo apt install exploitdb`)Everything inside
requirements.txtis commentary; the project runs with only the Python standard library. Uncommentrich/coloramaif you want richer terminal output.
python main.py --help
python main.py offensive --help
python main.py defensive --help# Default scan: top 1024 ports, sV + sC nmap scripts, searchsploit feed.
python main.py offensive --target scanme.nmap.org
# Custom port list and output directory.
python main.py offensive -t 192.0.2.10 -p 22,80,443 -o ./scans
# Full-range TCP scan, no searchsploit feed.
python main.py offensive -t 10.0.0.5 -p 1-65535 --no-searchsploitThe command writes a timestamped XML file to the output directory, then prints a colourised table of discovered services and any matching exploit-DB entries.
# Audit the local host (sysctl + /etc/ssh/sshd_config).
python main.py defensive
# Custom sshd_config path and persist the full report.
python main.py defensive \
--sshd-config /etc/ssh/sshd_config \
--report ./cyberguard_defensive_report.txtSample output (truncated):
=================================================================
Defensive Audit Report
=================================================================
Compliant: 9 Vulnerable: 4 Error: 1 Total: 14
[sysctl]
SAFE [info] net.ipv4.ip_forward observed='0' expected='0'
VULNERABLE [medium] net.ipv4.icmp_echo_ignore_broadcasts observed='0' expected='1'
...
[sshd]
SAFE [info] PermitRootLogin observed='prohibit-password' expected='no/prohibit-password/without-password'
VULNERABLE [critical] PermitEmptyPasswords observed='yes' expected='no'
Exit codes (useful for CI/CD pipelines):
Precedence: error > vulnerable > clean - the auditor prefers to report "partially failed" over "looks clean" when it could not collect enough evidence.
| Code | Meaning |
|---|---|
| 0 | Fully compliant |
| 1 | At least one vulnerable setting |
| 2 | Read error / partial audit |
| 64 | Usage error (e.g. bad CLI flags) |
| 130 | Interrupted by the user |
| Code | Meaning |
|---|---|
| 0 | Scan completed, ≥ 1 open service found |
| 1 | Scan completed, no open services surfaced |
| 64 | Usage error (e.g. empty --ports) |
| 130 | Interrupted by the user |
The suite exercises every parser and orchestrator without needing nmap, searchsploit or root access:
python -m unittest tests.test_smoke -vCovered behavior includes:
parse_nmap_xml— open services + NSE script hits, closed/garbage ports dropped.parse_searchsploit_json— modern JSON shape, legacy table fallback, garbage handling.SearchsploitSearcher—--format jsoninvocation and legacy fallback.SSHAuditor— first-match-wins parsing,Matchblock truncation, unsafe-directive flags.run_offensive—enable_searchsploit=Falsenever invokes the searcher.run_defensive— clean host yields exit code 0.- CLI entry points —
--helpfor root and both sub-commands.
Add a new module by following the same shape as offensive.py /
defensive.py:
- Create
cyberguard/<module>.pyexporting arun_<module>()function (or class) returning a dataclass. - Register the new sub-parser in
cyberguard/cli.py:build_parser. - Add any constraints to
requirements.txt. - Document it in this README.
CyberGuard ships with powerful offensive-assistance primitives. You are solely responsible for ensuring you have explicit, written authorization before scanning any system that is not your own. The authors disclaim all liability for misuse. Aion Sincro enforces the same rule: practice only on your own lab or with permission.
If you embed CyberGuard as a library (not just the CLI), a few public symbols changed between releases:
cyberguard.utils.parse_nmap_xmlnow returnsTuple[List[NmapService], List[NmapScriptHit]](services + NSE script findings) instead ofList[NmapService]. Iterating over the return value directly will iterate the tuple. Unpack explicitly:services, scripts = parse_nmap_xml(path).cyberguard.offensive.ScanReportgainedscriptsandservice_exploitsfields; existing keyword arguments remain valid because both usedefault_factory.cyberguard.run_offensivegained anenable_searchsploitkwarg (Trueby default) - set toFalseto skip the searchsploit feed in CI runs.
The CLI surface is unchanged across releases.
Released under the MIT License. See LICENSE (add your own copy in
your fork) for details.