Both recommendations are Manual, so they belong in the manual
supplementals rather than the cis_lvl1/cis_lvl2 baselines. The rules
keep their STIG and NIST tags.
2.9.1 Ensure Help Apple Improve Search Is Disabled is Manual in Sequoia
v2.1.0 and Automated in Tahoe v1.1.0. Remove the macOS 15 citation and
macOS 15 cis_lvl1/cis_lvl2 membership from
system_settings_improve_search_disable and list 2.9.1 in the macOS 15
supplemental. macOS 26 and 27 are unchanged.
2.3.5.1 Ensure 'allowUIConfigurationProfileInstallation' Is Set to
Disabled is Manual, level 2 in the Tahoe v2.0 and Golden Gate 27 v1.0
drafts, both expected to be published in October or November 2026.
Remove the macOS 26 and 27 citations and cis_lvl2 membership from
os_install_configuration_profile_disable, and list 2.3.5.1 in the
macOS 26 supplemental alongside the macOS 27 one.
cis_lvl2_macos_27 drops os_install_configuration_profile_disable.
Checked against Sequoia v2.1.0.
os_sleep_and_display_sleep_apple_silicon_enable cited 2.10.1.1, the
Intel recommendation, which is Manual. The Apple Silicon recommendation
the rule implements is 2.10.1.2, Automated, level 2, matching the macOS
26 citation. Golden Gate collapses the pair to a flat 2.10.1 because
macOS 27 drops Intel, which the macOS 27 citation already reflects.
os_mdm_require cited 1.8, which appears in no benchmark at any version.
Remove the citations and the macOS 15 cis_lvl1/cis_lvl2 membership that
depended on them.
system_settings_hot_corners_secure cited 2.7.1 as level 2, but Sequoia
lists it under Level 1, so its '15.0' block was in cis_lvl2 only.
Correct the level and add cis_lvl1, matching macOS 26 and 27.
system_settings_screensaver_password_enforce had no macOS 15 citation.
Sequoia 2.11.2 audits askForPassword as well as askForPasswordDelay,
and both rules already cite 2.11.2 for macOS 26 and 27. Add the macOS
15 citation and cis_lvl1/cis_lvl2 membership.
The macOS 15 citations in section 1 carried Sonoma v3.1.0 numbering.
Sonoma's 1.2 Ensure Auto Update Is Enabled was dropped in Sequoia
v2.1.0, and every later recommendation moved up one. Each copied number
still exists in Sequoia, is Automated and is level 1, so the citations
pointed at the wrong control without failing any structural check.
Matched by the key each Sequoia recommendation audits:
1.2 AutomaticDownload software_update_download_enforce 1.3 -> 1.2
1.3 AutomaticallyInstallMacOSUpdates install_macos_updates_enforce 1.4 -> 1.3
1.4 AutomaticallyInstallAppUpdates software_update_app_update_enforce 1.5 -> 1.4
1.5 CriticalUpdateInstall critical_update_install_enforce 1.6 -> 1.5
1.5 ConfigDataInstall os_config_data_install_enforce 1.6 -> 1.5
1.6 enforcedSoftwareUpdateDelay os_software_update_deferral 1.7 -> 1.6
The macOS 26 and 27 citations already use these numbers.
system_settings_software_update_enforce checks AutomaticCheckEnabled,
which no Sequoia or Tahoe recommendation audits. Remove its macOS 15
citation and its macOS 15 cis_lvl1/cis_lvl2 membership. It already had
no macOS 26 or 27 citation.
CIS 2.4.1 Audit Menu Bar and Control Center Icons replaces the separate
Wi-Fi and Bluetooth menu recommendations. It is a manual check that the
items allowed in the menu bar match organizational policy, and it is
Manual in Sequoia v2.1.0, Tahoe v1.1.0, and the Tahoe v2.0 and Golden
Gate 27 drafts.
system_settings_wifi_menu_enable cited 2.4.1 directly.
system_settings_bluetooth_menu_enable cited 2.4.2, which no longer
exists in any benchmark. Neither rule carried a non-CIS tag and neither
was in cis_lvl1 or cis_lvl2, so removing them loses no other coverage.
2.4.1 is listed in the manual supplementals for macOS 15, 26 and 27.
cisv8_macos_27 and all_rules_macos_27 each drop
system_settings_bluetooth_menu_enable. The CIS baselines are unchanged.
The per-version files were seeded from supplemental_cis_manual.yaml
before PR #781's corrections to it merged, so those corrections reached
supplemental_cis_manual_27 but not these two. Checked against Sequoia
v2.1.0 and Tahoe v1.1.0.
Both files:
- Remove 5.3.1 and 5.3.2. They are Automated, level 1, and implemented
by os_internal_apfs_volumes_encrypted and os_external_apfs_hfs_
volumes_encrypted on macOS 15, 26 and 27.
- Add 5.3.3 Audit Connected FAT32 and ExFAT Drives, which is Manual.
- Use the published titles for 2.1.1.1, 2.5.2.2 and 2.15.1.
macOS 15 only:
- Add 2.4.1 Audit Menu Bar and Control Center Icons, which is Manual.
- Use the published titles for 2.1.1.4 and 6.5.1, and list 6.5.1 under
Applications as the macOS 26 and 27 files do.
macOS 26 only:
- Remove 1.7. Tahoe v1.1.0 ends at 1.6, and no MDM recommendation
appears in the Sequoia, Tahoe or Golden Gate benchmarks.
5.3.1 Ensure all internal user storage APFS volumes are encrypted and
5.3.2 Ensure all APFS and HFS+ external user storage volumes are
encrypted are Automated, level 1 in Sequoia v2.1.0. Their audit and
remediation commands are identical to Tahoe v1.1.0, which
os_internal_apfs_volumes_encrypted and os_external_apfs_hfs_volumes_
encrypted already implement for macOS 26 and 27.
Add the macOS 15 citations and a '15.0' block in cis_lvl1 and cis_lvl2.
Both rules carry only the cisv8 tag, so no STIG or NIST baseline changes.
CIS does not require the password complexity settings and assesses them
manually. From the Sequoia v2.1.0 benchmark, repeated in Tahoe v1.1.0
and the Golden Gate 27 v1.0 draft:
"The CIS macOS community has decided to not require the additional
password complexity settings (Recommendations 5.3 - 5.6). Because of
that, we have left the complexity recommendations as a manual
assessment."
5.2.3 through 5.2.6 are Manual in every published benchmark and in the
Golden Gate draft, and all four are already listed in the CIS manual
supplementals, so they were counted twice.
Remove the CIS benchmark references, cis_lvl2 membership and CIS ODVs
from pwpolicy_alpha_numeric_enforce, pwpolicy_special_character_enforce
and pwpolicy_custom_regex_enforce. The rules stay: they are required by
800-53r5, 800-171, CMMC, CNSSI-1253, HICP and the DISA STIG. The cisv8
tag and CIS Controls v8 mapping are a separate framework and unchanged.
cis_lvl2_macos_27 drops from 117 to 114 rules. cis_lvl1 is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.2.1 in the CIS Apple macOS 14 Sonoma Benchmark v3.1.0 audits only
policyAttributeMaximumFailedAuthentications, the same as 15 and 26, so
the macos_14 citation on this rule was never accurate either. main has
no macOS 14.0 platform block, so nothing is generated from it.
The sonoma branch keeps its own copy of the rule and is not affected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
os_show_filename_extensions_enable is recommendation 6.1.1, which is
Manual in the CIS Apple macOS Benchmarks for 14 (v3.1.0), 15 (v2.1.0)
and 26 (v1.1.0). Remove the rule and list 6.1.1 in the CIS supplemental
sections instead. supplemental_cis_manual_26 carried a title from a
draft benchmark; align it with the published v1.1.0 wording.
pwpolicy_account_lockout_timeout_enforce is no longer a CIS Benchmark
recommendation. CIS 5.2.1 audits only maxFailedAttempts, covered by
pwpolicy_account_lockout_enforce; neither autoEnableInSeconds nor
minutesUntilFailedLoginReset appears in the macOS 14, 15 or 26
Benchmarks. Drop its cis_lvl1/cis_lvl2 membership, benchmark references
and CIS ODVs for macOS 15, 26 and 27. The cisv8 tag and CIS Controls v8
mapping are a separate framework and are unchanged.
Closes#818
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Commit 78f2fcc9 ("Modified rule files") set out to remove an unnecessary
leading `---` from rule files, but its bulk edit also collapsed the
`----` source block delimiters in nine rules, merging each delimiter
into the line that followed it.
The damage tracks that commit's file batch rather than any content rule:
every one of the nine rules it touched that used `----` lost its
delimiters, while the four untouched rules using the same syntax kept
theirs. The `[source,xml]` and `[source,bash]` attribute lines were left
in place, so this was a side effect rather than a move away from
asciidoc markup; the document renderers still parse these fences.
With the delimiters gone, our own HTML/PDF output drops the opening
`<dict>` of the pwpolicy XML examples, swallows the remediation prose
into the code block, and prints a literal `[source,bash]`. Feeding the
same rules to asciidoctor additionally leaves the discussions' [NOTE]
blocks unterminated, which cascades: generating the macOS 27 hicp_lp
guidance that way loses 43 of its 140 rule headings along with the
Inherent and Permanent Findings sections.
Restore the delimiters so all nine rules match their pre-78f2fcc9 text,
keeping that commit's intended removal of the leading `---`.
Affected rules:
- os_firmware_password_require
- os_show_filename_extensions_enable
- pwpolicy_account_inactivity_enforce
- pwpolicy_force_password_change
- pwpolicy_lower_case_character_enforce
- pwpolicy_minimum_lifetime_enforce
- pwpolicy_upper_case_character_enforce
- system_settings_bluetooth_sharing_disable
- system_settings_hot_corners_secure
resolve_enforcement_info() was treating an OS-version-specific
enforcement_info block as a full replacement of the platform-level
one. That's wrong when the version block only specifies part of it
(e.g. system_settings_screen_sharing_disable's 26.0 override only
redefines fix, and its 15.0 override only redefines check) -- the
unspecified half was being silently dropped instead of falling back
to the platform default.
Merge at the check/fix/default_state level instead: the version
block's keys override the platform default's corresponding keys,
and anything it omits still comes from the platform-level block.
The rule loader, the configuration-profile fix generator, and SCAP/OVAL
generation all read platforms.<os>.enforcement_info directly, ignoring
any more specific platforms.<os>.<version>.enforcement_info block. This
silently discarded per-version checks (e.g. macOS 26.0-specific logic)
in favor of the generic platform-level one, and dropped enforcement
info entirely for rules that only defined it at the version level.
Add resolve_enforcement_info() to prefer the version-specific block
when present, falling back to the platform-level one as the default,
and use it consistently across all three consumers. Also collapse
os_messages_app_disable_familycontrols's identical 15.0/26.0 blocks
into a single platform-level block now that it's redundant.
The macOS 26.0 enforcement_info check was authored as a YAML double-quoted
flow scalar instead of a literal block scalar. That format only preserves
newlines written as explicit \n escapes, and only two survived the
conversion, so the heredoc's internal newlines became spaces:
... << EOS $.NSUserDefaults...('com.apple.SoftwareUpdate')\ .objectForKey(...).js EOS )
A heredoc terminator must be alone on its line, so zsh never finds EOS,
swallows the rest of the script and fails with "parse error near `unset'".
The trailing `\` line-continuation likewise collapsed into `\ `, an escaped
space. The same collapse also folded the conditional onto one line, where
it is missing its `;` separators and so is invalid in any POSIX shell:
if [[ ... ]]; then echo "true" else echo "false" fi
Re-author the check as a `|-` literal block scalar, matching the style of
the sibling 15.0 entry, restoring the heredoc newlines and the line
continuation, and separating the conditional's branches.
The check's intent is unchanged: pass when either the com.apple.SoftwareUpdate
profile sets CriticalUpdateInstall, or DDM reports
automaticallyInstallSystemAndSecurityUpdates, matching `result: string 'true'`.
mSCP's own generator does not surface this, because it reads only the
platform-level enforcement_info (classes/macsecurityrule.py:292) and never
the version-keyed overrides, but the schema declares enforcement_info on
every macOS version key, and consumers that honour it emit a script that
neither zsh nor bash can parse.
Verified: the rule's check.shell now passes `zsh -n` when wrapped as
`result_value=$(<code>\n)`, the file has no schema errors against
schema/mscp_rule.json, and a full sweep of all 407 check/fix shell
snippets in src/mscp/data/rules leaves no syntactically invalid zsh
beyond the pre-existing prose-valued check in os_home_folders_default
(a `manual` rule that is never scripted).