-
Notifications
You must be signed in to change notification settings - Fork 2
Output Reference
This guide provides comprehensive documentation for all output formats generated by the Linux Security Audit Project, including data structures, field definitions, and usage examples.
- Output Format Overview
- HTML Report
- CSV Format
- JSON Format
- XML Format
- Console Output
- Data Field Definitions
- Status Codes
- File Naming Conventions
The Linux Security Audit Project supports five output formats, each designed for specific use cases:
| Format | File Extension | Use Case | Interactive | Machine-Readable |
|---|---|---|---|---|
| HTML | .html |
Human review, reporting, management presentation | Yes | No |
| CSV | .csv |
Spreadsheet analysis, trending, bulk data manipulation | No | Yes |
| JSON | .json |
API integration, SIEM, automation, selective remediation | No | Yes |
| XML | .xml |
Enterprise tools, legacy systems, SIEM integration | No | Yes |
| Console | N/A | Quick checks, SSH sessions, terminal-only environments | No | Partial |
Choose HTML when:
- Conducting manual security reviews
- Presenting findings to management or auditors
- Interactive exploration of results is needed
- Exporting specific issues for targeted remediation
Choose CSV when:
- Performing trend analysis over time
- Creating custom reports in Excel/Sheets
- Generating graphs and visualizations
- Bulk data manipulation is required
Choose JSON when:
- Integrating with modern APIs
- Feeding data to SIEM or monitoring tools
- Implementing automated workflows
- Using selective remediation features
- Custom scripting and analysis
Choose XML when:
- Integrating with enterprise security tools
- Working with legacy systems requiring XML
- Compliance with XML-based standards
- Enterprise SIEM ingestion (Splunk, QRadar)
Choose Console when:
- Performing quick security checks
- Working in terminal-only environments
- No file storage is desired
- Real-time output monitoring is needed
The HTML report is a fully self-contained, interactive web page. For real-world console output examples from each module and an HTML report preview, see the Examples page. Completely rewritten in v2.0 and extended through v3.7 with 20+ features:
- Executive Dashboard (SVG donut chart, clickable segments)
- Compliance Overview (weighted, simple, severity-adjusted scores)
- Host Identification (hostname, IP addresses, OS)
- Compliance Matrix, Remediation Priority ranking
- Module Summary tiles (v3.7) - color-banded grid (green >=90%, yellow 70-90%, orange 50-70%, red <50%) showing per-module score, pass/fail/warn/info/error counts, top severity badge, and anchor link to module section
- Top Priority Findings (v3.7) - top 10 non-Pass results sorted by severity (Critical -> High -> Medium -> Low -> Informational) then status (Fail -> Warning -> Info), displayed above the per-module detail tables
- Column Resizing, In-Column Filtering, Column Visibility toggles
- Global Search (include/exclude), Multi-Format Export (CSV/Excel/JSON/XML/TXT)
- Row Selection, Dark/Light Theme, Print CSS, Table of Contents
- Garamond typography, full-width header, collapsible sections
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Linux Security Audit Report</title>
<style>/* Embedded CSS for styling */</style>
<script>/* Embedded JavaScript for interactivity */</script>
</head>
<body>
<!-- Report Header -->
<!-- Summary Statistics -->
<!-- Interactive Controls -->
<!-- Results Table -->
</body>
</html>Contains execution metadata and branding:
====================================================================================================
LINUX SECURITY AUDIT REPORT
====================================================================================================
Hostname: server01.example.com
Operating System: Linux 5.15.0-91-generic
Scan Date: 2025-01-07 14:30:22
Execution Time: 0:03:45
Modules Executed: CIS, CISA, CORE, ENISA, ISO27001, NIST, NSA, STIG
Script Version: 2.0
Visual dashboard with key metrics:
- Total Checks: Number of security checks performed
- Pass Count: Checks that passed successfully (Green)
- Fail Count: Critical security issues detected (Red)
- Warning Count: Best practice violations (Yellow)
- Info Count: Informational findings (Cyan)
- Error Count: Checks that could not be completed (Magenta)
Example:
Total Checks: 2,297
Passed: 892 (76%)
Failed: 156 (13%)
Warnings: 98 (8%)
Info: 28 (2%)
Errors: 0 (0%)
Filter by Status:
- Buttons to show/hide specific statuses (All, Pass, Fail, Warning, Info, Error)
- Click to toggle visibility of results with that status
Filter by Module:
- Dropdown or buttons to filter by security framework
- Shows results from specific modules (Core, CIS, NIST, etc.)
Search Function:
- Text input to search across all fields
- Real-time filtering as you type
- Searches: Module, Category, Status, Message, Details, Remediation
Theme Toggle:
- Switch between light and dark themes
- Preference saved to browser localStorage
Export Functions:
- Export All to JSON: Download complete audit results
- Export Selected to JSON: Download only checked items (for selective remediation)
A grid of compact tiles, one per module, that gives an at-a-glance health view without scanning the detail tables. Tiles are color-banded:
| Health Band | Score Range | Border Color |
|---|---|---|
| Green | >= 90% pass | #2e7d32 |
| Yellow | 70 - 90% | #fbc02d |
| Orange | 50 - 70% | #ef6c00 |
| Red | < 50% | #c62828 |
Each tile shows:
- Module name and top severity badge (Critical / High / Medium / Low / Informational)
- Compliance score as a large percentage
- Pass / Fail / Warn / Info / Error counts in colored monospace
- Total checks in the module
- Anchor link to the corresponding per-module section in the report
Tile clicks scroll directly to the module's detail table. Layout uses CSS grid with a minmax(200px, 1fr) template, so tiles reflow responsively.
The top 10 non-Pass findings, sorted by:
- Severity rank - Critical > High > Medium > Low > Informational
- Status priority - Fail > Warning > Info
- Module name (stable order for ties)
Each row shows the severity badge, status badge, module, category, and a truncated message (<=140 chars). Color-coded badges match the donut-chart palette so visual scanning is consistent across the report.
If the audit produced no non-Pass results (rare on real systems), the section displays a friendly "all checks succeeded" placeholder instead of an empty table.
Sortable, filterable table with the following columns:
| Column | Description | Sortable | Searchable |
|---|---|---|---|
| Checkbox | Select for export | No | No |
| Module | Security framework name | Yes | Yes |
| Category | Specific security area | Yes | Yes |
| Status | Check result (Pass/Fail/Warning/Info/Error) | Yes | Yes |
| Message | Brief description of finding | Yes | Yes |
| Details | Detailed explanation | No | Yes |
| Remediation | Commands to fix the issue | No | Yes |
| Timestamp | When check was performed | Yes | No |
Column Sorting:
- Click column header to sort ascending
- Click again to sort descending
- Visual indicators show sort direction
// Filter buttons control row visibility
<button onclick="filterStatus('Fail')">Show Failed Only</button>
// Results are hidden/shown via CSS classes
<tr class="status-fail" style="display: table-row;">...</tr>// Real-time search across all text content
function searchTable() {
var input = document.getElementById("searchInput");
var filter = input.value.toLowerCase();
var rows = document.querySelectorAll("#resultsTable tbody tr");
rows.forEach(function(row) {
var text = row.textContent.toLowerCase();
row.style.display = text.includes(filter) ? "" : "none";
});
}// Export checked rows to JSON for selective remediation
function exportSelected() {
var selected = [];
document.querySelectorAll('input[type="checkbox"]:checked').forEach(function(checkbox) {
var row = checkbox.closest('tr');
selected.push({
module: row.cells[1].textContent,
category: row.cells[2].textContent,
status: row.cells[3].textContent,
message: row.cells[4].textContent,
details: row.cells[5].textContent,
remediation: row.cells[6].textContent,
timestamp: row.cells[7].textContent
});
});
var json = JSON.stringify({
executionInfo: {...},
results: selected
}, null, 2);
downloadJSON(json, 'Selected-Report-' + timestamp + '.json');
}Light Theme:
- Background: White (#FFFFFF)
- Text: Dark gray (#333333)
- Pass: Green (#28a745)
- Fail: Red (#dc3545)
- Warning: Orange (#ffc107)
- Info: Blue (#17a2b8)
- Error: Magenta (#6f42c1)
Dark Theme:
- Background: Dark gray (#1e1e1e)
- Text: Light gray (#e0e0e0)
- Pass: Light green (#4caf50)
- Fail: Light red (#f44336)
- Warning: Light orange (#ff9800)
- Info: Light blue (#03a9f4)
- Error: Light magenta (#9c27b0)
The HTML report adapts to different screen sizes:
- Desktop: Full table with all columns visible
- Tablet: Condensed view with scrolling
- Mobile: Stacked cards view (if implemented)
Supported Browsers:
- Chrome/Chromium 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Required Features:
- JavaScript enabled
- localStorage (for theme preference)
- CSS3 support
- HTML5 support
File: Security-Audit-Report-20250107-143022.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linux Security Audit Report - server01 - 2025-01-07</title>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 20px; }
.header { text-align: center; margin-bottom: 30px; }
.stats { display: flex; justify-content: space-around; margin: 20px 0; }
.stat-box { padding: 20px; border-radius: 5px; text-align: center; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
.status-pass { color: #28a745; font-weight: bold; }
.status-fail { color: #dc3545; font-weight: bold; }
/* ... more styles ... */
</style>
</head>
<body>
<div class="header">
<h1>Linux Security Audit Report</h1>
<p>Hostname: server01.example.com | Date: 2025-01-07 14:30:22</p>
</div>
<div class="stats">
<div class="stat-box">Total: 2,297</div>
<div class="stat-box" style="background-color: #d4edda;">Pass: 892</div>
<div class="stat-box" style="background-color: #f8d7da;">Fail: 156</div>
<!-- ... more stats ... -->
</div>
<div class="controls">
<button onclick="filterStatus('all')">Show All</button>
<button onclick="filterStatus('Fail')">Failed Only</button>
<input type="text" id="searchInput" onkeyup="searchTable()" placeholder="Search...">
<button onclick="toggleTheme()">Toggle Theme</button>
<button onclick="exportSelected()">Export Selected</button>
</div>
<table id="resultsTable">
<thead>
<tr>
<th><input type="checkbox" onclick="selectAll(this)"></th>
<th onclick="sortTable(1)">Module v</th>
<th onclick="sortTable(2)">Category v</th>
<th onclick="sortTable(3)">Status v</th>
<th onclick="sortTable(4)">Message v</th>
<th>Details</th>
<th>Remediation</th>
<th onclick="sortTable(7)">Timestamp v</th>
</tr>
</thead>
<tbody>
<tr class="status-fail">
<td><input type="checkbox"></td>
<td>Core</td>
<td>SSH Security</td>
<td class="status-fail">Fail</td>
<td>Root login is enabled</td>
<td>SSH configuration allows direct root login which is a security risk</td>
<td><code>sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config && systemctl restart sshd</code></td>
<td>2025-01-07 14:30:25</td>
</tr>
<!-- ... more rows ... -->
</tbody>
</table>
<script>
function filterStatus(status) { /* ... */ }
function searchTable() { /* ... */ }
function sortTable(column) { /* ... */ }
function toggleTheme() { /* ... */ }
function exportSelected() { /* ... */ }
function selectAll(checkbox) { /* ... */ }
</script>
</body>
</html>With --split-reports, in addition to the combined report the tool writes one report per framework to reports/by-framework/, named <FRAMEWORK>-Audit-<host>-<timestamp>.<ext>. Each split report is a complete, standalone report for that single framework - same structure as the combined report (executive dashboard, module summary tile, compliance score, priority findings, detailed results) but scoped to one framework's findings only.
Use --split-only to skip the combined report and produce just the per-framework set. Splitting applies to whichever --output-format is selected (HTML, CSV, JSON, XML). If only one framework is selected, no split occurs because the combined report already represents that single framework.
This is intended for distribution to different audiences: each framework owner receives a digestible report containing only their relevant data, rather than a single large multi-framework document.
With --attack-surface, the tool writes a dedicated assessment report to reports/Attack-Surface-<host>-<timestamp>.html (and a companion .json). Unlike the compliance reports, this report is organized by exposure rather than by framework or control.
Structure:
- Overall exposure dial - a 0-100 severity-weighted score with a Minimal/Low/Moderate/Elevated/High rating
- Host summary - distribution, firewall, external listener count, MAC framework, auditd state, FIM tool, container runtime (from the host-facts registry)
- Top Exposure Findings - the highest-contributing non-passing findings across all domains, with severity, status, module, and the domain(s) each maps to
- Exposure by Domain - ten domain cards (Network, Authentication, Privilege, Filesystem, Service, Kernel, Container, Credentials, Cryptography, Detection), each with its own exposure score, rating, finding counts, and top contributing findings
The JSON companion contains the full structured assessment (overall_score, overall_rating, domains[] with per-domain scores and findings, and highlights[]) for SIEM ingestion or dashboarding.
The assessment is derived from the same findings shown in the compliance reports - it does not run duplicate checks. It reads each finding's category, message, and severity to map it onto the relevant exposure domain(s) and weights non-passing findings by severity. It is an assessment aid, not a compliance score.
Comma-separated values format suitable for spreadsheet applications and data analysis tools.
Module,Category,Status,Message,Details,Remediation,Timestamp
Core,SSH Security,Fail,Root login is enabled,SSH configuration allows direct root login,"sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config && systemctl restart sshd",2025-01-07 14:30:25
Core,Password Policy,Pass,Password aging is configured,/etc/login.defs contains proper aging settings,,2025-01-07 14:30:26
CIS,Filesystem Configuration,Warning,Separate /tmp partition not found,Consider creating separate partition for /tmp,Create and mount /tmp as separate partition,2025-01-07 14:30:30| Column | Type | Description | Example |
|---|---|---|---|
| Module | String | Security framework name |
Core, CIS, NIST
|
| Category | String | Specific security area |
SSH Security, Password Policy
|
| Status | String | Result status |
Pass, Fail, Warning, Info, Error
|
| Message | String | Brief finding description | Root login is enabled |
| Details | String | Detailed explanation | SSH configuration allows direct root login |
| Remediation | String | Fix command(s) | sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config |
| Timestamp | DateTime | Check execution time | 2025-01-07 14:30:25 |
Handling:
- Commas in data are enclosed in quotes
- Quotes in data are escaped with double quotes
- Newlines in data are preserved within quoted fields
Example:
Module,Message,Details
Core,"SSH, Firewall, Password","Configuration issues found: 1) SSH root login, 2) Firewall disabled"The CSV format is fully compatible with:
- Microsoft Excel 2013+
- Google Sheets
- LibreOffice Calc
- Apple Numbers
Opening in Excel:
- File -> Open -> Select CSV file
- Excel automatically detects delimiters
- All columns import correctly
=COUNTIF(C:C,"Fail") // Count failed checks
=COUNTIF(C:C,"Pass") // Count passed checks
=COUNTIF(C:C,"Pass")/COUNTA(C:C)*100 // Percentage of passed checks
Create pivot table with:
- Rows: Module
- Columns: Status
- Values: Count of Status
Result:
Pass Fail Warning Info
Core 120 15 8 3
CIS 156 42 12 5
NIST 180 35 18 7
File: security-audit-20250107.csv
Module,Category,Status,Message,Details,Remediation,Timestamp
Core,OS Detection,Pass,Operating System identified,Ubuntu 24.04 LTS (Noble Numbat) detected,,2025-01-07 14:30:22
Core,SSH Security,Fail,Root login is enabled,SSH configuration allows direct root login,"sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config && systemctl restart sshd",2025-01-07 14:30:25
Core,Firewall Status,Fail,UFW is not enabled,Firewall (UFW) is inactive,sudo ufw enable && sudo ufw default deny incoming && sudo ufw default allow outgoing,2025-01-07 14:30:26
Core,Password Policy,Pass,Password aging is configured,Password aging settings are properly configured in /etc/login.defs,,2025-01-07 14:30:27
CIS,Filesystem Configuration,Warning,Separate /tmp partition not found,/tmp is not on a separate partition,Create and mount /tmp as a separate partition with nodev noexec nosuid options,2025-01-07 14:30:30JavaScript Object Notation - structured data format ideal for APIs, automation, and modern tools.
{
"executionInfo": {
"hostname": "string",
"os_version": "string",
"ip_addresses": ["string"],
"scan_date": "string",
"duration": "string",
"modules_run": ["string"],
"total_checks": integer,
"pass_count": integer,
"fail_count": integer,
"warning_count": integer,
"info_count": integer,
"error_count": integer,
"compliance_scores": {
"overall": { "simple_pct": number, "weighted_pct": number, "severity_weighted_pct": number, "threshold": number, "threshold_result": "string" },
"modules": { "<ModuleName>": { "simple_pct": number, "weighted_pct": number, "severity_weighted_pct": number, "total_checks": integer } }
}
},
"results": [
{
"module": "string",
"category": "string",
"status": "string",
"message": "string",
"details": "string",
"remediation": "string",
"severity": "string",
"cross_references": { "<framework>": "<control-id>" },
"timestamp": "string"
}
]
}The top-level key is
executionInfo(camelCase). Each result carries all nineAuditResultfields, includingseverityandcross_references.
File: security-audit-20250107.json
{
"executionInfo": {
"hostname": "server01.example.com",
"os_version": "Linux 5.15.0-91-generic",
"scan_date": "2025-01-07 14:30:22",
"duration": "0:03:45",
"modules_run": [
"CIS",
"CISA",
"CORE",
"ENISA",
"ISO27001",
"NIST",
"NSA",
"STIG"
],
"total_checks": 1174,
"pass_count": 892,
"fail_count": 156,
"warning_count": 98,
"info_count": 28,
"error_count": 0
},
"results": [
{
"module": "Core",
"category": "OS Detection",
"status": "Pass",
"message": "Operating System identified",
"details": "Ubuntu 24.04 LTS (Noble Numbat) detected - Debian family",
"remediation": "",
"severity": "Medium",
"cross_references": {},
"timestamp": "2025-01-07 14:30:22"
},
{
"module": "Core",
"category": "SSH Security",
"status": "Fail",
"message": "Root login is enabled",
"details": "SSH configuration allows direct root login which is a security risk. Found: PermitRootLogin yes",
"remediation": "Disable direct root login over SSH. Set in /etc/ssh/sshd_config (or a drop-in under /etc/ssh/sshd_config.d/): PermitRootLogin no. Apply with: systemctl reload sshd",
"severity": "High",
"cross_references": { "CIS": "5.2.7", "STIG": "V-230296", "NIST": "AC-6" },
"timestamp": "2025-01-07 14:30:25"
},
{
"module": "Core",
"category": "Firewall Status",
"status": "Fail",
"message": "UFW is not enabled",
"details": "Firewall (UFW) is inactive. System is vulnerable to network attacks.",
"remediation": "sudo ufw enable && sudo ufw default deny incoming && sudo ufw default allow outgoing",
"timestamp": "2025-01-07 14:30:26"
},
{
"module": "CIS",
"category": "Filesystem Configuration",
"status": "Warning",
"message": "Separate /tmp partition not found",
"details": "/tmp is not on a separate partition. CIS recommends separate partitions for better security isolation.",
"remediation": "Create and mount /tmp as a separate partition with nodev,noexec,nosuid options",
"timestamp": "2025-01-07 14:30:30"
}
]
}| Field | Type | Nullable | Description |
|---|---|---|---|
| executionInfo | Object | No | Metadata about the audit execution |
| executionInfo.hostname | String | No | System hostname |
| executionInfo.os_version | String | No | Operating system and kernel version |
| executionInfo.scan_date | String | No | ISO 8601 datetime |
| executionInfo.duration | String | No | Execution time (HH:MM:SS) |
| executionInfo.modules_run | Array[String] | No | List of executed modules |
| executionInfo.total_checks | Integer | No | Total number of checks performed |
| executionInfo.*_count | Integer | No | Count by status type |
| results | Array[Object] | No | Array of check results |
| results[].module | String | No | Security framework name |
| results[].category | String | No | Security area |
| results[].status | String | No | Pass/Fail/Warning/Info/Error |
| results[].message | String | No | Brief description |
| results[].details | String | Yes | Detailed explanation (can be empty) |
| results[].remediation | String | Yes | Fix command/guidance (can be empty for Pass) |
| results[].severity | String | No | Critical/High/Medium/Low/Informational |
| results[].cross_references | Object | Yes | Map of framework -> control ID (can be empty) |
| results[].timestamp | String | No | ISO 8601 datetime |
import json
# Load JSON file
with open('security-audit-20250107.json', 'r') as f:
audit_data = json.load(f)
# Get summary statistics
print(f"Total Checks: {audit_data['executionInfo']['total_checks']}")
print(f"Failed: {audit_data['executionInfo']['fail_count']}")
# Filter failed checks
failed_checks = [r for r in audit_data['results'] if r['status'] == 'Fail']
# Group by module
from collections import defaultdict
by_module = defaultdict(list)
for result in failed_checks:
by_module[result['module']].append(result)
# Print failed checks by module
for module, checks in by_module.items():
print(f"\n{module}: {len(checks)} failures")
for check in checks:
print(f" - {check['category']}: {check['message']}")# Count failed checks
jq '.executionInfo.fail_count' security-audit-20250107.json
# List all failed check messages
jq '.results[] | select(.status=="Fail") | .message' security-audit-20250107.json
# Get remediation commands for failed checks
jq '.results[] | select(.status=="Fail") | .remediation' security-audit-20250107.json
# Count issues by module
jq '.results | group_by(.module) | map({module: .[0].module, count: length})' security-audit-20250107.json
# Export only Core module failures
jq '{executionInfo, results: [.results[] | select(.module=="Core" and .status=="Fail")]}' security-audit-20250107.json// Fetch audit data
fetch('https://api.example.com/audit/latest')
.then(response => response.json())
.then(data => {
// Display summary
console.log(`Total: ${data.executionInfo.total_checks}`);
console.log(`Failed: ${data.executionInfo.fail_count}`);
// Filter critical issues
const critical = data.results.filter(r => r.status === 'Fail');
// Send alerts
critical.forEach(issue => {
sendAlert({
severity: 'high',
title: `${issue.module} - ${issue.category}`,
message: issue.message,
remediation: issue.remediation
});
});
});When exporting selected issues from HTML report, the JSON structure is identical but contains only the selected results:
{
"executionInfo": {
"hostname": "server01.example.com",
"scan_date": "2025-01-07 14:30:22"
},
"results": [
{
"module": "Core",
"category": "SSH Security",
"status": "Fail",
"message": "Root login is enabled",
"details": "SSH configuration allows direct root login",
"remediation": "Disable direct root login over SSH. Set in /etc/ssh/sshd_config (or a drop-in under /etc/ssh/sshd_config.d/): PermitRootLogin no. Apply with: systemctl reload sshd",
"severity": "High",
"cross_references": { "CIS": "5.2.7", "STIG": "V-230296", "NIST": "AC-6" },
"timestamp": "2025-01-07 14:30:25"
}
]
}This format is used with:
sudo python3 linux_security_audit.py --auto-remediate --remediation-file Selected-Report-20250107-143022.jsonExtensible Markup Language format for enterprise tools, legacy systems, and SIEM integration.
<?xml version="1.0" encoding="utf-8"?>
<security_audit>
<metadata>
<export_date>string (ISO 8601)</export_date>
<hostname>string</hostname>
<ip_addresses>string</ip_addresses>
<operating_system>string</operating_system>
<scan_date>string</scan_date>
<duration>string</duration>
<total_checks>integer</total_checks>
<pass_count>integer</pass_count>
<fail_count>integer</fail_count>
<warning_count>integer</warning_count>
<info_count>integer</info_count>
<error_count>integer</error_count>
</metadata>
<events>
<event>
<timestamp>string</timestamp>
<module>string</module>
<status>string</status>
<severity>string</severity>
<category>string</category>
<message>string</message>
<details>string</details>
<remediation>string</remediation>
</event>
</events>
</security_audit>The XML root is
<security_audit>with a<metadata>block and an<events>list of<event>elements. Note that XML uses<metadata>/<operating_system>(notexecution_info/os_version) and groups findings under<events>/<event>.
File: security-audit-20250107.xml
<?xml version="1.0" encoding="utf-8"?>
<security_audit>
<metadata>
<export_date>2026-06-13T14:30:22.123456</export_date>
<hostname>server01.example.com</hostname>
<ip_addresses>10.0.2.15</ip_addresses>
<operating_system>Ubuntu 24.04.4 LTS</operating_system>
<scan_date>2026-06-13 14:30:22</scan_date>
<duration>0:03:45</duration>
<total_checks>2297</total_checks>
<pass_count>1290</pass_count>
<fail_count>430</fail_count>
<warning_count>320</warning_count>
<info_count>257</info_count>
<error_count>0</error_count>
</metadata>
<events>
<event>
<timestamp>2026-06-13 14:30:22</timestamp>
<module>CORE</module>
<status>Pass</status>
<severity>Medium</severity>
<category>CORE - OS Detection</category>
<message>CORE-OS-001: Operating system identified</message>
<details>ubuntu 24.04.4 LTS (Noble Numbat) (debian)</details>
<remediation>OS detection successful</remediation>
</event>
<event>
<timestamp>2026-06-13 14:30:25</timestamp>
<module>CORE</module>
<status>Fail</status>
<severity>High</severity>
<category>CORE - SSH</category>
<message>Root login is enabled</message>
<details>SSH configuration allows direct root login. Found: PermitRootLogin yes</details>
<remediation>Disable direct root login over SSH. In /etc/ssh/sshd_config (or a drop-in): PermitRootLogin no. Apply with: systemctl reload sshd</remediation>
</event>
<event>
<timestamp>2026-06-13 14:30:30</timestamp>
<module>CIS</module>
<status>Warning</status>
<severity>Medium</severity>
<category>CIS 1.1 - Filesystem</category>
<message>1.1.2 Separate /tmp partition not found</message>
<details>/tmp is not on a separate partition. CIS recommends a separate partition for isolation.</details>
<remediation>Create and mount /tmp as a separate partition with nodev,nosuid,noexec options</remediation>
</event>
</events>
</security_audit>XML entities are automatically escaped:
-
&->& -
<->< -
>->> -
"->" -
'->'
import xml.etree.ElementTree as ET
# Parse XML file
tree = ET.parse('security-audit-20250107.xml')
root = tree.getroot()
# Get metadata
meta = root.find('metadata')
print(f"Hostname: {meta.find('hostname').text}")
print(f"Total Checks: {meta.find('total_checks').text}")
print(f"Failed: {meta.find('fail_count').text}")
# Iterate through events
for result in root.find('events'):
status = result.find('status').text
if status == 'Fail':
module = result.find('module').text
message = result.find('message').text
print(f"{module}: {message}")<!-- Count failed checks -->
count(//event[status='Fail'])
<!-- Get all SSH-related issues -->
//event[contains(category, 'SSH')]
<!-- Get remediation commands for failed checks -->
//r[status='Fail']/remediation/text()
<!-- Count issues by module -->
//r/module[not(.=preceding::module)]/text()
Upload XML to Splunk using HTTP Event Collector:
curl -X POST https://splunk.example.com:8088/services/collector \
-H "Authorization: Splunk YOUR-TOKEN" \
-d @security-audit-20250107.xmlConfigure QRadar to ingest XML files from network share:
# Copy XML to QRadar intake directory
scp security-audit-20250107.xml admin@qradar:/store/intake/Real-time terminal output with ANSI color coding for immediate visual feedback.
====================================================================================================
Linux Security Audit Script v1.1
====================================================================================================
[*] Checking prerequisites...
[+] Running as: ROOT (Full Access)
[+] Python version: 3.10.12
[+] All prerequisites met
[*] Discovering security modules...
[+] Found 16 modules: ACSC, CIS, CISA, CMMC, CORE, DISTBASELINE, EDR, ENISA, GDPR, HIPAA, ISO27001, NIST, NSA, PCI, SOC2, STIG
[*] Modules to execute: ACSC, CIS, CISA, CMMC, CORE, DISTBASELINE, EDR, ENISA, GDPR, HIPAA, ISO27001, NIST, NSA, PCI, SOC2, STIG
[*] Executing module: CORE
[PASS] Core - OS Detection: Operating System identified
[FAIL] Core - SSH Security: Root login is enabled
[FAIL] Core - Firewall Status: UFW is not enabled
[PASS] Core - Password Policy: Password aging is configured
[WARNING] Core - System Updates: Security updates available
...
[+] Module CORE completed: 182 checks
====================================================================================================
AUDIT SUMMARY
====================================================================================================
Execution Mode: ROOT (Full Access)
Total Checks: 1174
Passed: 892
Failed: 156
Warnings: 98
Info: 28
Errors: 0
Duration: 0:03:45
====================================================================================================
[+] Audit completed successfully!
[*] GitHub: https://github.com/Sandler73/Linux-Security-Audit-Project.git
| Status | Color | ANSI Code | Visual Indicator |
|---|---|---|---|
| Pass | Green | \033[92m |
or [PASS] |
| Fail | Red | \033[91m |
or [FAIL] |
| Warning | Yellow | \033[93m |
or [WARNING] |
| Info | Cyan | \033[96m |
i or [INFO] |
| Error | Magenta | \033[95m |
! or [ERROR] |
| Header | Cyan | \033[96m |
[*] |
| Success | Green | \033[92m |
[+] |
| Notice | Yellow | \033[93m |
[!] |
====================================================================================================
Linux Security Audit Script v1.1
====================================================================================================
[*] Checking prerequisites...
[+] Running as: ROOT (Full Access)
[+] Python version: 3.10.12
[+] All prerequisites met
[*] Discovering security modules...
[+] Found 16 modules: ACSC, CIS, CISA, CMMC, CORE, DISTBASELINE, EDR, ENISA, GDPR, HIPAA, ISO27001, NIST, NSA, PCI, SOC2, STIG
[*] Executing module: CORE
[PASS] Core - OS Detection: Operating System identified
[FAIL] Core - SSH Security: Root login is enabled
...
[+] Module CORE completed: 182 checks
====================================================================================================
AUDIT SUMMARY
====================================================================================================
Execution Mode: ROOT (Full Access)
Total Checks: 1174
Passed: 892
Failed: 156
Warnings: 98
Info: 28
Errors: 0
Duration: 0:03:45
====================================================================================================
# Redirect all output
sudo python3 linux_security_audit.py -f Console > audit-$(date +%Y%m%d).txt 2>&1
# Redirect only stdout
sudo python3 linux_security_audit.py -f Console > audit-$(date +%Y%m%d).txt
# View while saving (tee)
sudo python3 linux_security_audit.py -f Console | tee audit-$(date +%Y%m%d).txt# Using sed
sudo python3 linux_security_audit.py -f Console | sed 's/\x1B\[[0-9;]*[JKmsu]//g' > audit-clean.txt
# Using ansi2txt (if available)
sudo python3 linux_security_audit.py -f Console | ansi2txt > audit-clean.txtFull Color Support:
- Linux terminal emulators (GNOME Terminal, Konsole, xterm)
- macOS Terminal.app
- iTerm2
- Windows Terminal
- WSL terminals
Limited/No Color Support:
- Old terminal emulators
- Serial consoles
- Some SSH clients with color disabled
Type: String
Values: Core, CIS, CISA, ENISA, ISO27001, NIST, NSA, STIG
Description: Security framework or standard being evaluated
Examples:
-
Core- Core security baseline assessment -
CIS- Center for Internet Security Benchmarks -
NIST- NIST 800-53, CSF 2.0, 800-171 controls
Type: String Description: Specific security area or control family within the module
Examples:
-
SSH Security- SSH daemon configuration -
Password Policy- Password requirements and aging -
Filesystem Configuration- Filesystem mount options and partitioning -
Network Configuration- Network stack and firewall settings -
Audit Configuration- System auditing and logging
Type: String (Enum)
Values: Pass, Fail, Warning, Info, Error
Description: Result of the security check
See Status Codes section for detailed definitions.
Type: String Description: Brief, human-readable description of the finding (typically 1 sentence)
Examples:
Root login is enabledPassword aging is configuredUFW is not enabledSeparate /tmp partition not found
Type: String (Optional) Description: Detailed explanation of the finding, including context and impact
Examples:
SSH configuration allows direct root login which is a security risk. Found: PermitRootLogin yes in /etc/ssh/sshd_configPassword aging settings are properly configured in /etc/login.defs: PASS_MAX_DAYS=90, PASS_MIN_DAYS=7, PASS_WARN_AGE=14Firewall (UFW) is inactive. System is vulnerable to network attacks. No iptables rules configured.
Type: String (Optional) Description: Command(s) to fix the issue (empty for Pass status)
Format: Shell command(s), typically using && for command chaining
Examples:
sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config && systemctl restart sshdsudo ufw enable && sudo ufw default deny incoming && sudo ufw default allow outgoingapt-get update && apt-get upgrade -y
Multi-line Commands: Complex remediations may include multiple steps separated by && or ;
Type: String (ISO 8601)
Format: YYYY-MM-DD HH:MM:SS
Description: Date and time when the check was performed
Examples:
2025-01-07 14:30:222025-01-07 14:30:25
Meaning: Security check passed successfully Color: Green Action Required: None
Interpretation: The system meets the security requirement for this check.
Examples:
- Password aging is properly configured
- SSH root login is disabled
- Firewall is enabled and configured
- System is up to date
Meaning: Critical security vulnerability or misconfiguration detected Color: Red Action Required: Immediate remediation recommended
Interpretation: The system has a security weakness that should be addressed.
Examples:
- SSH allows root login
- Firewall is disabled
- Weak password policy
- Critical security updates missing
Priority: High - Address as soon as possible
Meaning: Potential security concern or best practice violation Color: Yellow Action Required: Review and consider remediation
Interpretation: The system configuration could be improved for better security posture.
Examples:
- /tmp not on separate partition
- Unnecessary services running
- Logging verbosity could be increased
- Security-related packages not installed
Priority: Medium - Schedule remediation during maintenance window
Meaning: Informational finding about system configuration Color: Cyan Action Required: Awareness only
Interpretation: Configuration information that may be useful for security awareness.
Examples:
- System has 5 security updates available
- Specific kernel version detected
- Package versions for awareness
- Configuration details for documentation
Priority: Low - No immediate action needed
Meaning: Check could not be completed Color: Magenta Action Required: Investigate
Interpretation: The check failed to execute, possibly due to permissions, missing files, or system issues.
Examples:
- Permission denied reading configuration file
- Required command not found
- File does not exist
- Service is not installed
Priority: Varies - May indicate missing root privileges or system issues
Common Causes:
- Running without root/sudo (most common)
- Missing system packages
- Unusual system configuration
- File system issues
When no output path is specified, files are saved to reports/ with a companion JSON and log file in logs/:
reports/Security-Audit-Report-HOSTNAME-YYYYMMDD-HHMMSS.html
reports/Security-Audit-Report-HOSTNAME-YYYYMMDD-HHMMSS.json (companion)
logs/Security-Audit-HOSTNAME-YYYYMMDD-HHMMSS.log
The detailed naming pattern for report files:
Security-Audit-Report-YYYYMMDD-HHMMSS.html
Example: Security-Audit-Report-20250107-143022.html
Security-Audit-Report-YYYYMMDD-HHMMSS.csv
Example: Security-Audit-Report-20250107-143022.csv
Security-Audit-Report-YYYYMMDD-HHMMSS.json
Example: Security-Audit-Report-20250107-143022.json
Security-Audit-Report-YYYYMMDD-HHMMSS.xml
Example: Security-Audit-Report-20250107-143022.xml
When exporting selected issues from HTML report:
Selected-Report-YYYYMMDD-HHMMSS.json
Example: Selected-Report-20250107-143022.json
sudo python3 linux_security_audit.py -o $(hostname)-audit-$(date +%Y%m%d).htmlResult: server01-audit-20250107.html
sudo python3 linux_security_audit.py -m CIS,NIST -o cis-nist-audit-$(date +%Y%m%d).htmlResult: cis-nist-audit-20250107.html
sudo python3 linux_security_audit.py -m STIG -o fedramp-compliance-$(date +%Y%m).htmlResult: fedramp-compliance-202501.html
sudo python3 linux_security_audit.py -o audit-v1.0-baseline.htmlResult: audit-v1.0-baseline.html
All generated files are created with secure permissions:
-
Mode:
600(rw-------) - Owner: SUDO_USER (when run with sudo) or current user
- Group: User's primary group
This ensures only the user can read sensitive security information.
- Usage Guide: How to generate different output formats
- Module Documentation: Details on what each module checks
- Development Guide: Creating custom output processors
- Troubleshooting: Common output issues and solutions
Linux Security Audit Project - Version 3.9 - MIT License
Repository - Releases - Issues - Pull Requests
Changelog - Contributing - Security Policy - License
Frameworks: Core - CIS - CISA - ENISA - ISO 27001 - NIST - NSA - STIG - ACSC - CMMC - DistBaseline - EDR - GDPR - HIPAA - PCI-DSS - SOC2
Coverage: 16 Modules - 2,297 Automated Security Checks - 5 Native Output Formats - Zero External Dependencies
This documentation reflects Linux Security Audit Project v3.9 (cross-framework remediation consistency via the canonical remediation registry, PCI-DSS module rename, compliance-scoring fix, attack-surface assessment, per-framework split reports, cross-module correlation, 18 distribution profiles, rollup metrics, OS-aware remediation library). For older versions, see the release tags.
Version 3.9 - 16 modules - 2,297 checks
Original modules (v2.0 baseline + v3.3 expansion)
Core - CIS - CISA - ENISA - ISO 27001 - NIST - NSA - STIG
New modules (v3.0+ Phase 3)
ACSC - CMMC - DistBaseline - EDR - GDPR - HIPAA - PCI-DSS - SOC2
Output Formats
HTML - JSON - CSV - XML - Console
Status Values
Pass - Fail - Warning - Info - Error
Severity Levels
Critical - High - Medium - Low - Informational