Catalog 0.4 (70 computer checks: unique login, prohibited software, tamper protection on Mac/Linux), app 0.5.1
Browse files- README.md +2 -2
- app/package.json +1 -1
- baseline.conf +8 -0
- catalog/checks.json +56 -5
- collectors/linux/audit.sh +63 -2
- collectors/macos/audit.sh +53 -2
- collectors/windows/audit.ps1 +21 -2
- index.html +6 -6
- library/check_guidance.json +53 -2
- library/controls.json +473 -146
- library/fixes.json +194 -23
- site/site.js +1 -0
- synthetic/generate_evidence.py +50 -9
README.md
CHANGED
|
@@ -29,7 +29,7 @@ can be built before real customer data exists. The generated training data is in
|
|
| 29 |
|
| 30 |
| Section | Checks | Examples |
|
| 31 |
|---|---|---|
|
| 32 |
-
| `COMPLIANCE RESULTS` | Security baseline
|
| 33 |
| `GDPR TECHNICAL CONTROLS` | 12 | Automatic updates, supported OS, security logging, time sync, backup, removable media encryption, guest account, remote access, diagnostic data, personal data discovery (opt-in, later stage) |
|
| 34 |
| `EU AI ACT CONTROLS` | 5 | AI software inventory, unapproved AI tools (shadow AI), risk classification (by the model), Windows Recall / Apple Intelligence, AI log retention |
|
| 35 |
| `ORGANISATIONAL CONTROLS` | 8 | RoPA, DPIA, breach procedure, processor agreements, AI register, AI literacy, human oversight, AI transparency |
|
|
@@ -210,7 +210,7 @@ Devseis builds the bundle with `python3 vulndb/build_bundle.py` (needs internet;
|
|
| 210 |
|
| 211 |
| Part | Version | Notes |
|
| 212 |
|---|---|---|
|
| 213 |
-
| Catalog, library, synthetic data
|
| 214 |
| Collectors (Windows, Linux, macOS) | **0.2** (catalog 0.3) | macOS tested on a real Mac; Linux tested on Ubuntu 24.04 and Fedora 42 containers; Windows parse-checked only (needs a real Windows test). Known vulnerabilities: inventory only, matching comes with the offline vulnerability bundle |
|
| 215 |
| Vulnerability matcher and bundle | 0.1 | Tested: this Mac (Chrome 154 → 58 critical/high, fixed in 155), Ubuntu 24.04 (OpenSSL), Rocky 9 (25 of 25 packages agree with dnf's own security list), Fedora reported as not covered |
|
| 216 |
| Website | **2026-10-14** | Computers only: download, check list, report viewer; no AI in the browser |
|
|
|
|
| 29 |
|
| 30 |
| Section | Checks | Examples |
|
| 31 |
|---|---|---|
|
| 32 |
+
| `COMPLIANCE RESULTS` | Security baseline | Password and lockout policy, unique user login, antivirus and tamper protection, firewall, screen lock, USB storage, administrators, disk encryption, updates, vulnerabilities, prohibited software |
|
| 33 |
| `GDPR TECHNICAL CONTROLS` | 12 | Automatic updates, supported OS, security logging, time sync, backup, removable media encryption, guest account, remote access, diagnostic data, personal data discovery (opt-in, later stage) |
|
| 34 |
| `EU AI ACT CONTROLS` | 5 | AI software inventory, unapproved AI tools (shadow AI), risk classification (by the model), Windows Recall / Apple Intelligence, AI log retention |
|
| 35 |
| `ORGANISATIONAL CONTROLS` | 8 | RoPA, DPIA, breach procedure, processor agreements, AI register, AI literacy, human oversight, AI transparency |
|
|
|
|
| 210 |
|
| 211 |
| Part | Version | Notes |
|
| 212 |
|---|---|---|
|
| 213 |
+
| Catalog, library, synthetic data | **0.4** | 76 checks, 70 on computers (Windows 66, Linux 59, macOS 59). 0.4 adds unique user login, prohibited software (`PROHIBITED_SOFTWARE`), tamper protection on macOS (SIP) and Linux (SELinux/AppArmor) and names the encryption product. The fine-tuned models handle the new checks without retraining (v0.3 full precision and v0.6 4-bit: 24/24 findings). Training data is still 0.3 |
|
| 214 |
| Collectors (Windows, Linux, macOS) | **0.2** (catalog 0.3) | macOS tested on a real Mac; Linux tested on Ubuntu 24.04 and Fedora 42 containers; Windows parse-checked only (needs a real Windows test). Known vulnerabilities: inventory only, matching comes with the offline vulnerability bundle |
|
| 215 |
| Vulnerability matcher and bundle | 0.1 | Tested: this Mac (Chrome 154 → 58 critical/high, fixed in 155), Ubuntu 24.04 (OpenSSL), Rocky 9 (25 of 25 packages agree with dnf's own security list), Fedora reported as not covered |
|
| 216 |
| Website | **2026-10-14** | Computers only: download, check list, report viewer; no AI in the browser |
|
app/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"name": "devseis-endpoint-auditor",
|
| 3 |
"productName": "Arx",
|
| 4 |
-
"version": "0.5.
|
| 5 |
"description": "Read-only endpoint audit for ISO 27001, GDPR and the EU AI Act, with a local AI auditor.",
|
| 6 |
"author": {
|
| 7 |
"name": "Devseis",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "devseis-endpoint-auditor",
|
| 3 |
"productName": "Arx",
|
| 4 |
+
"version": "0.5.1",
|
| 5 |
"description": "Read-only endpoint audit for ISO 27001, GDPR and the EU AI Act, with a local AI auditor.",
|
| 6 |
"author": {
|
| 7 |
"name": "Devseis",
|
baseline.conf
CHANGED
|
@@ -40,11 +40,19 @@ APPROVED_ADMINS=itadmin
|
|
| 40 |
# Windows: a disabled built-in Administrator (RID 500) is not counted as unauthorized.
|
| 41 |
ALLOW_DISABLED_BUILTIN_ADMIN=1
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
# --- Vulnerabilities -------------------------------------------------------
|
| 44 |
MAX_PENDING_SECURITY_UPDATES=0
|
| 45 |
MAX_OUTDATED_APPS=0
|
| 46 |
# Critical or high vulnerabilities allowed in installed software (offline OSV/NVD data)
|
| 47 |
MAX_CRITICAL_HIGH_VULNERABILITIES=0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
# --- GDPR technical controls ----------------------------------------------
|
| 50 |
UPDATES_MAX_AGE_DAYS=30
|
|
|
|
| 40 |
# Windows: a disabled built-in Administrator (RID 500) is not counted as unauthorized.
|
| 41 |
ALLOW_DISABLED_BUILTIN_ADMIN=1
|
| 42 |
|
| 43 |
+
# --- Unique user login ------------------------------------------------------
|
| 44 |
+
# Account names that suggest a shared or generic login (exact match, any case). Each person should have their own account.
|
| 45 |
+
SHARED_ACCOUNT_NAMES=admin,administrator,user,users,shared,office,staff,reception,frontdesk,test,temp,demo,student,kiosk,public,helpdesk,owner
|
| 46 |
+
|
| 47 |
# --- Vulnerabilities -------------------------------------------------------
|
| 48 |
MAX_PENDING_SECURITY_UPDATES=0
|
| 49 |
MAX_OUTDATED_APPS=0
|
| 50 |
# Critical or high vulnerabilities allowed in installed software (offline OSV/NVD data)
|
| 51 |
MAX_CRITICAL_HIGH_VULNERABILITIES=0
|
| 52 |
+
# Software that must not be installed: part of an installed app or package name, any case. Default: torrent clients
|
| 53 |
+
# (any name containing "torrent": µTorrent, BitTorrent, qBittorrent…) and
|
| 54 |
+
# Windows/Office activation cracks. Add your own (e.g. games, unlicensed tools). Licences cannot be checked from the device.
|
| 55 |
+
PROHIBITED_SOFTWARE=Torrent,Transmission,Deluge,Vuze,FrostWire,KMSpico,KMSAuto,AutoKMS,Microsoft Toolkit
|
| 56 |
|
| 57 |
# --- GDPR technical controls ----------------------------------------------
|
| 58 |
UPDATES_MAX_AGE_DAYS=30
|
catalog/checks.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"catalog_version": "0.
|
| 3 |
"statuses": [
|
| 4 |
"Compliant",
|
| 5 |
"Non-Compliant",
|
|
@@ -59,7 +59,8 @@
|
|
| 59 |
"A.8.17": "Clock synchronization",
|
| 60 |
"A.8.19": "Installation of software on operational systems",
|
| 61 |
"A.8.20": "Networks security",
|
| 62 |
-
"A.8.24": "Use of cryptography"
|
|
|
|
| 63 |
},
|
| 64 |
"gdpr": {
|
| 65 |
"Art. 5(1)(c)": "Data minimisation",
|
|
@@ -375,10 +376,12 @@
|
|
| 375 |
"section": "baseline",
|
| 376 |
"name": "Tamper protection",
|
| 377 |
"os": [
|
| 378 |
-
"windows"
|
|
|
|
|
|
|
| 379 |
],
|
| 380 |
"baseline_keys": [],
|
| 381 |
-
"rule": "Defender tamper protection
|
| 382 |
"controls": {
|
| 383 |
"iso27001": [
|
| 384 |
"A.8.7"
|
|
@@ -1047,7 +1050,7 @@
|
|
| 1047 |
"android"
|
| 1048 |
],
|
| 1049 |
"baseline_keys": [],
|
| 1050 |
-
"rule": "The system disk is fully encrypted (BitLocker / LUKS / FileVault). Phones: iOS data protection is on when a passcode is set; Android 10+ encrypts by default.",
|
| 1051 |
"controls": {
|
| 1052 |
"iso27001": [
|
| 1053 |
"A.8.24",
|
|
@@ -1137,6 +1140,30 @@
|
|
| 1137 |
"ai_act": []
|
| 1138 |
}
|
| 1139 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1140 |
{
|
| 1141 |
"id": "vuln.pending_updates",
|
| 1142 |
"section": "baseline",
|
|
@@ -1198,6 +1225,30 @@
|
|
| 1198 |
"android": "App updates"
|
| 1199 |
}
|
| 1200 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1201 |
{
|
| 1202 |
"id": "vuln.known_vulnerabilities",
|
| 1203 |
"section": "baseline",
|
|
|
|
| 1 |
{
|
| 2 |
+
"catalog_version": "0.4.0",
|
| 3 |
"statuses": [
|
| 4 |
"Compliant",
|
| 5 |
"Non-Compliant",
|
|
|
|
| 59 |
"A.8.17": "Clock synchronization",
|
| 60 |
"A.8.19": "Installation of software on operational systems",
|
| 61 |
"A.8.20": "Networks security",
|
| 62 |
+
"A.8.24": "Use of cryptography",
|
| 63 |
+
"A.5.32": "Intellectual property rights"
|
| 64 |
},
|
| 65 |
"gdpr": {
|
| 66 |
"Art. 5(1)(c)": "Data minimisation",
|
|
|
|
| 376 |
"section": "baseline",
|
| 377 |
"name": "Tamper protection",
|
| 378 |
"os": [
|
| 379 |
+
"windows",
|
| 380 |
+
"linux",
|
| 381 |
+
"macos"
|
| 382 |
],
|
| 383 |
"baseline_keys": [],
|
| 384 |
+
"rule": "Protection cannot be switched off by malware: Defender tamper protection (Windows), System Integrity Protection (macOS), an enforcing SELinux or AppArmor (Linux).",
|
| 385 |
"controls": {
|
| 386 |
"iso27001": [
|
| 387 |
"A.8.7"
|
|
|
|
| 1050 |
"android"
|
| 1051 |
],
|
| 1052 |
"baseline_keys": [],
|
| 1053 |
+
"rule": "The system disk is fully encrypted (BitLocker / LUKS / FileVault); the finding names the encryption product. Phones: iOS data protection is on when a passcode is set; Android 10+ encrypts by default.",
|
| 1054 |
"controls": {
|
| 1055 |
"iso27001": [
|
| 1056 |
"A.8.24",
|
|
|
|
| 1140 |
"ai_act": []
|
| 1141 |
}
|
| 1142 |
},
|
| 1143 |
+
{
|
| 1144 |
+
"id": "account.unique_login",
|
| 1145 |
+
"section": "baseline",
|
| 1146 |
+
"name": "Unique user login",
|
| 1147 |
+
"os": [
|
| 1148 |
+
"windows",
|
| 1149 |
+
"linux",
|
| 1150 |
+
"macos"
|
| 1151 |
+
],
|
| 1152 |
+
"baseline_keys": [
|
| 1153 |
+
"SHARED_ACCOUNT_NAMES"
|
| 1154 |
+
],
|
| 1155 |
+
"rule": "No automatic login, and no enabled account with a shared or generic name from SHARED_ACCOUNT_NAMES: each person signs in with their own account.",
|
| 1156 |
+
"controls": {
|
| 1157 |
+
"iso27001": [
|
| 1158 |
+
"A.5.16",
|
| 1159 |
+
"A.8.5"
|
| 1160 |
+
],
|
| 1161 |
+
"gdpr": [
|
| 1162 |
+
"Art. 32(1)(b)"
|
| 1163 |
+
],
|
| 1164 |
+
"ai_act": []
|
| 1165 |
+
}
|
| 1166 |
+
},
|
| 1167 |
{
|
| 1168 |
"id": "vuln.pending_updates",
|
| 1169 |
"section": "baseline",
|
|
|
|
| 1225 |
"android": "App updates"
|
| 1226 |
}
|
| 1227 |
},
|
| 1228 |
+
{
|
| 1229 |
+
"id": "software.prohibited",
|
| 1230 |
+
"section": "baseline",
|
| 1231 |
+
"name": "Prohibited software",
|
| 1232 |
+
"os": [
|
| 1233 |
+
"windows",
|
| 1234 |
+
"linux",
|
| 1235 |
+
"macos"
|
| 1236 |
+
],
|
| 1237 |
+
"baseline_keys": [
|
| 1238 |
+
"PROHIBITED_SOFTWARE"
|
| 1239 |
+
],
|
| 1240 |
+
"rule": "No installed application or package whose name contains an entry of PROHIBITED_SOFTWARE (torrent clients, activation cracks by default). Licences themselves cannot be checked from the device.",
|
| 1241 |
+
"controls": {
|
| 1242 |
+
"iso27001": [
|
| 1243 |
+
"A.8.19",
|
| 1244 |
+
"A.5.32"
|
| 1245 |
+
],
|
| 1246 |
+
"gdpr": [
|
| 1247 |
+
"Art. 32(1)(b)"
|
| 1248 |
+
],
|
| 1249 |
+
"ai_act": []
|
| 1250 |
+
}
|
| 1251 |
+
},
|
| 1252 |
{
|
| 1253 |
"id": "vuln.known_vulnerabilities",
|
| 1254 |
"section": "baseline",
|
collectors/linux/audit.sh
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
set -u
|
| 12 |
|
| 13 |
COLLECTOR_VERSION="0.2.0"
|
| 14 |
-
CATALOG_VERSION="0.
|
| 15 |
|
| 16 |
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
| 17 |
ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
|
|
@@ -49,7 +49,7 @@ conf_get() {
|
|
| 49 |
if [ -n "$value" ]; then printf '%s' "$value"; else printf '%s' "$3"; fi
|
| 50 |
}
|
| 51 |
|
| 52 |
-
BASELINE_KEYS="PASSWORD_MIN_LENGTH PASSWORD_HISTORY PASSWORD_MAX_AGE_DAYS PASSWORD_MIN_AGE_DAYS PASSWORD_COMPLEXITY LOCKOUT_THRESHOLD_MAX LOCKOUT_DURATION_MIN_MINUTES LOCKOUT_OBSERVATION_MIN_MINUTES SIGNATURE_MAX_AGE_DAYS MACOS_XPROTECT_MAX_AGE_DAYS FIREWALL_OUTBOUND SCREEN_LOCK_MAX_SECONDS USB_READ USB_WRITE APPROVED_ADMINS ALLOW_DISABLED_BUILTIN_ADMIN UPDATES_MAX_AGE_DAYS BACKUP_MAX_AGE_DAYS APPROVED_REMOTE_SERVICES WINDOWS_MIN_BUILD MACOS_MIN_MAJOR UBUNTU_MIN_VERSION DEBIAN_MIN_VERSION RHEL_MIN_VERSION PERSONAL_DATA_SCAN APPROVED_AI_TOOLS USB_DEVICE_ACCESS MAX_PENDING_SECURITY_UPDATES MAX_OUTDATED_APPS MAX_CRITICAL_HIGH_VULNERABILITIES"
|
| 53 |
declare -A B
|
| 54 |
B[PASSWORD_MIN_LENGTH]=14; B[PASSWORD_HISTORY]=24; B[PASSWORD_MAX_AGE_DAYS]=365; B[PASSWORD_MIN_AGE_DAYS]=1
|
| 55 |
B[PASSWORD_COMPLEXITY]=1; B[LOCKOUT_THRESHOLD_MAX]=5; B[LOCKOUT_DURATION_MIN_MINUTES]=15; B[LOCKOUT_OBSERVATION_MIN_MINUTES]=15
|
|
@@ -59,6 +59,8 @@ B[UPDATES_MAX_AGE_DAYS]=30; B[BACKUP_MAX_AGE_DAYS]=7; B[APPROVED_REMOTE_SERVICES
|
|
| 59 |
B[MACOS_MIN_MAJOR]=14; B[UBUNTU_MIN_VERSION]=22.04; B[DEBIAN_MIN_VERSION]=12; B[RHEL_MIN_VERSION]=9
|
| 60 |
B[PERSONAL_DATA_SCAN]=0; B[APPROVED_AI_TOOLS]=""
|
| 61 |
B[USB_DEVICE_ACCESS]=allow; B[MAX_PENDING_SECURITY_UPDATES]=0; B[MAX_OUTDATED_APPS]=0; B[MAX_CRITICAL_HIGH_VULNERABILITIES]=0
|
|
|
|
|
|
|
| 62 |
for key in $BASELINE_KEYS; do B[$key]=$(conf_get "$BASELINE_FILE" "$key" "${B[$key]}"); done
|
| 63 |
|
| 64 |
is_root() { [ "$(id -u)" -eq 0 ]; }
|
|
@@ -284,6 +286,22 @@ else
|
|
| 284 |
[ "$clamonacc" -eq 1 ]; pass_fail $? malware.on_access $S "On-access malware protection" "$( [ "$clamonacc" -eq 1 ] && echo "clamonacc running" || echo "not running")" "on-access scanning"
|
| 285 |
fi
|
| 286 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
# Firewall: ufw, firewalld, nftables or iptables.
|
| 288 |
fw_name=""; fw_in=""; fw_out=""; fw_detail=""
|
| 289 |
if have ufw && is_root; then
|
|
@@ -424,6 +442,24 @@ else
|
|
| 424 |
fi
|
| 425 |
fi
|
| 426 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
# Disk encryption (LUKS under the root filesystem)
|
| 428 |
root_src=$(findmnt -no SOURCE / 2>/dev/null)
|
| 429 |
# Btrfs subvolumes appear as /dev/mapper/x[/@]: keep the device part only.
|
|
@@ -503,6 +539,31 @@ else
|
|
| 503 |
pass_fail $? vuln.outdated_apps $S "Outdated third-party applications" "$outdated outdated" "$OUTDATED_EXP" "$outdated_detail"
|
| 504 |
fi
|
| 505 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
# Known vulnerabilities: inventory now; matching against offline OSV data comes in a later version.
|
| 507 |
add vuln.known_vulnerabilities $S "Known vulnerabilities in installed software" Pending "$pkg_count packages inventoried" "<= ${B[MAX_CRITICAL_HIGH_VULNERABILITIES]} critical/high" "Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match."
|
| 508 |
|
|
|
|
| 11 |
set -u
|
| 12 |
|
| 13 |
COLLECTOR_VERSION="0.2.0"
|
| 14 |
+
CATALOG_VERSION="0.4.0"
|
| 15 |
|
| 16 |
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
| 17 |
ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
|
|
|
|
| 49 |
if [ -n "$value" ]; then printf '%s' "$value"; else printf '%s' "$3"; fi
|
| 50 |
}
|
| 51 |
|
| 52 |
+
BASELINE_KEYS="PASSWORD_MIN_LENGTH PASSWORD_HISTORY PASSWORD_MAX_AGE_DAYS PASSWORD_MIN_AGE_DAYS PASSWORD_COMPLEXITY LOCKOUT_THRESHOLD_MAX LOCKOUT_DURATION_MIN_MINUTES LOCKOUT_OBSERVATION_MIN_MINUTES SIGNATURE_MAX_AGE_DAYS MACOS_XPROTECT_MAX_AGE_DAYS FIREWALL_OUTBOUND SCREEN_LOCK_MAX_SECONDS USB_READ USB_WRITE APPROVED_ADMINS ALLOW_DISABLED_BUILTIN_ADMIN UPDATES_MAX_AGE_DAYS BACKUP_MAX_AGE_DAYS APPROVED_REMOTE_SERVICES WINDOWS_MIN_BUILD MACOS_MIN_MAJOR UBUNTU_MIN_VERSION DEBIAN_MIN_VERSION RHEL_MIN_VERSION PERSONAL_DATA_SCAN APPROVED_AI_TOOLS USB_DEVICE_ACCESS MAX_PENDING_SECURITY_UPDATES MAX_OUTDATED_APPS MAX_CRITICAL_HIGH_VULNERABILITIES SHARED_ACCOUNT_NAMES PROHIBITED_SOFTWARE"
|
| 53 |
declare -A B
|
| 54 |
B[PASSWORD_MIN_LENGTH]=14; B[PASSWORD_HISTORY]=24; B[PASSWORD_MAX_AGE_DAYS]=365; B[PASSWORD_MIN_AGE_DAYS]=1
|
| 55 |
B[PASSWORD_COMPLEXITY]=1; B[LOCKOUT_THRESHOLD_MAX]=5; B[LOCKOUT_DURATION_MIN_MINUTES]=15; B[LOCKOUT_OBSERVATION_MIN_MINUTES]=15
|
|
|
|
| 59 |
B[MACOS_MIN_MAJOR]=14; B[UBUNTU_MIN_VERSION]=22.04; B[DEBIAN_MIN_VERSION]=12; B[RHEL_MIN_VERSION]=9
|
| 60 |
B[PERSONAL_DATA_SCAN]=0; B[APPROVED_AI_TOOLS]=""
|
| 61 |
B[USB_DEVICE_ACCESS]=allow; B[MAX_PENDING_SECURITY_UPDATES]=0; B[MAX_OUTDATED_APPS]=0; B[MAX_CRITICAL_HIGH_VULNERABILITIES]=0
|
| 62 |
+
B[SHARED_ACCOUNT_NAMES]="admin,administrator,user,users,shared,office,staff,reception,frontdesk,test,temp,demo,student,kiosk,public,helpdesk,owner"
|
| 63 |
+
B[PROHIBITED_SOFTWARE]="Torrent,Transmission,Deluge,Vuze,FrostWire,KMSpico,KMSAuto,AutoKMS,Microsoft Toolkit"
|
| 64 |
for key in $BASELINE_KEYS; do B[$key]=$(conf_get "$BASELINE_FILE" "$key" "${B[$key]}"); done
|
| 65 |
|
| 66 |
is_root() { [ "$(id -u)" -eq 0 ]; }
|
|
|
|
| 286 |
[ "$clamonacc" -eq 1 ]; pass_fail $? malware.on_access $S "On-access malware protection" "$( [ "$clamonacc" -eq 1 ] && echo "clamonacc running" || echo "not running")" "on-access scanning"
|
| 287 |
fi
|
| 288 |
|
| 289 |
+
# Tamper protection: an enforcing Linux security module (SELinux or AppArmor) confines services, so malware running as
|
| 290 |
+
# them cannot switch off protection; Secure Boot is reported for information.
|
| 291 |
+
lsm=""
|
| 292 |
+
if have getenforce && [ "$(getenforce 2>/dev/null)" = "Enforcing" ]; then lsm="SELinux enforcing"
|
| 293 |
+
elif [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = "Y" ]; then
|
| 294 |
+
profiles=$(cat /sys/kernel/security/apparmor/profiles 2>/dev/null | grep -c "(enforce)")
|
| 295 |
+
if [ "${profiles:-0}" -gt 0 ]; then lsm="AppArmor enforcing ($profiles profiles)"
|
| 296 |
+
elif ! is_root; then lsm="AppArmor enabled"; fi
|
| 297 |
+
fi
|
| 298 |
+
sb=""; have mokutil && sb=$(mokutil --sb-state 2>/dev/null | head -1)
|
| 299 |
+
if [ -n "$lsm" ]; then
|
| 300 |
+
add malware.tamper $S "Tamper protection" Compliant "$lsm" "SELinux or AppArmor enforcing" "${sb:+Secure Boot: $sb}"
|
| 301 |
+
else
|
| 302 |
+
add malware.tamper $S "Tamper protection" Non-Compliant "no security module enforcing" "SELinux or AppArmor enforcing" "${sb:+Secure Boot: $sb}"
|
| 303 |
+
fi
|
| 304 |
+
|
| 305 |
# Firewall: ufw, firewalld, nftables or iptables.
|
| 306 |
fw_name=""; fw_in=""; fw_out=""; fw_detail=""
|
| 307 |
if have ufw && is_root; then
|
|
|
|
| 442 |
fi
|
| 443 |
fi
|
| 444 |
|
| 445 |
+
# Unique user login: no automatic login in the display manager, and no shared or generic account names.
|
| 446 |
+
auto_login=""
|
| 447 |
+
for f in /etc/gdm3/custom.conf /etc/gdm/custom.conf; do
|
| 448 |
+
[ -r "$f" ] && grep -qiE '^[[:space:]]*AutomaticLoginEnable[[:space:]]*=[[:space:]]*true' "$f" && auto_login=$(awk -F= 'tolower($1) ~ /^[[:space:]]*automaticlogin[[:space:]]*$/ { gsub(/[[:space:]]/, "", $2); print $2 }' "$f" | head -1)
|
| 449 |
+
[ -n "$auto_login" ] && break
|
| 450 |
+
done
|
| 451 |
+
[ -z "$auto_login" ] && auto_login=$(cat /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.d/*.conf 2>/dev/null | awk -F= '/^[[:space:]]*autologin-user[[:space:]]*=/ { gsub(/[[:space:]]/, "", $2); if ($2 != "") print $2 }' | head -1)
|
| 452 |
+
[ -z "$auto_login" ] && auto_login=$(cat /etc/sddm.conf /etc/sddm.conf.d/*.conf 2>/dev/null | awk -F= '/^\[Autologin\]/ { a = 1; next } /^\[/ { a = 0 } a && $1 ~ /^[[:space:]]*User[[:space:]]*$/ { gsub(/[[:space:]]/, "", $2); if ($2 != "") print $2 }' | head -1)
|
| 453 |
+
generic=""
|
| 454 |
+
for entry in $HUMAN_USERS; do
|
| 455 |
+
name=${entry%%:*}
|
| 456 |
+
in_list "$name" "${B[SHARED_ACCOUNT_NAMES]}" && generic="${generic:+$generic, }$name"
|
| 457 |
+
done
|
| 458 |
+
issues=""
|
| 459 |
+
[ -n "$auto_login" ] && issues="automatic login as $auto_login"
|
| 460 |
+
[ -n "$generic" ] && issues="${issues:+$issues; }shared or generic accounts: $generic"
|
| 461 |
+
[ -z "$issues" ]; pass_fail $? account.unique_login $S "Unique user login" "${issues:-personal accounts, no automatic login}" "personal accounts, no automatic login"
|
| 462 |
+
|
| 463 |
# Disk encryption (LUKS under the root filesystem)
|
| 464 |
root_src=$(findmnt -no SOURCE / 2>/dev/null)
|
| 465 |
# Btrfs subvolumes appear as /dev/mapper/x[/@]: keep the device part only.
|
|
|
|
| 539 |
pass_fail $? vuln.outdated_apps $S "Outdated third-party applications" "$outdated outdated" "$OUTDATED_EXP" "$outdated_detail"
|
| 540 |
fi
|
| 541 |
|
| 542 |
+
# Prohibited software (PROHIBITED_SOFTWARE: parts of package names, any case). Licences cannot be checked from the device.
|
| 543 |
+
pkg_names=""
|
| 544 |
+
if have dpkg-query; then pkg_names=$(dpkg-query -W -f '${db:Status-Abbrev}\t${Package}\n' 2>/dev/null | awk -F'\t' '$1 ~ /^ii/ { print $2 }')
|
| 545 |
+
elif have rpm; then pkg_names=$(rpm -qa --qf '%{NAME}\n' 2>/dev/null); fi
|
| 546 |
+
have flatpak && pkg_names="$pkg_names
|
| 547 |
+
$(flatpak list --app --columns=application 2>/dev/null)"
|
| 548 |
+
have snap && pkg_names="$pkg_names
|
| 549 |
+
$(snap list 2>/dev/null | awk 'NR > 1 { print $1 }')"
|
| 550 |
+
prohibited=""
|
| 551 |
+
if [ -n "${B[PROHIBITED_SOFTWARE]}" ]; then
|
| 552 |
+
old_ifs="$IFS"; IFS=,
|
| 553 |
+
for item in ${B[PROHIBITED_SOFTWARE]}; do
|
| 554 |
+
item=$(lower "$(printf '%s' "$item" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')")
|
| 555 |
+
[ -n "$item" ] || continue
|
| 556 |
+
found=$(printf '%s\n' "$pkg_names" | grep -iF -- "$item" | grep -v '^lib' | head -3 | paste -sd, - | sed 's/,/, /g')
|
| 557 |
+
[ -n "$found" ] && prohibited="${prohibited:+$prohibited, }$found"
|
| 558 |
+
done
|
| 559 |
+
IFS="$old_ifs"
|
| 560 |
+
fi
|
| 561 |
+
if [ -z "${B[PROHIBITED_SOFTWARE]}" ]; then
|
| 562 |
+
add software.prohibited $S "Prohibited software" Compliant "no list configured" "none of: (empty list)" "PROHIBITED_SOFTWARE in baseline.conf is empty."
|
| 563 |
+
else
|
| 564 |
+
[ -z "$prohibited" ]; pass_fail $? software.prohibited $S "Prohibited software" "${prohibited:-none found}" "none of: ${B[PROHIBITED_SOFTWARE]}"
|
| 565 |
+
fi
|
| 566 |
+
|
| 567 |
# Known vulnerabilities: inventory now; matching against offline OSV data comes in a later version.
|
| 568 |
add vuln.known_vulnerabilities $S "Known vulnerabilities in installed software" Pending "$pkg_count packages inventoried" "<= ${B[MAX_CRITICAL_HIGH_VULNERABILITIES]} critical/high" "Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match."
|
| 569 |
|
collectors/macos/audit.sh
CHANGED
|
@@ -13,7 +13,7 @@
|
|
| 13 |
set -u
|
| 14 |
|
| 15 |
COLLECTOR_VERSION="0.2.0"
|
| 16 |
-
CATALOG_VERSION="0.
|
| 17 |
|
| 18 |
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
| 19 |
ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
|
|
@@ -51,7 +51,7 @@ conf_get() {
|
|
| 51 |
if [ -n "$value" ]; then printf '%s' "$value"; else printf '%s' "$3"; fi
|
| 52 |
}
|
| 53 |
|
| 54 |
-
BASELINE_KEYS="PASSWORD_MIN_LENGTH PASSWORD_HISTORY PASSWORD_MAX_AGE_DAYS PASSWORD_MIN_AGE_DAYS PASSWORD_COMPLEXITY LOCKOUT_THRESHOLD_MAX LOCKOUT_DURATION_MIN_MINUTES LOCKOUT_OBSERVATION_MIN_MINUTES SIGNATURE_MAX_AGE_DAYS MACOS_XPROTECT_MAX_AGE_DAYS FIREWALL_OUTBOUND SCREEN_LOCK_MAX_SECONDS USB_READ USB_WRITE APPROVED_ADMINS ALLOW_DISABLED_BUILTIN_ADMIN UPDATES_MAX_AGE_DAYS BACKUP_MAX_AGE_DAYS APPROVED_REMOTE_SERVICES WINDOWS_MIN_BUILD MACOS_MIN_MAJOR UBUNTU_MIN_VERSION DEBIAN_MIN_VERSION RHEL_MIN_VERSION PERSONAL_DATA_SCAN APPROVED_AI_TOOLS USB_DEVICE_ACCESS MAX_PENDING_SECURITY_UPDATES MAX_OUTDATED_APPS MAX_CRITICAL_HIGH_VULNERABILITIES"
|
| 55 |
|
| 56 |
B_PASSWORD_MIN_LENGTH=$(conf_get "$BASELINE_FILE" PASSWORD_MIN_LENGTH 14)
|
| 57 |
B_PASSWORD_HISTORY=$(conf_get "$BASELINE_FILE" PASSWORD_HISTORY 24)
|
|
@@ -80,6 +80,8 @@ B_RHEL_MIN_VERSION=$(conf_get "$BASELINE_FILE" RHEL_MIN_VERSION 9)
|
|
| 80 |
B_PERSONAL_DATA_SCAN=$(conf_get "$BASELINE_FILE" PERSONAL_DATA_SCAN 0)
|
| 81 |
B_APPROVED_AI_TOOLS=$(conf_get "$BASELINE_FILE" APPROVED_AI_TOOLS "")
|
| 82 |
B_USB_DEVICE_ACCESS=$(conf_get "$BASELINE_FILE" USB_DEVICE_ACCESS allow)
|
|
|
|
|
|
|
| 83 |
B_MAX_PENDING_SECURITY_UPDATES=$(conf_get "$BASELINE_FILE" MAX_PENDING_SECURITY_UPDATES 0)
|
| 84 |
B_MAX_OUTDATED_APPS=$(conf_get "$BASELINE_FILE" MAX_OUTDATED_APPS 0)
|
| 85 |
B_MAX_CRITICAL_HIGH_VULNERABILITIES=$(conf_get "$BASELINE_FILE" MAX_CRITICAL_HIGH_VULNERABILITIES 0)
|
|
@@ -289,6 +291,17 @@ else
|
|
| 289 |
add malware.on_access $S "On-access malware protection" NotApplicable "XProtect only" "on-access scanning" "XProtect scans at launch and download; macOS has no built-in on-access scanning."
|
| 290 |
fi
|
| 291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
# Firewall (application firewall)
|
| 293 |
FW=/usr/libexec/ApplicationFirewall/socketfilterfw
|
| 294 |
fw_state=$("$FW" --getglobalstate 2>/dev/null)
|
|
@@ -416,6 +429,25 @@ else
|
|
| 416 |
add user.account_type $S "Signed-in user account type" Compliant "Standard ($CONSOLE_USER)" "Standard"
|
| 417 |
fi
|
| 418 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 419 |
# FileVault
|
| 420 |
fv=$(fdesetup status 2>/dev/null)
|
| 421 |
if printf '%s' "$fv" | grep -q "FileVault is On"; then
|
|
@@ -481,6 +513,25 @@ for app in /Applications/*.app /Applications/*/*.app ${CONSOLE_HOME:+"$CONSOLE_H
|
|
| 481 |
[ -f "$app/Contents/Info.plist" ] && APP_BUNDLES+=("$app")
|
| 482 |
done
|
| 483 |
app_count=${#APP_BUNDLES[@]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
add vuln.known_vulnerabilities $S "Known vulnerabilities in installed software" Pending "$app_count applications inventoried" "<= $B_MAX_CRITICAL_HIGH_VULNERABILITIES critical/high" "Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match."
|
| 485 |
|
| 486 |
# ---------------------------------------------------------------------------
|
|
|
|
| 13 |
set -u
|
| 14 |
|
| 15 |
COLLECTOR_VERSION="0.2.0"
|
| 16 |
+
CATALOG_VERSION="0.4.0"
|
| 17 |
|
| 18 |
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
| 19 |
ROOT_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
|
|
|
|
| 51 |
if [ -n "$value" ]; then printf '%s' "$value"; else printf '%s' "$3"; fi
|
| 52 |
}
|
| 53 |
|
| 54 |
+
BASELINE_KEYS="PASSWORD_MIN_LENGTH PASSWORD_HISTORY PASSWORD_MAX_AGE_DAYS PASSWORD_MIN_AGE_DAYS PASSWORD_COMPLEXITY LOCKOUT_THRESHOLD_MAX LOCKOUT_DURATION_MIN_MINUTES LOCKOUT_OBSERVATION_MIN_MINUTES SIGNATURE_MAX_AGE_DAYS MACOS_XPROTECT_MAX_AGE_DAYS FIREWALL_OUTBOUND SCREEN_LOCK_MAX_SECONDS USB_READ USB_WRITE APPROVED_ADMINS ALLOW_DISABLED_BUILTIN_ADMIN UPDATES_MAX_AGE_DAYS BACKUP_MAX_AGE_DAYS APPROVED_REMOTE_SERVICES WINDOWS_MIN_BUILD MACOS_MIN_MAJOR UBUNTU_MIN_VERSION DEBIAN_MIN_VERSION RHEL_MIN_VERSION PERSONAL_DATA_SCAN APPROVED_AI_TOOLS USB_DEVICE_ACCESS MAX_PENDING_SECURITY_UPDATES MAX_OUTDATED_APPS MAX_CRITICAL_HIGH_VULNERABILITIES SHARED_ACCOUNT_NAMES PROHIBITED_SOFTWARE"
|
| 55 |
|
| 56 |
B_PASSWORD_MIN_LENGTH=$(conf_get "$BASELINE_FILE" PASSWORD_MIN_LENGTH 14)
|
| 57 |
B_PASSWORD_HISTORY=$(conf_get "$BASELINE_FILE" PASSWORD_HISTORY 24)
|
|
|
|
| 80 |
B_PERSONAL_DATA_SCAN=$(conf_get "$BASELINE_FILE" PERSONAL_DATA_SCAN 0)
|
| 81 |
B_APPROVED_AI_TOOLS=$(conf_get "$BASELINE_FILE" APPROVED_AI_TOOLS "")
|
| 82 |
B_USB_DEVICE_ACCESS=$(conf_get "$BASELINE_FILE" USB_DEVICE_ACCESS allow)
|
| 83 |
+
B_SHARED_ACCOUNT_NAMES=$(conf_get "$BASELINE_FILE" SHARED_ACCOUNT_NAMES "admin,administrator,user,users,shared,office,staff,reception,frontdesk,test,temp,demo,student,kiosk,public,helpdesk,owner")
|
| 84 |
+
B_PROHIBITED_SOFTWARE=$(conf_get "$BASELINE_FILE" PROHIBITED_SOFTWARE "Torrent,Transmission,Deluge,Vuze,FrostWire,KMSpico,KMSAuto,AutoKMS,Microsoft Toolkit")
|
| 85 |
B_MAX_PENDING_SECURITY_UPDATES=$(conf_get "$BASELINE_FILE" MAX_PENDING_SECURITY_UPDATES 0)
|
| 86 |
B_MAX_OUTDATED_APPS=$(conf_get "$BASELINE_FILE" MAX_OUTDATED_APPS 0)
|
| 87 |
B_MAX_CRITICAL_HIGH_VULNERABILITIES=$(conf_get "$BASELINE_FILE" MAX_CRITICAL_HIGH_VULNERABILITIES 0)
|
|
|
|
| 291 |
add malware.on_access $S "On-access malware protection" NotApplicable "XProtect only" "on-access scanning" "XProtect scans at launch and download; macOS has no built-in on-access scanning."
|
| 292 |
fi
|
| 293 |
|
| 294 |
+
# Tamper protection: System Integrity Protection stops anything, even root, changing protected system files and Apple's
|
| 295 |
+
# security tools (XProtect, Gatekeeper); it can only be switched off from Recovery mode.
|
| 296 |
+
sip=$(csrutil status 2>/dev/null)
|
| 297 |
+
if printf '%s' "$sip" | grep -q "status: enabled"; then
|
| 298 |
+
add malware.tamper $S "Tamper protection" Compliant "System Integrity Protection on" "on"
|
| 299 |
+
elif [ -n "$sip" ]; then
|
| 300 |
+
add malware.tamper $S "Tamper protection" Non-Compliant "System Integrity Protection $(printf '%s' "$sip" | sed -n 's/.*status: \([a-z]*\).*/\1/p' | head -1)" "on" "$(printf '%s' "$sip" | head -1)"
|
| 301 |
+
else
|
| 302 |
+
add malware.tamper $S "Tamper protection" Error "not read" "on" "csrutil status gave no answer."
|
| 303 |
+
fi
|
| 304 |
+
|
| 305 |
# Firewall (application firewall)
|
| 306 |
FW=/usr/libexec/ApplicationFirewall/socketfilterfw
|
| 307 |
fw_state=$("$FW" --getglobalstate 2>/dev/null)
|
|
|
|
| 429 |
add user.account_type $S "Signed-in user account type" Compliant "Standard ($CONSOLE_USER)" "Standard"
|
| 430 |
fi
|
| 431 |
|
| 432 |
+
# Unique user login: no automatic login, and no shared or generic account names (each person signs in as themselves).
|
| 433 |
+
auto_login=$(defaults read /Library/Preferences/com.apple.loginwindow autoLoginUser 2>/dev/null)
|
| 434 |
+
generic=""
|
| 435 |
+
while read -r name uid; do
|
| 436 |
+
is_int "$uid" && [ "$uid" -ge 500 ] || continue
|
| 437 |
+
case "$name" in _*|daemon|nobody|root) continue ;; esac
|
| 438 |
+
in_list "$name" "$B_SHARED_ACCOUNT_NAMES" && generic="${generic:+$generic, }$name"
|
| 439 |
+
done <<EOF_USERS
|
| 440 |
+
$(dscl . -list /Users UniqueID 2>/dev/null)
|
| 441 |
+
EOF_USERS
|
| 442 |
+
issues=""
|
| 443 |
+
[ -n "$auto_login" ] && issues="automatic login as $auto_login"
|
| 444 |
+
[ -n "$generic" ] && issues="${issues:+$issues; }shared or generic accounts: $generic"
|
| 445 |
+
if [ -z "$issues" ]; then
|
| 446 |
+
add account.unique_login $S "Unique user login" Compliant "personal accounts, no automatic login" "personal accounts, no automatic login"
|
| 447 |
+
else
|
| 448 |
+
add account.unique_login $S "Unique user login" Non-Compliant "$issues" "personal accounts, no automatic login"
|
| 449 |
+
fi
|
| 450 |
+
|
| 451 |
# FileVault
|
| 452 |
fv=$(fdesetup status 2>/dev/null)
|
| 453 |
if printf '%s' "$fv" | grep -q "FileVault is On"; then
|
|
|
|
| 513 |
[ -f "$app/Contents/Info.plist" ] && APP_BUNDLES+=("$app")
|
| 514 |
done
|
| 515 |
app_count=${#APP_BUNDLES[@]}
|
| 516 |
+
|
| 517 |
+
# Prohibited software (PROHIBITED_SOFTWARE: parts of app names, any case). Licences cannot be checked from the device.
|
| 518 |
+
prohibited=""
|
| 519 |
+
for app in ${APP_BUNDLES[@]+"${APP_BUNDLES[@]}"}; do
|
| 520 |
+
name=$(basename "$app" .app); lname=$(lower "$name")
|
| 521 |
+
old_ifs="$IFS"; IFS=,
|
| 522 |
+
for item in $B_PROHIBITED_SOFTWARE; do
|
| 523 |
+
item=$(lower "$(printf '%s' "$item" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')")
|
| 524 |
+
[ -n "$item" ] && case "$lname" in *"$item"*) prohibited="${prohibited:+$prohibited, }$name"; break ;; esac
|
| 525 |
+
done
|
| 526 |
+
IFS="$old_ifs"
|
| 527 |
+
done
|
| 528 |
+
if [ -z "$B_PROHIBITED_SOFTWARE" ]; then
|
| 529 |
+
add software.prohibited $S "Prohibited software" Compliant "no list configured" "none of: (empty list)" "PROHIBITED_SOFTWARE in baseline.conf is empty."
|
| 530 |
+
elif [ -z "$prohibited" ]; then
|
| 531 |
+
add software.prohibited $S "Prohibited software" Compliant "none found in $app_count applications" "none of: $B_PROHIBITED_SOFTWARE"
|
| 532 |
+
else
|
| 533 |
+
add software.prohibited $S "Prohibited software" Non-Compliant "$prohibited" "none of: $B_PROHIBITED_SOFTWARE"
|
| 534 |
+
fi
|
| 535 |
add vuln.known_vulnerabilities $S "Known vulnerabilities in installed software" Pending "$app_count applications inventoried" "<= $B_MAX_CRITICAL_HIGH_VULNERABILITIES critical/high" "Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match."
|
| 536 |
|
| 537 |
# ---------------------------------------------------------------------------
|
collectors/windows/audit.ps1
CHANGED
|
@@ -26,7 +26,7 @@ param(
|
|
| 26 |
Set-StrictMode -Version 2.0
|
| 27 |
$ErrorActionPreference = 'Stop'
|
| 28 |
$CollectorVersion = '0.2.0'
|
| 29 |
-
$CatalogVersion = '0.
|
| 30 |
|
| 31 |
# ---------------------------------------------------------------------------
|
| 32 |
# Helpers
|
|
@@ -54,6 +54,8 @@ $Defaults = [ordered]@{
|
|
| 54 |
MACOS_MIN_MAJOR = '14'; UBUNTU_MIN_VERSION = '22.04'; DEBIAN_MIN_VERSION = '12'; RHEL_MIN_VERSION = '9'
|
| 55 |
PERSONAL_DATA_SCAN = '0'; APPROVED_AI_TOOLS = ''
|
| 56 |
USB_DEVICE_ACCESS = 'allow'; MAX_PENDING_SECURITY_UPDATES = '0'; MAX_OUTDATED_APPS = '0'; MAX_CRITICAL_HIGH_VULNERABILITIES = '0'
|
|
|
|
|
|
|
| 57 |
}
|
| 58 |
$conf = Read-Conf $Baseline
|
| 59 |
$B = [ordered]@{}
|
|
@@ -329,6 +331,17 @@ Check 'user.account_type' $S 'Signed-in user account type' 'Standard' {
|
|
| 329 |
Pass $false "Administrator ($console)" 'The signed-in user is a member of the local Administrators group.'
|
| 330 |
}
|
| 331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
# BitLocker on the system drive
|
| 333 |
$Bl = $null; $BlError = $null
|
| 334 |
try { Assert-Admin; $Bl = Get-BitLockerVolume -MountPoint $env:SystemDrive -ErrorAction Stop } catch { $BlError = $_.Exception.Message }
|
|
@@ -336,7 +349,7 @@ function BitLockerCheck($Id, $Name, $Expected, [scriptblock]$Test) {
|
|
| 336 |
if ($null -eq $Bl) { Add-Result $Id $S $Name 'Error' 'not read' $Expected $BlError } else { Check $Id $S $Name $Expected $Test }
|
| 337 |
}
|
| 338 |
BitLockerCheck 'encryption.feature' 'BitLocker' 'on' { Pass ("$($Bl.VolumeStatus)" -ne 'FullyDecrypted') $(if ("$($Bl.VolumeStatus)" -ne 'FullyDecrypted') { 'on' } else { 'off' }) }
|
| 339 |
-
BitLockerCheck 'encryption.enabled' 'Encryption' 'fully encrypted' { Pass ("$($Bl.VolumeStatus)" -eq 'FullyEncrypted') ("{0} ({1}%)" -f $Bl.VolumeStatus, $Bl.EncryptionPercentage) }
|
| 340 |
BitLockerCheck 'encryption.protection' 'BitLocker protection' 'protection on, AES' {
|
| 341 |
$method = "$($Bl.EncryptionMethod)"
|
| 342 |
Pass ("$($Bl.ProtectionStatus)" -eq 'On' -and $method -match 'Aes') ("protection {0}, {1}" -f $Bl.ProtectionStatus, $method)
|
|
@@ -401,6 +414,12 @@ $Inventory = @(Get-ItemProperty -Path $UninstallKeys -ErrorAction SilentlyContin
|
|
| 401 |
Where-Object { $_.DisplayName -and -not $_.SystemComponent -and -not $_.ParentKeyName } |
|
| 402 |
ForEach-Object { [ordered]@{ name = "$($_.DisplayName)".Trim(); version = "$($_.DisplayVersion)".Trim(); publisher = "$($_.Publisher)".Trim() } } |
|
| 403 |
Sort-Object { $_.name + '|' + $_.version } -Unique)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
Check 'vuln.known_vulnerabilities' $S 'Known vulnerabilities in installed software' "<= $($B.MAX_CRITICAL_HIGH_VULNERABILITIES) critical/high" {
|
| 405 |
# Inventory now; matching against offline OSV/NVD data comes in a later version.
|
| 406 |
State 'Pending' "$($Inventory.Count) applications inventoried" 'Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match.'
|
|
|
|
| 26 |
Set-StrictMode -Version 2.0
|
| 27 |
$ErrorActionPreference = 'Stop'
|
| 28 |
$CollectorVersion = '0.2.0'
|
| 29 |
+
$CatalogVersion = '0.4.0'
|
| 30 |
|
| 31 |
# ---------------------------------------------------------------------------
|
| 32 |
# Helpers
|
|
|
|
| 54 |
MACOS_MIN_MAJOR = '14'; UBUNTU_MIN_VERSION = '22.04'; DEBIAN_MIN_VERSION = '12'; RHEL_MIN_VERSION = '9'
|
| 55 |
PERSONAL_DATA_SCAN = '0'; APPROVED_AI_TOOLS = ''
|
| 56 |
USB_DEVICE_ACCESS = 'allow'; MAX_PENDING_SECURITY_UPDATES = '0'; MAX_OUTDATED_APPS = '0'; MAX_CRITICAL_HIGH_VULNERABILITIES = '0'
|
| 57 |
+
SHARED_ACCOUNT_NAMES = 'admin,administrator,user,users,shared,office,staff,reception,frontdesk,test,temp,demo,student,kiosk,public,helpdesk,owner'
|
| 58 |
+
PROHIBITED_SOFTWARE = 'Torrent,Transmission,Deluge,Vuze,FrostWire,KMSpico,KMSAuto,AutoKMS,Microsoft Toolkit'
|
| 59 |
}
|
| 60 |
$conf = Read-Conf $Baseline
|
| 61 |
$B = [ordered]@{}
|
|
|
|
| 331 |
Pass $false "Administrator ($console)" 'The signed-in user is a member of the local Administrators group.'
|
| 332 |
}
|
| 333 |
|
| 334 |
+
# Unique user login: no automatic sign-in (Winlogon AutoAdminLogon) and no enabled shared or generic local accounts.
|
| 335 |
+
Check 'account.unique_login' $S 'Unique user login' 'personal accounts, no automatic login' {
|
| 336 |
+
$winlogon = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
|
| 337 |
+
$issues = @()
|
| 338 |
+
if ("$(Get-RegValue $winlogon 'AutoAdminLogon')" -eq '1') { $issues += "automatic login as $(Get-RegValue $winlogon 'DefaultUserName')" }
|
| 339 |
+
$shared = @(Split-List $B.SHARED_ACCOUNT_NAMES)
|
| 340 |
+
$generic = @(Get-LocalUser -ErrorAction Stop | Where-Object { $_.Enabled -and ($shared -contains $_.Name) } | ForEach-Object { $_.Name })
|
| 341 |
+
if ($generic.Count) { $issues += "shared or generic accounts: $($generic -join ', ')" }
|
| 342 |
+
if ($issues.Count) { Pass $false ($issues -join '; ') } else { Pass $true 'personal accounts, no automatic login' }
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
# BitLocker on the system drive
|
| 346 |
$Bl = $null; $BlError = $null
|
| 347 |
try { Assert-Admin; $Bl = Get-BitLockerVolume -MountPoint $env:SystemDrive -ErrorAction Stop } catch { $BlError = $_.Exception.Message }
|
|
|
|
| 349 |
if ($null -eq $Bl) { Add-Result $Id $S $Name 'Error' 'not read' $Expected $BlError } else { Check $Id $S $Name $Expected $Test }
|
| 350 |
}
|
| 351 |
BitLockerCheck 'encryption.feature' 'BitLocker' 'on' { Pass ("$($Bl.VolumeStatus)" -ne 'FullyDecrypted') $(if ("$($Bl.VolumeStatus)" -ne 'FullyDecrypted') { 'on' } else { 'off' }) }
|
| 352 |
+
BitLockerCheck 'encryption.enabled' 'Encryption' 'fully encrypted' { Pass ("$($Bl.VolumeStatus)" -eq 'FullyEncrypted') ("BitLocker: {0} ({1}%)" -f $Bl.VolumeStatus, $Bl.EncryptionPercentage) }
|
| 353 |
BitLockerCheck 'encryption.protection' 'BitLocker protection' 'protection on, AES' {
|
| 354 |
$method = "$($Bl.EncryptionMethod)"
|
| 355 |
Pass ("$($Bl.ProtectionStatus)" -eq 'On' -and $method -match 'Aes') ("protection {0}, {1}" -f $Bl.ProtectionStatus, $method)
|
|
|
|
| 414 |
Where-Object { $_.DisplayName -and -not $_.SystemComponent -and -not $_.ParentKeyName } |
|
| 415 |
ForEach-Object { [ordered]@{ name = "$($_.DisplayName)".Trim(); version = "$($_.DisplayVersion)".Trim(); publisher = "$($_.Publisher)".Trim() } } |
|
| 416 |
Sort-Object { $_.name + '|' + $_.version } -Unique)
|
| 417 |
+
# Prohibited software (PROHIBITED_SOFTWARE: parts of installed program names, any case). Licences cannot be checked here.
|
| 418 |
+
Check 'software.prohibited' $S 'Prohibited software' $(if ($B.PROHIBITED_SOFTWARE) { "none of: $($B.PROHIBITED_SOFTWARE)" } else { 'none of: (empty list)' }) {
|
| 419 |
+
if (-not $B.PROHIBITED_SOFTWARE) { return State 'Compliant' 'no list configured' 'PROHIBITED_SOFTWARE in baseline.conf is empty.' }
|
| 420 |
+
$found = @($Inventory | Where-Object { $n = $_.name; @(Split-List $B.PROHIBITED_SOFTWARE | Where-Object { $n -like "*$_*" }).Count } | ForEach-Object { $_.name } | Select-Object -Unique)
|
| 421 |
+
if ($found.Count) { Pass $false ($found -join ', ') } else { Pass $true "none found in $($Inventory.Count) programs" }
|
| 422 |
+
}
|
| 423 |
Check 'vuln.known_vulnerabilities' $S 'Known vulnerabilities in installed software' "<= $($B.MAX_CRITICAL_HIGH_VULNERABILITIES) critical/high" {
|
| 424 |
# Inventory now; matching against offline OSV/NVD data comes in a later version.
|
| 425 |
State 'Pending' "$($Inventory.Count) applications inventoried" 'Inventory saved for the Devseis app, which matches it against its offline OSV/NVD vulnerability data; the collector on its own does not match.'
|
index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="utf-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
| 6 |
-
<meta name="description" content="Arx: a free security audit for your Mac, Windows or Linux computer.
|
| 7 |
<meta name="theme-color" content="#ed2939">
|
| 8 |
<title>Arx · Security audit for your computer</title>
|
| 9 |
<link rel="icon" href="app/build/icon.png">
|
|
@@ -33,7 +33,7 @@
|
|
| 33 |
<section class="wrap hero">
|
| 34 |
<p class="eyebrow"><img src="app/build/icon.png" alt="">Arx security audit</p>
|
| 35 |
<h1>Is your computer secure?<br><span class="grad">Find out in a minute.</span></h1>
|
| 36 |
-
<p class="lead">A free audit of your Mac, Windows or Linux computer: <b>
|
| 37 |
|
| 38 |
<div class="device-card" id="deviceCard">
|
| 39 |
<span class="device-icon" id="deviceIcon">💻</span>
|
|
@@ -56,12 +56,12 @@
|
|
| 56 |
<label class="btn btn-lg" for="reportFile" title="Open the …-evidence.json file Arx saves next to each report">Open a report</label>
|
| 57 |
<input type="file" id="reportFile" accept=".json,application/json" hidden>
|
| 58 |
</div>
|
| 59 |
-
<p class="tiny muted" id="heroMeta">Free · open source · version 0.5.
|
| 60 |
</section>
|
| 61 |
|
| 62 |
<section class="wrap">
|
| 63 |
<div class="stats">
|
| 64 |
-
<div class="stat c-red"><span class="tiny muted">Checks</span><b>
|
| 65 |
<div class="stat c-blue"><span class="tiny muted">Time</span><b>~1 min</b><span class="tiny muted">for the whole audit</span></div>
|
| 66 |
<div class="stat c-green"><span class="tiny muted">Uploaded</span><b>0 bytes</b><span class="tiny muted">runs offline</span></div>
|
| 67 |
<div class="stat c-violet"><span class="tiny muted">Frameworks</span><b>3</b><span class="tiny muted">ISO · GDPR · AI Act</span></div>
|
|
@@ -69,7 +69,7 @@
|
|
| 69 |
</section>
|
| 70 |
|
| 71 |
<section class="wrap section" id="checks">
|
| 72 |
-
<div class="section-head"><h2>High-risk checks</h2><a class="tiny muted link" href="#all-checks">See all
|
| 73 |
<div class="rail" id="riskRail"></div>
|
| 74 |
</section>
|
| 75 |
|
|
@@ -95,7 +95,7 @@
|
|
| 95 |
</section>
|
| 96 |
|
| 97 |
<section class="wrap section" id="download">
|
| 98 |
-
<div class="section-head"><h2>Download Arx</h2><span class="tiny muted" id="dlVersion">Version 0.5.
|
| 99 |
<div class="dl-grid">
|
| 100 |
<article class="dl-card" data-os="mac">
|
| 101 |
<span class="ribbon ribbon-you hidden">YOUR SYSTEM</span>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="utf-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
| 6 |
+
<meta name="description" content="Arx: a free security audit for your Mac, Windows or Linux computer. 70 checks in about a minute, offline, mapped to ISO 27001, GDPR and the EU AI Act, with one-click fixes on Mac. Nothing is uploaded.">
|
| 7 |
<meta name="theme-color" content="#ed2939">
|
| 8 |
<title>Arx · Security audit for your computer</title>
|
| 9 |
<link rel="icon" href="app/build/icon.png">
|
|
|
|
| 33 |
<section class="wrap hero">
|
| 34 |
<p class="eyebrow"><img src="app/build/icon.png" alt="">Arx security audit</p>
|
| 35 |
<h1>Is your computer secure?<br><span class="grad">Find out in a minute.</span></h1>
|
| 36 |
+
<p class="lead">A free audit of your Mac, Windows or Linux computer: <b><span data-count>70</span> checks</b> mapped to <b>ISO 27001</b>, <b>GDPR</b> and the <b>EU AI Act</b>. A small AI on your computer writes the report, and on a Mac Arx can <b>fix problems for you</b>. It runs offline. <u>Nothing is uploaded.</u></p>
|
| 37 |
|
| 38 |
<div class="device-card" id="deviceCard">
|
| 39 |
<span class="device-icon" id="deviceIcon">💻</span>
|
|
|
|
| 56 |
<label class="btn btn-lg" for="reportFile" title="Open the …-evidence.json file Arx saves next to each report">Open a report</label>
|
| 57 |
<input type="file" id="reportFile" accept=".json,application/json" hidden>
|
| 58 |
</div>
|
| 59 |
+
<p class="tiny muted" id="heroMeta">Free · open source · version 0.5.1</p>
|
| 60 |
</section>
|
| 61 |
|
| 62 |
<section class="wrap">
|
| 63 |
<div class="stats">
|
| 64 |
+
<div class="stat c-red"><span class="tiny muted">Checks</span><b data-count>70</b><span class="tiny muted">settings & controls</span></div>
|
| 65 |
<div class="stat c-blue"><span class="tiny muted">Time</span><b>~1 min</b><span class="tiny muted">for the whole audit</span></div>
|
| 66 |
<div class="stat c-green"><span class="tiny muted">Uploaded</span><b>0 bytes</b><span class="tiny muted">runs offline</span></div>
|
| 67 |
<div class="stat c-violet"><span class="tiny muted">Frameworks</span><b>3</b><span class="tiny muted">ISO · GDPR · AI Act</span></div>
|
|
|
|
| 69 |
</section>
|
| 70 |
|
| 71 |
<section class="wrap section" id="checks">
|
| 72 |
+
<div class="section-head"><h2>High-risk checks</h2><a class="tiny muted link" href="#all-checks">See all <span data-count>70</span> →</a></div>
|
| 73 |
<div class="rail" id="riskRail"></div>
|
| 74 |
</section>
|
| 75 |
|
|
|
|
| 95 |
</section>
|
| 96 |
|
| 97 |
<section class="wrap section" id="download">
|
| 98 |
+
<div class="section-head"><h2>Download Arx</h2><span class="tiny muted" id="dlVersion">Version 0.5.1</span></div>
|
| 99 |
<div class="dl-grid">
|
| 100 |
<article class="dl-card" data-os="mac">
|
| 101 |
<span class="ribbon ribbon-you hidden">YOUR SYSTEM</span>
|
library/check_guidance.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"library_version": "0.
|
| 3 |
"note": "Per-check guidance used to write findings. Fix steps are written for administrators; prefer central management (Group Policy/Intune, MDM, configuration management) over per-device changes. Review by a security professional before use with customers.",
|
| 4 |
"aliases": {
|
| 5 |
"firewall.domain.enabled": "firewall.enabled",
|
|
@@ -257,7 +257,7 @@
|
|
| 257 |
"verify": "Re-run the audit; On-access malware protection should be Compliant."
|
| 258 |
},
|
| 259 |
"malware.tamper": {
|
| 260 |
-
"why": "Tamper protection stops malware or
|
| 261 |
"risk": {
|
| 262 |
"level": "Medium",
|
| 263 |
"reason": "Attackers commonly disable antivirus before deploying ransomware."
|
|
@@ -265,6 +265,13 @@
|
|
| 265 |
"fix": {
|
| 266 |
"windows": [
|
| 267 |
"Turn on Tamper Protection in Windows Security > Virus & threat protection settings, or centrally through Microsoft Intune / Defender for Endpoint (it cannot be set with PowerShell)."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
]
|
| 269 |
},
|
| 270 |
"verify": "Re-run the audit; Tamper protection should be on."
|
|
@@ -1219,6 +1226,50 @@
|
|
| 1219 |
]
|
| 1220 |
},
|
| 1221 |
"verify": "Re-run the phone check; previews should be hidden when the phone is locked."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1222 |
}
|
| 1223 |
}
|
| 1224 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"library_version": "0.4.0",
|
| 3 |
"note": "Per-check guidance used to write findings. Fix steps are written for administrators; prefer central management (Group Policy/Intune, MDM, configuration management) over per-device changes. Review by a security professional before use with customers.",
|
| 4 |
"aliases": {
|
| 5 |
"firewall.domain.enabled": "firewall.enabled",
|
|
|
|
| 257 |
"verify": "Re-run the audit; On-access malware protection should be Compliant."
|
| 258 |
},
|
| 259 |
"malware.tamper": {
|
| 260 |
+
"why": "Tamper protection stops malware, or a user, from switching off the device's security protection.",
|
| 261 |
"risk": {
|
| 262 |
"level": "Medium",
|
| 263 |
"reason": "Attackers commonly disable antivirus before deploying ransomware."
|
|
|
|
| 265 |
"fix": {
|
| 266 |
"windows": [
|
| 267 |
"Turn on Tamper Protection in Windows Security > Virus & threat protection settings, or centrally through Microsoft Intune / Defender for Endpoint (it cannot be set with PowerShell)."
|
| 268 |
+
],
|
| 269 |
+
"macos": [
|
| 270 |
+
"System Integrity Protection can only be turned back on from Recovery: start the Mac in Recovery mode, open Terminal and run csrutil enable, then restart. Ask IT first if a tool needed it off."
|
| 271 |
+
],
|
| 272 |
+
"linux": [
|
| 273 |
+
"Ubuntu / Debian: sudo apt install apparmor apparmor-utils && sudo systemctl enable --now apparmor (profiles load in enforce mode).",
|
| 274 |
+
"RHEL / Fedora: set SELINUX=enforcing in /etc/selinux/config, run sudo touch /.autorelabel and restart."
|
| 275 |
]
|
| 276 |
},
|
| 277 |
"verify": "Re-run the audit; Tamper protection should be on."
|
|
|
|
| 1226 |
]
|
| 1227 |
},
|
| 1228 |
"verify": "Re-run the phone check; previews should be hidden when the phone is locked."
|
| 1229 |
+
},
|
| 1230 |
+
"account.unique_login": {
|
| 1231 |
+
"why": "Every action on a device should be traceable to one person. Automatic login lets anyone who turns the computer on use it, and shared accounts hide who did what.",
|
| 1232 |
+
"risk": {
|
| 1233 |
+
"level": "Medium",
|
| 1234 |
+
"reason": "With shared or automatic logins, a lost or borrowed device opens straight into someone's data, and incidents cannot be traced to a person."
|
| 1235 |
+
},
|
| 1236 |
+
"fix": {
|
| 1237 |
+
"macos": [
|
| 1238 |
+
"Turn off automatic login: System Settings > Users & Groups > Automatically log in as: Off.",
|
| 1239 |
+
"Give each person their own account and remove or rename shared ones such as office or admin (keep one named, approved IT administrator)."
|
| 1240 |
+
],
|
| 1241 |
+
"windows": [
|
| 1242 |
+
"Turn off automatic sign-in: run netplwiz and tick 'Users must enter a user name and password', or set AutoAdminLogon = 0 under HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon.",
|
| 1243 |
+
"Give each person their own account and disable or remove shared local accounts (Computer Management > Local Users and Groups)."
|
| 1244 |
+
],
|
| 1245 |
+
"linux": [
|
| 1246 |
+
"Turn off automatic login in Settings > Users, or set AutomaticLoginEnable=false in /etc/gdm3/custom.conf (autologin-user= in LightDM, [Autologin] User= in SDDM).",
|
| 1247 |
+
"Give each person their own account; lock shared ones with sudo usermod -L <name>."
|
| 1248 |
+
]
|
| 1249 |
+
},
|
| 1250 |
+
"verify": "Re-run the audit; Unique user login should be Compliant."
|
| 1251 |
+
},
|
| 1252 |
+
"software.prohibited": {
|
| 1253 |
+
"why": "Torrent clients and activation cracks are common sources of malware and of unlicensed software, which is a legal and licence-audit risk.",
|
| 1254 |
+
"risk": {
|
| 1255 |
+
"level": "High",
|
| 1256 |
+
"reason": "Activation cracks and pirated downloads often carry malware, and unlicensed software breaches copyright and licence terms."
|
| 1257 |
+
},
|
| 1258 |
+
"fix": {
|
| 1259 |
+
"macos": [
|
| 1260 |
+
"Quit the app and drag it from Applications to the Bin, then empty the Bin.",
|
| 1261 |
+
"If the software is needed for work, ask IT to approve it and remove its name from PROHIBITED_SOFTWARE in baseline.conf."
|
| 1262 |
+
],
|
| 1263 |
+
"windows": [
|
| 1264 |
+
"Uninstall it in Settings > Apps > Installed apps. For activation cracks, also run a full Microsoft Defender scan and activate Windows/Office with a genuine licence.",
|
| 1265 |
+
"If the software is needed for work, ask IT to approve it and remove its name from PROHIBITED_SOFTWARE in baseline.conf."
|
| 1266 |
+
],
|
| 1267 |
+
"linux": [
|
| 1268 |
+
"Remove the package: sudo apt remove <package> (or sudo dnf remove <package>, flatpak uninstall, snap remove).",
|
| 1269 |
+
"If the software is needed for work, ask IT to approve it and remove its name from PROHIBITED_SOFTWARE in baseline.conf."
|
| 1270 |
+
]
|
| 1271 |
+
},
|
| 1272 |
+
"verify": "Re-run the audit; Prohibited software should show none found."
|
| 1273 |
}
|
| 1274 |
}
|
| 1275 |
}
|
library/controls.json
CHANGED
|
@@ -2,199 +2,526 @@
|
|
| 2 |
"library_version": "0.1.0",
|
| 3 |
"note": "Written by Devseis in its own words for retrieval by the auditor model. ISO/IEC 27001:2022 control titles are cited; the standard's text is not reproduced. GDPR and AI Act entries summarise the law and are not legal advice.",
|
| 4 |
"controls": [
|
| 5 |
-
{
|
|
|
|
|
|
|
|
|
|
| 6 |
"summary": "Know which information assets, devices and software exist and who owns them, and keep that list current.",
|
| 7 |
-
"auditor_looks_for": [
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
"summary": "Label information by how sensitive it is so that the right protection can be applied.",
|
| 11 |
-
"auditor_looks_for": [
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
"summary": "Grant access to information and systems based on business need, and document the rules.",
|
| 15 |
-
"auditor_looks_for": [
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
"summary": "Every account belongs to an identifiable person or a documented service, through its whole life cycle.",
|
| 19 |
-
"auditor_looks_for": [
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
"summary": "Passwords and other secrets are allocated, managed and protected under clear rules.",
|
| 23 |
-
"auditor_looks_for": [
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
"summary": "Access rights are granted, reviewed regularly and removed when no longer needed.",
|
| 27 |
-
"auditor_looks_for": [
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
"summary": "Agreements with suppliers set out the security requirements they must meet.",
|
| 31 |
-
"auditor_looks_for": [
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
"summary": "Plan in advance how security incidents are reported, handled and communicated.",
|
| 35 |
-
"auditor_looks_for": [
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
"summary": "Respond to incidents according to the documented procedure.",
|
| 39 |
-
"auditor_looks_for": [
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
"summary": "Meet the legal and contractual requirements for protecting personal data.",
|
| 43 |
-
"auditor_looks_for": [
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
"summary": "People receive awareness and training suited to their role, and it is kept current.",
|
| 47 |
-
"auditor_looks_for": [
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
"summary": "Protect information accessed, processed or stored outside the organisation's premises.",
|
| 51 |
-
"auditor_looks_for": [
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
"summary": "Unattended screens and papers must not expose information.",
|
| 55 |
-
"auditor_looks_for": [
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
"summary": "Manage removable media through its life cycle according to the classification of the data on it.",
|
| 59 |
-
"auditor_looks_for": [
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
"summary": "Protect information stored on, processed by or reachable from user devices.",
|
| 63 |
-
"auditor_looks_for": [
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
"summary": "Restrict and manage the allocation and use of administrator rights.",
|
| 67 |
-
"auditor_looks_for": [
|
| 68 |
-
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
"summary": "Authentication methods and procedures resist guessing, brute force and misuse.",
|
| 71 |
-
"auditor_looks_for": [
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
"summary": "Protect against malware with technical controls supported by user awareness.",
|
| 75 |
-
"auditor_looks_for": [
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
"summary": "Find technical weaknesses in time, judge the exposure and fix them.",
|
| 79 |
-
"auditor_looks_for": [
|
| 80 |
-
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
"summary": "Apply measures that stop sensitive information leaving through unauthorised channels.",
|
| 83 |
-
"auditor_looks_for": [
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
"summary": "Keep backup copies of information and software and test that they can be restored.",
|
| 87 |
-
"auditor_looks_for": [
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
"summary": "Produce, protect and review logs of activities, exceptions and security events.",
|
| 91 |
-
"auditor_looks_for": [
|
| 92 |
-
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
"summary": "Synchronise system clocks to an approved time source.",
|
| 95 |
-
"auditor_looks_for": [
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
"summary": "Control which software users may install.",
|
| 99 |
-
"auditor_looks_for": [
|
| 100 |
-
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
"summary": "Secure, manage and control networks and network devices to protect information.",
|
| 103 |
-
"auditor_looks_for": [
|
| 104 |
-
|
| 105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
"summary": "Define and apply rules for using cryptography, including key management.",
|
| 107 |
-
"auditor_looks_for": [
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
"summary": "Personal data must be adequate, relevant and limited to what is necessary for the purpose.",
|
| 112 |
-
"auditor_looks_for": [
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
"summary": "Personal data must not be kept in identifiable form longer than necessary.",
|
| 116 |
-
"auditor_looks_for": [
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
"summary": "Personal data must be protected against unauthorised access, loss and damage with appropriate measures.",
|
| 120 |
-
"auditor_looks_for": [
|
| 121 |
-
|
| 122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
"summary": "Build data protection into systems and use privacy-friendly settings by default.",
|
| 124 |
-
"auditor_looks_for": [
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
"summary": "Use only processors that give sufficient guarantees, under a written contract with required terms.",
|
| 128 |
-
"auditor_looks_for": [
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
"summary": "Keep a written record of the processing activities you carry out.",
|
| 132 |
-
"auditor_looks_for": [
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
"summary": "Where appropriate, protect personal data with pseudonymisation and encryption.",
|
| 136 |
-
"auditor_looks_for": [
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
"summary": "Ensure the ongoing confidentiality, integrity, availability and resilience of systems that process personal data.",
|
| 140 |
-
"auditor_looks_for": [
|
| 141 |
-
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
"summary": "Be able to restore access to personal data in time after a physical or technical incident.",
|
| 144 |
-
"auditor_looks_for": [
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
"summary": "Regularly test, assess and evaluate whether security measures work.",
|
| 148 |
-
"auditor_looks_for": [
|
| 149 |
-
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
"summary": "Report a personal data breach to the supervisory authority within 72 hours of becoming aware of it, unless it is unlikely to result in a risk.",
|
| 152 |
-
"auditor_looks_for": [
|
| 153 |
-
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
"summary": "Tell affected people about a high-risk breach without undue delay; encryption can remove this duty.",
|
| 156 |
-
"auditor_looks_for": [
|
| 157 |
-
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
"summary": "Assess the impact before processing that is likely to result in a high risk to people.",
|
| 160 |
-
"auditor_looks_for": [
|
| 161 |
-
|
| 162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
"summary": "Transfer personal data outside the EEA only under the conditions of Chapter V.",
|
| 164 |
-
"auditor_looks_for": [
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
"summary": "Providers and deployers take measures so their staff using AI have a sufficient level of AI literacy.",
|
| 169 |
-
"auditor_looks_for": [
|
| 170 |
-
|
| 171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
"summary": "Certain AI uses are banned, such as emotion recognition at work and in education (with narrow exceptions) and social scoring.",
|
| 173 |
-
"auditor_looks_for": [
|
| 174 |
-
|
| 175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
"summary": "An AI system is high-risk if it is a safety component of regulated products or is used for a purpose listed in Annex III.",
|
| 177 |
-
"auditor_looks_for": [
|
| 178 |
-
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
"summary": "High-risk AI systems must be designed so that people can oversee them effectively.",
|
| 181 |
-
"auditor_looks_for": [
|
| 182 |
-
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
"summary": "Deployers must use high-risk AI as instructed, assign human oversight, monitor it, keep logs and inform affected people.",
|
| 185 |
-
"auditor_looks_for": [
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
"summary": "Deployers keep the logs a high-risk AI system generates, under their control, for at least six months unless other law says otherwise.",
|
| 189 |
-
"auditor_looks_for": [
|
| 190 |
-
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
"summary": "People must be told when they interact with an AI system, and deepfakes and certain AI-generated text must be disclosed.",
|
| 193 |
-
"auditor_looks_for": [
|
| 194 |
-
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
"summary": "Lists high-risk uses such as biometrics, critical infrastructure, education, employment and worker management, access to essential services, law enforcement, migration and justice.",
|
| 197 |
-
"auditor_looks_for": [
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
]
|
| 200 |
}
|
|
|
|
| 2 |
"library_version": "0.1.0",
|
| 3 |
"note": "Written by Devseis in its own words for retrieval by the auditor model. ISO/IEC 27001:2022 control titles are cited; the standard's text is not reproduced. GDPR and AI Act entries summarise the law and are not legal advice.",
|
| 4 |
"controls": [
|
| 5 |
+
{
|
| 6 |
+
"id": "A.5.9",
|
| 7 |
+
"framework": "ISO 27001:2022",
|
| 8 |
+
"title": "Inventory of information and other associated assets",
|
| 9 |
"summary": "Know which information assets, devices and software exist and who owns them, and keep that list current.",
|
| 10 |
+
"auditor_looks_for": [
|
| 11 |
+
"An up-to-date asset list that includes endpoints and installed software",
|
| 12 |
+
"An owner for each asset"
|
| 13 |
+
],
|
| 14 |
+
"endpoint_relevance": "Each endpoint and the software on it (including AI tools) should appear in the inventory."
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"id": "A.5.12",
|
| 18 |
+
"framework": "ISO 27001:2022",
|
| 19 |
+
"title": "Classification of information",
|
| 20 |
"summary": "Label information by how sensitive it is so that the right protection can be applied.",
|
| 21 |
+
"auditor_looks_for": [
|
| 22 |
+
"A classification scheme",
|
| 23 |
+
"Evidence that sensitive data is identified, e.g. personal data"
|
| 24 |
+
],
|
| 25 |
+
"endpoint_relevance": "Personal or confidential files stored on laptops need to be found and protected accordingly."
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"id": "A.5.15",
|
| 29 |
+
"framework": "ISO 27001:2022",
|
| 30 |
+
"title": "Access control",
|
| 31 |
"summary": "Grant access to information and systems based on business need, and document the rules.",
|
| 32 |
+
"auditor_looks_for": [
|
| 33 |
+
"An access control policy",
|
| 34 |
+
"Administrative access limited to named, approved people"
|
| 35 |
+
],
|
| 36 |
+
"endpoint_relevance": "Only approved IT staff should hold administrator rights on endpoints."
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"id": "A.5.16",
|
| 40 |
+
"framework": "ISO 27001:2022",
|
| 41 |
+
"title": "Identity management",
|
| 42 |
"summary": "Every account belongs to an identifiable person or a documented service, through its whole life cycle.",
|
| 43 |
+
"auditor_looks_for": [
|
| 44 |
+
"No shared or anonymous accounts",
|
| 45 |
+
"Disabled guest and default accounts"
|
| 46 |
+
],
|
| 47 |
+
"endpoint_relevance": "Guest accounts and anonymous logins break the link between actions and people."
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"id": "A.5.17",
|
| 51 |
+
"framework": "ISO 27001:2022",
|
| 52 |
+
"title": "Authentication information",
|
| 53 |
"summary": "Passwords and other secrets are allocated, managed and protected under clear rules.",
|
| 54 |
+
"auditor_looks_for": [
|
| 55 |
+
"A password rule set (length, reuse, change) enforced by the system",
|
| 56 |
+
"Users told how to protect their passwords"
|
| 57 |
+
],
|
| 58 |
+
"endpoint_relevance": "The device's password policy is the technical enforcement of these rules."
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"id": "A.5.18",
|
| 62 |
+
"framework": "ISO 27001:2022",
|
| 63 |
+
"title": "Access rights",
|
| 64 |
"summary": "Access rights are granted, reviewed regularly and removed when no longer needed.",
|
| 65 |
+
"auditor_looks_for": [
|
| 66 |
+
"Periodic review of who has administrator rights",
|
| 67 |
+
"Removal of rights that are not justified"
|
| 68 |
+
],
|
| 69 |
+
"endpoint_relevance": "Employee accounts that are local administrators without approval are a finding."
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"id": "A.5.20",
|
| 73 |
+
"framework": "ISO 27001:2022",
|
| 74 |
+
"title": "Addressing information security within supplier agreements",
|
| 75 |
"summary": "Agreements with suppliers set out the security requirements they must meet.",
|
| 76 |
+
"auditor_looks_for": [
|
| 77 |
+
"Signed agreements with security and data protection clauses"
|
| 78 |
+
],
|
| 79 |
+
"endpoint_relevance": "Cloud and AI services used from endpoints are suppliers that need agreements."
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"id": "A.5.24",
|
| 83 |
+
"framework": "ISO 27001:2022",
|
| 84 |
+
"title": "Information security incident management planning and preparation",
|
| 85 |
"summary": "Plan in advance how security incidents are reported, handled and communicated.",
|
| 86 |
+
"auditor_looks_for": [
|
| 87 |
+
"A documented incident procedure with roles",
|
| 88 |
+
"Contact points and escalation paths"
|
| 89 |
+
],
|
| 90 |
+
"endpoint_relevance": "Endpoint logs and alerts feed the incident process."
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"id": "A.5.26",
|
| 94 |
+
"framework": "ISO 27001:2022",
|
| 95 |
+
"title": "Response to information security incidents",
|
| 96 |
"summary": "Respond to incidents according to the documented procedure.",
|
| 97 |
+
"auditor_looks_for": [
|
| 98 |
+
"Records of past incidents and how they were handled"
|
| 99 |
+
],
|
| 100 |
+
"endpoint_relevance": "Investigations depend on endpoint evidence being available and trustworthy."
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"id": "A.5.34",
|
| 104 |
+
"framework": "ISO 27001:2022",
|
| 105 |
+
"title": "Privacy and protection of PII",
|
| 106 |
"summary": "Meet the legal and contractual requirements for protecting personal data.",
|
| 107 |
+
"auditor_looks_for": [
|
| 108 |
+
"Links between the ISMS and GDPR compliance",
|
| 109 |
+
"Minimised collection and sharing of personal data"
|
| 110 |
+
],
|
| 111 |
+
"endpoint_relevance": "Diagnostic data sharing and OS AI features can send personal data off the device."
|
| 112 |
+
},
|
| 113 |
+
{
|
| 114 |
+
"id": "A.6.3",
|
| 115 |
+
"framework": "ISO 27001:2022",
|
| 116 |
+
"title": "Information security awareness, education and training",
|
| 117 |
"summary": "People receive awareness and training suited to their role, and it is kept current.",
|
| 118 |
+
"auditor_looks_for": [
|
| 119 |
+
"Training records",
|
| 120 |
+
"Topics that match the risks people face (including AI use)"
|
| 121 |
+
],
|
| 122 |
+
"endpoint_relevance": "Users decide what they install and share; training reduces shadow IT and shadow AI."
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"id": "A.6.7",
|
| 126 |
+
"framework": "ISO 27001:2022",
|
| 127 |
+
"title": "Remote working",
|
| 128 |
"summary": "Protect information accessed, processed or stored outside the organisation's premises.",
|
| 129 |
+
"auditor_looks_for": [
|
| 130 |
+
"Rules for remote access tools",
|
| 131 |
+
"Only approved remote access services enabled"
|
| 132 |
+
],
|
| 133 |
+
"endpoint_relevance": "Remote desktop and screen sharing services open the device to outside access."
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"id": "A.7.7",
|
| 137 |
+
"framework": "ISO 27001:2022",
|
| 138 |
+
"title": "Clear desk and clear screen",
|
| 139 |
"summary": "Unattended screens and papers must not expose information.",
|
| 140 |
+
"auditor_looks_for": [
|
| 141 |
+
"Automatic screen lock after a short idle time",
|
| 142 |
+
"A password needed to unlock"
|
| 143 |
+
],
|
| 144 |
+
"endpoint_relevance": "The screen lock settings are the technical control for clear screen."
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"id": "A.7.10",
|
| 148 |
+
"framework": "ISO 27001:2022",
|
| 149 |
+
"title": "Storage media",
|
| 150 |
"summary": "Manage removable media through its life cycle according to the classification of the data on it.",
|
| 151 |
+
"auditor_looks_for": [
|
| 152 |
+
"Rules for USB and external drives",
|
| 153 |
+
"Encryption or blocking of removable media"
|
| 154 |
+
],
|
| 155 |
+
"endpoint_relevance": "Unrestricted USB writing lets data leave the device unencrypted."
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"id": "A.8.1",
|
| 159 |
+
"framework": "ISO 27001:2022",
|
| 160 |
+
"title": "User endpoint devices",
|
| 161 |
"summary": "Protect information stored on, processed by or reachable from user devices.",
|
| 162 |
+
"auditor_looks_for": [
|
| 163 |
+
"A baseline configuration for laptops and desktops",
|
| 164 |
+
"Encryption, firewall, screen lock and malware protection enforced"
|
| 165 |
+
],
|
| 166 |
+
"endpoint_relevance": "This is the main control the whole endpoint baseline supports."
|
| 167 |
+
},
|
| 168 |
+
{
|
| 169 |
+
"id": "A.8.2",
|
| 170 |
+
"framework": "ISO 27001:2022",
|
| 171 |
+
"title": "Privileged access rights",
|
| 172 |
"summary": "Restrict and manage the allocation and use of administrator rights.",
|
| 173 |
+
"auditor_looks_for": [
|
| 174 |
+
"Named, approved administrators",
|
| 175 |
+
"No everyday user accounts with administrator rights"
|
| 176 |
+
],
|
| 177 |
+
"endpoint_relevance": "Local administrator membership on each device shows whether this control works."
|
| 178 |
+
},
|
| 179 |
+
{
|
| 180 |
+
"id": "A.8.5",
|
| 181 |
+
"framework": "ISO 27001:2022",
|
| 182 |
+
"title": "Secure authentication",
|
| 183 |
"summary": "Authentication methods and procedures resist guessing, brute force and misuse.",
|
| 184 |
+
"auditor_looks_for": [
|
| 185 |
+
"Account lockout after repeated failures",
|
| 186 |
+
"Strong password or multi-factor requirements"
|
| 187 |
+
],
|
| 188 |
+
"endpoint_relevance": "Lockout, complexity and screen-unlock settings implement this on the device."
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"id": "A.8.7",
|
| 192 |
+
"framework": "ISO 27001:2022",
|
| 193 |
+
"title": "Protection against malware",
|
| 194 |
"summary": "Protect against malware with technical controls supported by user awareness.",
|
| 195 |
+
"auditor_looks_for": [
|
| 196 |
+
"Anti-malware running with current signatures",
|
| 197 |
+
"Protection that cannot easily be switched off"
|
| 198 |
+
],
|
| 199 |
+
"endpoint_relevance": "Antivirus status, real-time scanning, tamper protection and signature age are checked on each device."
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"id": "A.8.8",
|
| 203 |
+
"framework": "ISO 27001:2022",
|
| 204 |
+
"title": "Management of technical vulnerabilities",
|
| 205 |
"summary": "Find technical weaknesses in time, judge the exposure and fix them.",
|
| 206 |
+
"auditor_looks_for": [
|
| 207 |
+
"Timely patching",
|
| 208 |
+
"Supported operating system versions"
|
| 209 |
+
],
|
| 210 |
+
"endpoint_relevance": "Automatic updates, recent patch dates and a supported OS show vulnerabilities are being managed."
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"id": "A.8.12",
|
| 214 |
+
"framework": "ISO 27001:2022",
|
| 215 |
+
"title": "Data leakage prevention",
|
| 216 |
"summary": "Apply measures that stop sensitive information leaving through unauthorised channels.",
|
| 217 |
+
"auditor_looks_for": [
|
| 218 |
+
"Controls on removable media and uploads",
|
| 219 |
+
"Monitoring of data leaving the organisation"
|
| 220 |
+
],
|
| 221 |
+
"endpoint_relevance": "USB storage write access is a common leakage channel."
|
| 222 |
+
},
|
| 223 |
+
{
|
| 224 |
+
"id": "A.8.13",
|
| 225 |
+
"framework": "ISO 27001:2022",
|
| 226 |
+
"title": "Information backup",
|
| 227 |
"summary": "Keep backup copies of information and software and test that they can be restored.",
|
| 228 |
+
"auditor_looks_for": [
|
| 229 |
+
"Backups configured and recent",
|
| 230 |
+
"Recovery keys and restore procedures available"
|
| 231 |
+
],
|
| 232 |
+
"endpoint_relevance": "Work stored only on a laptop is lost if the device fails, is stolen or is encrypted by ransomware."
|
| 233 |
+
},
|
| 234 |
+
{
|
| 235 |
+
"id": "A.8.15",
|
| 236 |
+
"framework": "ISO 27001:2022",
|
| 237 |
+
"title": "Logging",
|
| 238 |
"summary": "Produce, protect and review logs of activities, exceptions and security events.",
|
| 239 |
+
"auditor_looks_for": [
|
| 240 |
+
"Logon and account changes recorded",
|
| 241 |
+
"Logs kept long enough for investigation"
|
| 242 |
+
],
|
| 243 |
+
"endpoint_relevance": "Without security event logs, a breach on the device cannot be reconstructed."
|
| 244 |
+
},
|
| 245 |
+
{
|
| 246 |
+
"id": "A.8.17",
|
| 247 |
+
"framework": "ISO 27001:2022",
|
| 248 |
+
"title": "Clock synchronization",
|
| 249 |
"summary": "Synchronise system clocks to an approved time source.",
|
| 250 |
+
"auditor_looks_for": [
|
| 251 |
+
"All devices using network time"
|
| 252 |
+
],
|
| 253 |
+
"endpoint_relevance": "Correct timestamps are needed to correlate events across devices during an incident."
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"id": "A.8.19",
|
| 257 |
+
"framework": "ISO 27001:2022",
|
| 258 |
+
"title": "Installation of software on operational systems",
|
| 259 |
"summary": "Control which software users may install.",
|
| 260 |
+
"auditor_looks_for": [
|
| 261 |
+
"An approved software list",
|
| 262 |
+
"Restrictions on self-installed software"
|
| 263 |
+
],
|
| 264 |
+
"endpoint_relevance": "Unapproved AI tools and remote access tools are signs this control is missing."
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"id": "A.8.20",
|
| 268 |
+
"framework": "ISO 27001:2022",
|
| 269 |
+
"title": "Networks security",
|
| 270 |
"summary": "Secure, manage and control networks and network devices to protect information.",
|
| 271 |
+
"auditor_looks_for": [
|
| 272 |
+
"Host firewalls enabled",
|
| 273 |
+
"Unsolicited inbound connections blocked"
|
| 274 |
+
],
|
| 275 |
+
"endpoint_relevance": "The host firewall protects the laptop on untrusted networks such as hotels and cafés."
|
| 276 |
+
},
|
| 277 |
+
{
|
| 278 |
+
"id": "A.8.24",
|
| 279 |
+
"framework": "ISO 27001:2022",
|
| 280 |
+
"title": "Use of cryptography",
|
| 281 |
"summary": "Define and apply rules for using cryptography, including key management.",
|
| 282 |
+
"auditor_looks_for": [
|
| 283 |
+
"Full-disk encryption with strong algorithms",
|
| 284 |
+
"Recovery keys stored safely"
|
| 285 |
+
],
|
| 286 |
+
"endpoint_relevance": "Disk encryption protects data on lost or stolen devices."
|
| 287 |
+
},
|
| 288 |
+
{
|
| 289 |
+
"id": "Art. 5(1)(c)",
|
| 290 |
+
"framework": "GDPR",
|
| 291 |
+
"title": "Data minimisation",
|
| 292 |
"summary": "Personal data must be adequate, relevant and limited to what is necessary for the purpose.",
|
| 293 |
+
"auditor_looks_for": [
|
| 294 |
+
"Only necessary data collected or shared",
|
| 295 |
+
"OS and app data sharing reduced to the minimum"
|
| 296 |
+
],
|
| 297 |
+
"endpoint_relevance": "Optional diagnostic data and AI features that capture screen content collect more than needed."
|
| 298 |
+
},
|
| 299 |
+
{
|
| 300 |
+
"id": "Art. 5(1)(e)",
|
| 301 |
+
"framework": "GDPR",
|
| 302 |
+
"title": "Storage limitation",
|
| 303 |
"summary": "Personal data must not be kept in identifiable form longer than necessary.",
|
| 304 |
+
"auditor_looks_for": [
|
| 305 |
+
"Retention rules",
|
| 306 |
+
"Old personal data deleted"
|
| 307 |
+
],
|
| 308 |
+
"endpoint_relevance": "Copies of personal data left on laptops are often kept far longer than allowed."
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"id": "Art. 5(1)(f)",
|
| 312 |
+
"framework": "GDPR",
|
| 313 |
+
"title": "Integrity and confidentiality",
|
| 314 |
"summary": "Personal data must be protected against unauthorised access, loss and damage with appropriate measures.",
|
| 315 |
+
"auditor_looks_for": [
|
| 316 |
+
"Technical security measures in place"
|
| 317 |
+
],
|
| 318 |
+
"endpoint_relevance": "The endpoint security baseline is part of these measures."
|
| 319 |
+
},
|
| 320 |
+
{
|
| 321 |
+
"id": "Art. 25",
|
| 322 |
+
"framework": "GDPR",
|
| 323 |
+
"title": "Data protection by design and by default",
|
| 324 |
"summary": "Build data protection into systems and use privacy-friendly settings by default.",
|
| 325 |
+
"auditor_looks_for": [
|
| 326 |
+
"Privacy-protective default settings on devices and software"
|
| 327 |
+
],
|
| 328 |
+
"endpoint_relevance": "Telemetry and AI data-collection features should be off unless needed."
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"id": "Art. 28",
|
| 332 |
+
"framework": "GDPR",
|
| 333 |
+
"title": "Processor",
|
| 334 |
"summary": "Use only processors that give sufficient guarantees, under a written contract with required terms.",
|
| 335 |
+
"auditor_looks_for": [
|
| 336 |
+
"A data processing agreement with each processor"
|
| 337 |
+
],
|
| 338 |
+
"endpoint_relevance": "Cloud AI tools used with work data are processors and need an agreement."
|
| 339 |
+
},
|
| 340 |
+
{
|
| 341 |
+
"id": "Art. 30",
|
| 342 |
+
"framework": "GDPR",
|
| 343 |
+
"title": "Records of processing activities",
|
| 344 |
"summary": "Keep a written record of the processing activities you carry out.",
|
| 345 |
+
"auditor_looks_for": [
|
| 346 |
+
"A current record of processing (RoPA)"
|
| 347 |
+
],
|
| 348 |
+
"endpoint_relevance": "Processing done with endpoint tools, including AI tools, belongs in the record."
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"id": "Art. 32(1)(a)",
|
| 352 |
+
"framework": "GDPR",
|
| 353 |
+
"title": "Security of processing: pseudonymisation and encryption",
|
| 354 |
"summary": "Where appropriate, protect personal data with pseudonymisation and encryption.",
|
| 355 |
+
"auditor_looks_for": [
|
| 356 |
+
"Encrypted devices and removable media"
|
| 357 |
+
],
|
| 358 |
+
"endpoint_relevance": "Disk encryption is the standard measure for laptops holding personal data."
|
| 359 |
+
},
|
| 360 |
+
{
|
| 361 |
+
"id": "Art. 32(1)(b)",
|
| 362 |
+
"framework": "GDPR",
|
| 363 |
+
"title": "Security of processing: confidentiality, integrity, availability and resilience",
|
| 364 |
"summary": "Ensure the ongoing confidentiality, integrity, availability and resilience of systems that process personal data.",
|
| 365 |
+
"auditor_looks_for": [
|
| 366 |
+
"Access control, malware protection, patching and network protection on devices"
|
| 367 |
+
],
|
| 368 |
+
"endpoint_relevance": "Most endpoint baseline checks support this requirement."
|
| 369 |
+
},
|
| 370 |
+
{
|
| 371 |
+
"id": "Art. 32(1)(c)",
|
| 372 |
+
"framework": "GDPR",
|
| 373 |
+
"title": "Security of processing: restore availability and access after an incident",
|
| 374 |
"summary": "Be able to restore access to personal data in time after a physical or technical incident.",
|
| 375 |
+
"auditor_looks_for": [
|
| 376 |
+
"Working backups",
|
| 377 |
+
"Recovery keys available"
|
| 378 |
+
],
|
| 379 |
+
"endpoint_relevance": "Backups and disk-encryption recovery keys make restoration possible."
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"id": "Art. 32(1)(d)",
|
| 383 |
+
"framework": "GDPR",
|
| 384 |
+
"title": "Security of processing: regular testing and evaluation",
|
| 385 |
"summary": "Regularly test, assess and evaluate whether security measures work.",
|
| 386 |
+
"auditor_looks_for": [
|
| 387 |
+
"Periodic audits such as this one",
|
| 388 |
+
"Evidence that findings are followed up"
|
| 389 |
+
],
|
| 390 |
+
"endpoint_relevance": "Weekly audits and logging provide this evidence."
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"id": "Art. 33",
|
| 394 |
+
"framework": "GDPR",
|
| 395 |
+
"title": "Notification of a personal data breach to the supervisory authority",
|
| 396 |
"summary": "Report a personal data breach to the supervisory authority within 72 hours of becoming aware of it, unless it is unlikely to result in a risk.",
|
| 397 |
+
"auditor_looks_for": [
|
| 398 |
+
"A breach procedure",
|
| 399 |
+
"Logs and accurate time to establish what happened"
|
| 400 |
+
],
|
| 401 |
+
"endpoint_relevance": "Security logs and time synchronisation make the 72-hour assessment possible."
|
| 402 |
+
},
|
| 403 |
+
{
|
| 404 |
+
"id": "Art. 34",
|
| 405 |
+
"framework": "GDPR",
|
| 406 |
+
"title": "Communication of a personal data breach to the data subject",
|
| 407 |
"summary": "Tell affected people about a high-risk breach without undue delay; encryption can remove this duty.",
|
| 408 |
+
"auditor_looks_for": [
|
| 409 |
+
"Encryption that makes lost data unintelligible"
|
| 410 |
+
],
|
| 411 |
+
"endpoint_relevance": "Encrypted devices and media can avoid the need to notify individuals."
|
| 412 |
+
},
|
| 413 |
+
{
|
| 414 |
+
"id": "Art. 35",
|
| 415 |
+
"framework": "GDPR",
|
| 416 |
+
"title": "Data protection impact assessment",
|
| 417 |
"summary": "Assess the impact before processing that is likely to result in a high risk to people.",
|
| 418 |
+
"auditor_looks_for": [
|
| 419 |
+
"DPIAs for high-risk processing"
|
| 420 |
+
],
|
| 421 |
+
"endpoint_relevance": "New tools with high-risk processing, such as AI used on employees, may need a DPIA."
|
| 422 |
+
},
|
| 423 |
+
{
|
| 424 |
+
"id": "Art. 44",
|
| 425 |
+
"framework": "GDPR",
|
| 426 |
+
"title": "General principle for transfers",
|
| 427 |
"summary": "Transfer personal data outside the EEA only under the conditions of Chapter V.",
|
| 428 |
+
"auditor_looks_for": [
|
| 429 |
+
"A transfer basis (e.g. adequacy decision, standard contractual clauses) for non-EEA services"
|
| 430 |
+
],
|
| 431 |
+
"endpoint_relevance": "Cloud AI tools often process data outside the EEA."
|
| 432 |
+
},
|
| 433 |
+
{
|
| 434 |
+
"id": "Art. 4",
|
| 435 |
+
"framework": "EU AI Act",
|
| 436 |
+
"title": "AI literacy",
|
| 437 |
"summary": "Providers and deployers take measures so their staff using AI have a sufficient level of AI literacy.",
|
| 438 |
+
"auditor_looks_for": [
|
| 439 |
+
"AI training for staff who use AI tools"
|
| 440 |
+
],
|
| 441 |
+
"endpoint_relevance": "AI tools found on endpoints show who needs AI literacy training."
|
| 442 |
+
},
|
| 443 |
+
{
|
| 444 |
+
"id": "Art. 5",
|
| 445 |
+
"framework": "EU AI Act",
|
| 446 |
+
"title": "Prohibited AI practices",
|
| 447 |
"summary": "Certain AI uses are banned, such as emotion recognition at work and in education (with narrow exceptions) and social scoring.",
|
| 448 |
+
"auditor_looks_for": [
|
| 449 |
+
"No AI tools used for banned purposes"
|
| 450 |
+
],
|
| 451 |
+
"endpoint_relevance": "The purpose of each detected AI tool must be checked against the banned list."
|
| 452 |
+
},
|
| 453 |
+
{
|
| 454 |
+
"id": "Art. 6",
|
| 455 |
+
"framework": "EU AI Act",
|
| 456 |
+
"title": "Classification rules for high-risk AI systems",
|
| 457 |
"summary": "An AI system is high-risk if it is a safety component of regulated products or is used for a purpose listed in Annex III.",
|
| 458 |
+
"auditor_looks_for": [
|
| 459 |
+
"A risk classification for each AI system in use"
|
| 460 |
+
],
|
| 461 |
+
"endpoint_relevance": "Classification depends on what the tool is used for, not only on which tool it is."
|
| 462 |
+
},
|
| 463 |
+
{
|
| 464 |
+
"id": "Art. 14",
|
| 465 |
+
"framework": "EU AI Act",
|
| 466 |
+
"title": "Human oversight",
|
| 467 |
"summary": "High-risk AI systems must be designed so that people can oversee them effectively.",
|
| 468 |
+
"auditor_looks_for": [
|
| 469 |
+
"Named, trained people overseeing each high-risk AI system"
|
| 470 |
+
],
|
| 471 |
+
"endpoint_relevance": "Applies only when a high-risk AI system is in use."
|
| 472 |
+
},
|
| 473 |
+
{
|
| 474 |
+
"id": "Art. 26",
|
| 475 |
+
"framework": "EU AI Act",
|
| 476 |
+
"title": "Obligations of deployers of high-risk AI systems",
|
| 477 |
"summary": "Deployers must use high-risk AI as instructed, assign human oversight, monitor it, keep logs and inform affected people.",
|
| 478 |
+
"auditor_looks_for": [
|
| 479 |
+
"An AI register",
|
| 480 |
+
"Use according to instructions",
|
| 481 |
+
"Monitoring and log retention"
|
| 482 |
+
],
|
| 483 |
+
"endpoint_relevance": "The AI software inventory is the starting point for these duties."
|
| 484 |
+
},
|
| 485 |
+
{
|
| 486 |
+
"id": "Art. 26(6)",
|
| 487 |
+
"framework": "EU AI Act",
|
| 488 |
+
"title": "Deployers: keep automatically generated logs for at least six months",
|
| 489 |
"summary": "Deployers keep the logs a high-risk AI system generates, under their control, for at least six months unless other law says otherwise.",
|
| 490 |
+
"auditor_looks_for": [
|
| 491 |
+
"Log retention of at least six months for high-risk AI systems"
|
| 492 |
+
],
|
| 493 |
+
"endpoint_relevance": "Only applies if a detected AI tool is used in a high-risk way."
|
| 494 |
+
},
|
| 495 |
+
{
|
| 496 |
+
"id": "Art. 50",
|
| 497 |
+
"framework": "EU AI Act",
|
| 498 |
+
"title": "Transparency obligations for providers and deployers of certain AI systems",
|
| 499 |
"summary": "People must be told when they interact with an AI system, and deepfakes and certain AI-generated text must be disclosed.",
|
| 500 |
+
"auditor_looks_for": [
|
| 501 |
+
"Disclosure practices for chatbots and AI-generated content"
|
| 502 |
+
],
|
| 503 |
+
"endpoint_relevance": "Staff publishing AI-generated content need clear rules."
|
| 504 |
+
},
|
| 505 |
+
{
|
| 506 |
+
"id": "Annex III",
|
| 507 |
+
"framework": "EU AI Act",
|
| 508 |
+
"title": "High-risk AI systems referred to in Article 6(2)",
|
| 509 |
"summary": "Lists high-risk uses such as biometrics, critical infrastructure, education, employment and worker management, access to essential services, law enforcement, migration and justice.",
|
| 510 |
+
"auditor_looks_for": [
|
| 511 |
+
"No unassessed use of AI for employment decisions, credit scoring or similar Annex III purposes"
|
| 512 |
+
],
|
| 513 |
+
"endpoint_relevance": "A general AI assistant becomes high-risk if used, for example, to screen job applicants."
|
| 514 |
+
},
|
| 515 |
+
{
|
| 516 |
+
"id": "A.5.32",
|
| 517 |
+
"framework": "ISO 27001:2022",
|
| 518 |
+
"title": "Intellectual property rights",
|
| 519 |
+
"summary": "Protect intellectual property rights and use only properly licensed software.",
|
| 520 |
+
"auditor_looks_for": [
|
| 521 |
+
"A software licence register",
|
| 522 |
+
"No pirated software, activation cracks or unlicensed copies on devices"
|
| 523 |
+
],
|
| 524 |
+
"endpoint_relevance": "Torrent clients and activation cracks on a device point to unlicensed software and a weak software-installation control."
|
| 525 |
+
}
|
| 526 |
]
|
| 527 |
}
|
library/fixes.json
CHANGED
|
@@ -3,73 +3,244 @@
|
|
| 3 |
"note": "Fixes Arx can apply or guide. kind 'auto': applied by collectors/<os>/fix.sh after the user clicks Fix and approves the administrator prompt; the old value is saved so it can be undone. kind 'settings': Arx opens the exact settings page and shows the steps (the change needs the user's password, a recovery key, a restart or a decision). The AI never writes or chooses commands; it may only explain these entries.",
|
| 4 |
"fixes": {
|
| 5 |
"firewall.enabled": {
|
| 6 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
},
|
| 8 |
"firewall.inbound": {
|
| 9 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
},
|
| 11 |
"malware.service": {
|
| 12 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
},
|
| 14 |
"malware.signatures": {
|
| 15 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
},
|
| 17 |
"malware.signature_updates": {
|
| 18 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
},
|
| 20 |
"gdpr.auto_updates": {
|
| 21 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
},
|
| 23 |
"gdpr.guest_account": {
|
| 24 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
},
|
| 26 |
"gdpr.telemetry": {
|
| 27 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
},
|
| 29 |
"gdpr.time_sync": {
|
| 30 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
},
|
| 32 |
"screen_lock.enabled": {
|
| 33 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
},
|
| 35 |
"screen_lock.timeout": {
|
| 36 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
},
|
| 38 |
"screen_lock.password": {
|
| 39 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
},
|
| 41 |
"encryption.enabled": {
|
| 42 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
},
|
| 44 |
"encryption.protection": {
|
| 45 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
},
|
| 47 |
"encryption.recovery": {
|
| 48 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
},
|
| 50 |
"vuln.pending_updates": {
|
| 51 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
},
|
| 53 |
"gdpr.updates_recent": {
|
| 54 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
},
|
| 56 |
"gdpr.os_supported": {
|
| 57 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
},
|
| 59 |
"gdpr.remote_access": {
|
| 60 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
},
|
| 62 |
"gdpr.backup_configured": {
|
| 63 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
},
|
| 65 |
"gdpr.backup_recent": {
|
| 66 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
},
|
| 68 |
"user.account_type": {
|
| 69 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
},
|
| 71 |
"admin.unauthorized": {
|
| 72 |
-
"macos": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
}
|
| 74 |
}
|
| 75 |
}
|
|
|
|
| 3 |
"note": "Fixes Arx can apply or guide. kind 'auto': applied by collectors/<os>/fix.sh after the user clicks Fix and approves the administrator prompt; the old value is saved so it can be undone. kind 'settings': Arx opens the exact settings page and shows the steps (the change needs the user's password, a recovery key, a restart or a decision). The AI never writes or chooses commands; it may only explain these entries.",
|
| 4 |
"fixes": {
|
| 5 |
"firewall.enabled": {
|
| 6 |
+
"macos": {
|
| 7 |
+
"kind": "auto",
|
| 8 |
+
"title": "Turn on the firewall",
|
| 9 |
+
"changes": "Turns on the macOS firewall, which blocks unwanted incoming connections.",
|
| 10 |
+
"note": "Apps you already allowed keep working.",
|
| 11 |
+
"undo": true
|
| 12 |
+
}
|
| 13 |
},
|
| 14 |
"firewall.inbound": {
|
| 15 |
+
"macos": {
|
| 16 |
+
"kind": "auto",
|
| 17 |
+
"title": "Turn on the firewall and stealth mode",
|
| 18 |
+
"changes": "Turns on the firewall and stealth mode, so the Mac does not answer probes from other computers on the network.",
|
| 19 |
+
"note": "Other computers can no longer ping this Mac.",
|
| 20 |
+
"undo": true
|
| 21 |
+
}
|
| 22 |
},
|
| 23 |
"malware.service": {
|
| 24 |
+
"macos": {
|
| 25 |
+
"kind": "auto",
|
| 26 |
+
"title": "Turn on Gatekeeper",
|
| 27 |
+
"changes": "Turns on Gatekeeper, so only apps from the App Store and identified developers can open.",
|
| 28 |
+
"note": "XProtect is always on and cannot be switched by a command.",
|
| 29 |
+
"undo": true
|
| 30 |
+
}
|
| 31 |
},
|
| 32 |
"malware.signatures": {
|
| 33 |
+
"macos": {
|
| 34 |
+
"kind": "auto",
|
| 35 |
+
"title": "Update malware definitions",
|
| 36 |
+
"changes": "Installs the latest XProtect malware definitions from Apple.",
|
| 37 |
+
"note": "An update: there is nothing to undo.",
|
| 38 |
+
"undo": false
|
| 39 |
+
}
|
| 40 |
},
|
| 41 |
"malware.signature_updates": {
|
| 42 |
+
"macos": {
|
| 43 |
+
"kind": "auto",
|
| 44 |
+
"title": "Install security responses automatically",
|
| 45 |
+
"changes": "Turns on 'Install Security Responses and system files' in Software Update, so malware definitions stay current.",
|
| 46 |
+
"note": "",
|
| 47 |
+
"undo": true
|
| 48 |
+
}
|
| 49 |
},
|
| 50 |
"gdpr.auto_updates": {
|
| 51 |
+
"macos": {
|
| 52 |
+
"kind": "auto",
|
| 53 |
+
"title": "Turn on automatic updates",
|
| 54 |
+
"changes": "Turns on checking for, downloading and installing macOS updates and security responses automatically.",
|
| 55 |
+
"note": "macOS may restart overnight to finish an update; it warns first.",
|
| 56 |
+
"undo": true
|
| 57 |
+
}
|
| 58 |
},
|
| 59 |
"gdpr.guest_account": {
|
| 60 |
+
"macos": {
|
| 61 |
+
"kind": "auto",
|
| 62 |
+
"title": "Turn off the guest account",
|
| 63 |
+
"changes": "Turns off guest login and guest access to shared folders.",
|
| 64 |
+
"note": "",
|
| 65 |
+
"undo": true
|
| 66 |
+
}
|
| 67 |
},
|
| 68 |
"gdpr.telemetry": {
|
| 69 |
+
"macos": {
|
| 70 |
+
"kind": "auto",
|
| 71 |
+
"title": "Stop sharing analytics",
|
| 72 |
+
"changes": "Turns off 'Share Mac Analytics' and 'Share with app developers'.",
|
| 73 |
+
"note": "",
|
| 74 |
+
"undo": true
|
| 75 |
+
}
|
| 76 |
},
|
| 77 |
"gdpr.time_sync": {
|
| 78 |
+
"macos": {
|
| 79 |
+
"kind": "auto",
|
| 80 |
+
"title": "Set the time automatically",
|
| 81 |
+
"changes": "Turns on 'Set time and date automatically' from Apple's time server, so logs have correct times.",
|
| 82 |
+
"note": "",
|
| 83 |
+
"undo": true
|
| 84 |
+
}
|
| 85 |
},
|
| 86 |
"screen_lock.enabled": {
|
| 87 |
+
"macos": {
|
| 88 |
+
"kind": "settings",
|
| 89 |
+
"title": "Turn on the screen lock",
|
| 90 |
+
"url": "x-apple.systempreferences:com.apple.Lock-Screen-Settings.extension",
|
| 91 |
+
"steps": [
|
| 92 |
+
"Set 'Start Screen Saver when inactive' and 'Turn display off when inactive' to 5 minutes or less.",
|
| 93 |
+
"Set 'Require password after screen saver begins or display is turned off' to Immediately."
|
| 94 |
+
]
|
| 95 |
+
}
|
| 96 |
},
|
| 97 |
"screen_lock.timeout": {
|
| 98 |
+
"macos": {
|
| 99 |
+
"kind": "settings",
|
| 100 |
+
"title": "Lock the screen sooner",
|
| 101 |
+
"url": "x-apple.systempreferences:com.apple.Lock-Screen-Settings.extension",
|
| 102 |
+
"steps": [
|
| 103 |
+
"Set 'Start Screen Saver when inactive' and 'Turn display off when inactive' to 5 minutes or less.",
|
| 104 |
+
"Set 'Require password after screen saver begins or display is turned off' to Immediately."
|
| 105 |
+
]
|
| 106 |
+
}
|
| 107 |
},
|
| 108 |
"screen_lock.password": {
|
| 109 |
+
"macos": {
|
| 110 |
+
"kind": "settings",
|
| 111 |
+
"title": "Ask for the password straight away",
|
| 112 |
+
"url": "x-apple.systempreferences:com.apple.Lock-Screen-Settings.extension",
|
| 113 |
+
"steps": [
|
| 114 |
+
"Set 'Require password after screen saver begins or display is turned off' to Immediately (macOS asks for your password)."
|
| 115 |
+
]
|
| 116 |
+
}
|
| 117 |
},
|
| 118 |
"encryption.enabled": {
|
| 119 |
+
"macos": {
|
| 120 |
+
"kind": "settings",
|
| 121 |
+
"title": "Turn on FileVault",
|
| 122 |
+
"url": "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?FileVault",
|
| 123 |
+
"steps": [
|
| 124 |
+
"Scroll to FileVault and click Turn On.",
|
| 125 |
+
"Choose how to unlock the disk if you forget your password, and keep the recovery key somewhere safe (not on this Mac): without it, data can be lost.",
|
| 126 |
+
"Encryption continues in the background; you can keep working."
|
| 127 |
+
]
|
| 128 |
+
}
|
| 129 |
},
|
| 130 |
"encryption.protection": {
|
| 131 |
+
"macos": {
|
| 132 |
+
"kind": "settings",
|
| 133 |
+
"title": "Finish disk encryption",
|
| 134 |
+
"url": "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?FileVault",
|
| 135 |
+
"steps": [
|
| 136 |
+
"Check that FileVault is on. If encryption is in progress, keep the Mac on power until it finishes."
|
| 137 |
+
]
|
| 138 |
+
}
|
| 139 |
},
|
| 140 |
"encryption.recovery": {
|
| 141 |
+
"macos": {
|
| 142 |
+
"kind": "settings",
|
| 143 |
+
"title": "Set up a recovery key",
|
| 144 |
+
"url": "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?FileVault",
|
| 145 |
+
"steps": [
|
| 146 |
+
"Turn FileVault on (or off and on again) and choose 'Create a recovery key'.",
|
| 147 |
+
"Store the key somewhere safe outside this Mac, or let your IT team escrow it."
|
| 148 |
+
]
|
| 149 |
+
}
|
| 150 |
},
|
| 151 |
"vuln.pending_updates": {
|
| 152 |
+
"macos": {
|
| 153 |
+
"kind": "settings",
|
| 154 |
+
"title": "Install pending updates",
|
| 155 |
+
"url": "x-apple.systempreferences:com.apple.Software-Update-Settings.extension",
|
| 156 |
+
"steps": [
|
| 157 |
+
"Click Update Now (or Restart Now). Save your work first: the Mac may restart."
|
| 158 |
+
]
|
| 159 |
+
}
|
| 160 |
},
|
| 161 |
"gdpr.updates_recent": {
|
| 162 |
+
"macos": {
|
| 163 |
+
"kind": "settings",
|
| 164 |
+
"title": "Install the latest updates",
|
| 165 |
+
"url": "x-apple.systempreferences:com.apple.Software-Update-Settings.extension",
|
| 166 |
+
"steps": [
|
| 167 |
+
"Click Update Now. Save your work first: the Mac may restart."
|
| 168 |
+
]
|
| 169 |
+
}
|
| 170 |
},
|
| 171 |
"gdpr.os_supported": {
|
| 172 |
+
"macos": {
|
| 173 |
+
"kind": "settings",
|
| 174 |
+
"title": "Upgrade macOS",
|
| 175 |
+
"url": "x-apple.systempreferences:com.apple.Software-Update-Settings.extension",
|
| 176 |
+
"steps": [
|
| 177 |
+
"Install the offered macOS upgrade. Back up first, and check that your apps support it."
|
| 178 |
+
]
|
| 179 |
+
}
|
| 180 |
},
|
| 181 |
"gdpr.remote_access": {
|
| 182 |
+
"macos": {
|
| 183 |
+
"kind": "settings",
|
| 184 |
+
"title": "Turn off remote access you do not need",
|
| 185 |
+
"url": "x-apple.systempreferences:com.apple.Sharing-Settings.extension",
|
| 186 |
+
"steps": [
|
| 187 |
+
"Turn off Screen Sharing, Remote Login, Remote Management and File Sharing unless your IT team needs them.",
|
| 188 |
+
"Quit and uninstall remote tools such as TeamViewer or AnyDesk if they are not approved."
|
| 189 |
+
]
|
| 190 |
+
}
|
| 191 |
},
|
| 192 |
"gdpr.backup_configured": {
|
| 193 |
+
"macos": {
|
| 194 |
+
"kind": "settings",
|
| 195 |
+
"title": "Set up Time Machine",
|
| 196 |
+
"url": "x-apple.systempreferences:com.apple.Time-Machine-Settings.extension",
|
| 197 |
+
"steps": [
|
| 198 |
+
"Connect an external drive or choose a network backup disk, then click Add Backup Disk.",
|
| 199 |
+
"Choose 'Encrypt backups'."
|
| 200 |
+
]
|
| 201 |
+
}
|
| 202 |
},
|
| 203 |
"gdpr.backup_recent": {
|
| 204 |
+
"macos": {
|
| 205 |
+
"kind": "settings",
|
| 206 |
+
"title": "Back up now",
|
| 207 |
+
"url": "x-apple.systempreferences:com.apple.Time-Machine-Settings.extension",
|
| 208 |
+
"steps": [
|
| 209 |
+
"Connect the backup disk and choose Back Up Now."
|
| 210 |
+
]
|
| 211 |
+
}
|
| 212 |
},
|
| 213 |
"user.account_type": {
|
| 214 |
+
"macos": {
|
| 215 |
+
"kind": "settings",
|
| 216 |
+
"title": "Use a standard account for everyday work",
|
| 217 |
+
"url": "x-apple.systempreferences:com.apple.Users-Groups-Settings.extension",
|
| 218 |
+
"steps": [
|
| 219 |
+
"Create a separate administrator account for installing software.",
|
| 220 |
+
"Then turn off 'Allow this user to administer this computer' for your everyday account. Do this only after the other administrator account works."
|
| 221 |
+
]
|
| 222 |
+
}
|
| 223 |
},
|
| 224 |
"admin.unauthorized": {
|
| 225 |
+
"macos": {
|
| 226 |
+
"kind": "settings",
|
| 227 |
+
"title": "Review administrator accounts",
|
| 228 |
+
"url": "x-apple.systempreferences:com.apple.Users-Groups-Settings.extension",
|
| 229 |
+
"steps": [
|
| 230 |
+
"Turn off 'Allow this user to administer this computer' for accounts that are not approved IT administrators. Keep at least one working administrator."
|
| 231 |
+
]
|
| 232 |
+
}
|
| 233 |
+
},
|
| 234 |
+
"account.unique_login": {
|
| 235 |
+
"macos": {
|
| 236 |
+
"kind": "settings",
|
| 237 |
+
"title": "Turn off automatic login and shared accounts",
|
| 238 |
+
"url": "x-apple.systempreferences:com.apple.Users-Groups-Settings.extension",
|
| 239 |
+
"steps": [
|
| 240 |
+
"Set 'Automatically log in as' to Off (at the bottom of the page).",
|
| 241 |
+
"Give each person their own account; remove or rename shared accounts such as office or admin, keeping one named IT administrator."
|
| 242 |
+
]
|
| 243 |
+
}
|
| 244 |
}
|
| 245 |
}
|
| 246 |
}
|
site/site.js
CHANGED
|
@@ -271,6 +271,7 @@ function handedOverReport() {
|
|
| 271 |
async function init() {
|
| 272 |
initDevice(); initDownloads();
|
| 273 |
try { await loadLibrary(); } catch (e) { $('checkCount').textContent = 'Could not load the check list.'; console.warn(e); return; }
|
|
|
|
| 274 |
renderRail(); renderFilters(); renderTable();
|
| 275 |
const showHandedOver = () => { const ev = handedOverReport(); if (ev) { history.replaceState(null, '', location.pathname); showResults(ev); } };
|
| 276 |
showHandedOver();
|
|
|
|
| 271 |
async function init() {
|
| 272 |
initDevice(); initDownloads();
|
| 273 |
try { await loadLibrary(); } catch (e) { $('checkCount').textContent = 'Could not load the check list.'; console.warn(e); return; }
|
| 274 |
+
document.querySelectorAll('[data-count]').forEach(el => { el.textContent = state.checks.length; });
|
| 275 |
renderRail(); renderFilters(); renderTable();
|
| 276 |
const showHandedOver = () => { const ev = handedOverReport(); if (ev) { history.replaceState(null, '', location.pathname); showResults(ev); } };
|
| 277 |
showHandedOver();
|
synthetic/generate_evidence.py
CHANGED
|
@@ -39,20 +39,20 @@ ORDER = {
|
|
| 39 |
"firewall.private.enabled", "firewall.private.inbound", "firewall.private.outbound",
|
| 40 |
"firewall.public.enabled", "firewall.public.inbound", "firewall.public.outbound",
|
| 41 |
"screen_lock.enabled", "screen_lock.timeout", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 42 |
-
"admin.approved", "admin.unauthorized", "user.account_type",
|
| 43 |
-
"encryption.feature", "encryption.enabled", "encryption.protection", "encryption.recovery", "vuln.pending_updates", "vuln.outdated_apps", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 44 |
"linux": PASSWORD_LOCKOUT + [
|
| 45 |
-
"malware.antivirus", "malware.service", "malware.signature_updates", "malware.signatures", "malware.on_access",
|
| 46 |
"firewall.enabled", "firewall.inbound", "firewall.outbound",
|
| 47 |
"screen_lock.enabled", "screen_lock.timeout", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 48 |
-
"admin.approved", "admin.unauthorized", "user.account_type", "encryption.enabled", "encryption.protection", "encryption.recovery",
|
| 49 |
-
"vuln.pending_updates", "vuln.outdated_apps", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 50 |
"macos": PASSWORD_LOCKOUT + [
|
| 51 |
-
"malware.antivirus", "malware.service", "malware.signatures", "malware.signature_updates", "malware.on_access",
|
| 52 |
"firewall.enabled", "firewall.inbound", "firewall.outbound",
|
| 53 |
"screen_lock.timeout", "screen_lock.enabled", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 54 |
-
"admin.approved", "admin.unauthorized", "user.account_type", "encryption.enabled", "encryption.protection", "encryption.recovery",
|
| 55 |
-
"vuln.pending_updates", "vuln.outdated_apps", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 56 |
}
|
| 57 |
# Checks that report Error when the collector is not run as administrator/root.
|
| 58 |
NEEDS_ADMIN = {
|
|
@@ -338,6 +338,18 @@ class Device:
|
|
| 338 |
return ("NotApplicable", "XProtect only", "on-access scanning", "XProtect scans at launch and download; macOS has no built-in on-access scanning.")
|
| 339 |
|
| 340 |
def c_malware_tamper(self):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
if self.third_party_av:
|
| 342 |
return self._defender_na("on")
|
| 343 |
ok = self.good()
|
|
@@ -567,7 +579,7 @@ class Device:
|
|
| 567 |
if self.os != "windows":
|
| 568 |
self._enc = self.good(0.05)
|
| 569 |
if self.os == "windows":
|
| 570 |
-
return self.result(self._enc, "FullyEncrypted (100%)" if self._enc else self.pick(["FullyDecrypted (0%)", "EncryptionInProgress (42%)"]), "fully encrypted")
|
| 571 |
if self.os == "linux":
|
| 572 |
return self.result(self._enc, "root filesystem on LUKS (dm_crypt-0)" if self._enc else "root filesystem not encrypted", "system disk encrypted")
|
| 573 |
return self.result(self._enc, "FileVault on" if self._enc else "FileVault off", "FileVault on")
|
|
@@ -608,6 +620,22 @@ class Device:
|
|
| 608 |
return ("Compliant", f"Standard ({shown})", "Standard", "")
|
| 609 |
return ("Non-Compliant", f"Administrator ({shown})", "Standard", "The signed-in user is a member of the administrators group.")
|
| 610 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
def c_vuln_pending_updates(self):
|
| 612 |
limit = self.n("MAX_PENDING_SECURITY_UPDATES")
|
| 613 |
expected = f"<= {limit} pending"
|
|
@@ -683,6 +711,19 @@ class Device:
|
|
| 683 |
rows.append(f"{name} {WINGET_IDS[name]} {a}.{self.rng.randint(0, 9)}.{self.rng.randint(0, 999)} {a + self.pick([0, 1])}.{self.rng.randint(0, 9)}.{self.rng.randint(0, 999)} winget")
|
| 684 |
return ("Non-Compliant", f"{len(rows)} outdated", expected, "; ".join(rows[:5]) + ".")
|
| 685 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 686 |
def c_vuln_known_vulnerabilities(self):
|
| 687 |
"""Builds a realistic software inventory; the real matcher fills in the result (see VULN_JOBS)."""
|
| 688 |
expected = f"<= {self.n('MAX_CRITICAL_HIGH_VULNERABILITIES')} critical/high"
|
|
|
|
| 39 |
"firewall.private.enabled", "firewall.private.inbound", "firewall.private.outbound",
|
| 40 |
"firewall.public.enabled", "firewall.public.inbound", "firewall.public.outbound",
|
| 41 |
"screen_lock.enabled", "screen_lock.timeout", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 42 |
+
"admin.approved", "admin.unauthorized", "user.account_type", "account.unique_login",
|
| 43 |
+
"encryption.feature", "encryption.enabled", "encryption.protection", "encryption.recovery", "vuln.pending_updates", "vuln.outdated_apps", "software.prohibited", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 44 |
"linux": PASSWORD_LOCKOUT + [
|
| 45 |
+
"malware.antivirus", "malware.service", "malware.signature_updates", "malware.signatures", "malware.on_access", "malware.tamper",
|
| 46 |
"firewall.enabled", "firewall.inbound", "firewall.outbound",
|
| 47 |
"screen_lock.enabled", "screen_lock.timeout", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 48 |
+
"admin.approved", "admin.unauthorized", "user.account_type", "account.unique_login", "encryption.enabled", "encryption.protection", "encryption.recovery",
|
| 49 |
+
"vuln.pending_updates", "vuln.outdated_apps", "software.prohibited", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 50 |
"macos": PASSWORD_LOCKOUT + [
|
| 51 |
+
"malware.antivirus", "malware.service", "malware.signatures", "malware.signature_updates", "malware.on_access", "malware.tamper",
|
| 52 |
"firewall.enabled", "firewall.inbound", "firewall.outbound",
|
| 53 |
"screen_lock.timeout", "screen_lock.enabled", "screen_lock.password", "usb.device_access", "usb.read", "usb.write",
|
| 54 |
+
"admin.approved", "admin.unauthorized", "user.account_type", "account.unique_login", "encryption.enabled", "encryption.protection", "encryption.recovery",
|
| 55 |
+
"vuln.pending_updates", "vuln.outdated_apps", "software.prohibited", "vuln.known_vulnerabilities"] + GDPR + AIACT + ORG,
|
| 56 |
}
|
| 57 |
# Checks that report Error when the collector is not run as administrator/root.
|
| 58 |
NEEDS_ADMIN = {
|
|
|
|
| 338 |
return ("NotApplicable", "XProtect only", "on-access scanning", "XProtect scans at launch and download; macOS has no built-in on-access scanning.")
|
| 339 |
|
| 340 |
def c_malware_tamper(self):
|
| 341 |
+
if self.os == "macos": # System Integrity Protection (csrutil status)
|
| 342 |
+
if self.good(0.2):
|
| 343 |
+
return ("Compliant", "System Integrity Protection on", "on", "")
|
| 344 |
+
state = self.pick(["disabled", "unknown (Custom Configuration)"])
|
| 345 |
+
return ("Non-Compliant", f"System Integrity Protection {state.split(' ')[0]}", "on", f"System Integrity Protection status: {state}.")
|
| 346 |
+
if self.os == "linux": # an enforcing security module; Secure Boot for information
|
| 347 |
+
expected = "SELinux or AppArmor enforcing"
|
| 348 |
+
sb = self.pick(["", "Secure Boot: SecureBoot enabled", "Secure Boot: SecureBoot disabled"])
|
| 349 |
+
if self.good(0.1):
|
| 350 |
+
lsm = "SELinux enforcing" if self.distro == "rhel" else f"AppArmor enforcing ({self.rng.randint(30, 140)} profiles)"
|
| 351 |
+
return ("Compliant", lsm, expected, sb)
|
| 352 |
+
return ("Non-Compliant", "no security module enforcing", expected, sb)
|
| 353 |
if self.third_party_av:
|
| 354 |
return self._defender_na("on")
|
| 355 |
ok = self.good()
|
|
|
|
| 579 |
if self.os != "windows":
|
| 580 |
self._enc = self.good(0.05)
|
| 581 |
if self.os == "windows":
|
| 582 |
+
return self.result(self._enc, "BitLocker: FullyEncrypted (100%)" if self._enc else self.pick(["BitLocker: FullyDecrypted (0%)", "BitLocker: EncryptionInProgress (42%)"]), "fully encrypted")
|
| 583 |
if self.os == "linux":
|
| 584 |
return self.result(self._enc, "root filesystem on LUKS (dm_crypt-0)" if self._enc else "root filesystem not encrypted", "system disk encrypted")
|
| 585 |
return self.result(self._enc, "FileVault on" if self._enc else "FileVault off", "FileVault on")
|
|
|
|
| 620 |
return ("Compliant", f"Standard ({shown})", "Standard", "")
|
| 621 |
return ("Non-Compliant", f"Administrator ({shown})", "Standard", "The signed-in user is a member of the administrators group.")
|
| 622 |
|
| 623 |
+
def c_account_unique_login(self):
|
| 624 |
+
expected = "personal accounts, no automatic login"
|
| 625 |
+
if self.good(0.05):
|
| 626 |
+
return ("Compliant", expected, expected, "")
|
| 627 |
+
shared = [n.strip() for n in self.b("SHARED_ACCOUNT_NAMES").split(",") if n.strip()] or ["office"]
|
| 628 |
+
names = sorted(self.rng.sample([n for n in shared if n not in ("administrator",)] or shared, self.rng.choice([1, 1, 2])))
|
| 629 |
+
if self.os == "windows":
|
| 630 |
+
names = [n.capitalize() for n in names]
|
| 631 |
+
issues = []
|
| 632 |
+
kind = self.pick(["auto", "generic", "both"])
|
| 633 |
+
if kind in ("auto", "both"):
|
| 634 |
+
issues.append(f"automatic login as {names[0] if kind == 'both' else self._desktop_users().split(', ')[0]}")
|
| 635 |
+
if kind in ("generic", "both"):
|
| 636 |
+
issues.append(f"shared or generic accounts: {', '.join(names)}")
|
| 637 |
+
return ("Non-Compliant", "; ".join(issues), expected, "")
|
| 638 |
+
|
| 639 |
def c_vuln_pending_updates(self):
|
| 640 |
limit = self.n("MAX_PENDING_SECURITY_UPDATES")
|
| 641 |
expected = f"<= {limit} pending"
|
|
|
|
| 711 |
rows.append(f"{name} {WINGET_IDS[name]} {a}.{self.rng.randint(0, 9)}.{self.rng.randint(0, 999)} {a + self.pick([0, 1])}.{self.rng.randint(0, 9)}.{self.rng.randint(0, 999)} winget")
|
| 712 |
return ("Non-Compliant", f"{len(rows)} outdated", expected, "; ".join(rows[:5]) + ".")
|
| 713 |
|
| 714 |
+
def c_software_prohibited(self):
|
| 715 |
+
listed = self.b("PROHIBITED_SOFTWARE")
|
| 716 |
+
if not listed:
|
| 717 |
+
return ("Compliant", "no list configured", "none of: (empty list)", "PROHIBITED_SOFTWARE in baseline.conf is empty.")
|
| 718 |
+
expected = f"none of: {listed}"
|
| 719 |
+
if self.good(0.12):
|
| 720 |
+
n = self.rng.randint(18, 140)
|
| 721 |
+
return ("Compliant", {"macos": f"none found in {n} applications", "windows": f"none found in {n} programs", "linux": "none found"}[self.os], expected, "")
|
| 722 |
+
found = {"macos": [["Transmission"], ["qBittorrent"], ["Deluge"], ["FrostWire"], ["Transmission", "qBittorrent"]],
|
| 723 |
+
"windows": [["µTorrent"], ["BitTorrent"], ["qBittorrent v4.6.2"], ["KMSpico 10.2.0"], ["KMSAuto Net"], ["µTorrent", "KMSpico 10.2.0"]],
|
| 724 |
+
"linux": [["transmission-gtk", "transmission-common"], ["qbittorrent"], ["deluge", "deluge-gtk"], ["ktorrent"]]}[self.os]
|
| 725 |
+
return ("Non-Compliant", ", ".join(self.pick(found)), expected, "")
|
| 726 |
+
|
| 727 |
def c_vuln_known_vulnerabilities(self):
|
| 728 |
"""Builds a realistic software inventory; the real matcher fills in the result (see VULN_JOBS)."""
|
| 729 |
expected = f"<= {self.n('MAX_CRITICAL_HIGH_VULNERABILITIES')} critical/high"
|