Rule Structure
Learn the mSCP YAML format for writing custom rules.
Required fields, optional fields, and how they all fit together.
Basic Structure
Here's what the Rule Builder generates when you create a new rule:
id: os_example_rule
title: Example Custom Rule
discussion: |
This setting _MUST_ be configured for security.
Explain why this rule matters and what risk it mitigates.
references:
nist:
cce:
macos_15:
- CCE-XXXXX-X
disa:
disa_stig:
macos_15:
- APPL-15-XXXXXX
platforms:
macOS:
'15.0':
benchmarks:
- name: cis_lvl1
enforcement_info:
check:
shell: /usr/bin/defaults read com.example.app Setting
result:
string: 'expected_value'
fix:
shell: /usr/bin/defaults write com.example.app Setting -string 'expected_value'
Required Fields
Unique identifier. Lowercase letters and underscores only. Must match the filename.
Human-readable name shown in the UI and documentation.
Explanation of why the rule exists and what it protects against. Use RFC 2119 keywords: MUST, SHOULD, MAY.
Compliance framework references. The Rule Builder auto-generates nist.cce and disa.disa_stig based on selected versions.
Platform-specific enforcement info including check and fix commands.
Field Details
id
The unique identifier for your rule. The Rule Builder automatically prefixes the ID based on the Category you select:
id: os_chrome_autoupdate_enabled
Category prefixes:
os_- Operating System rulessystem_settings_- System Settings rulesauth_- Authentication rulesaudit_- Audit rulespwpolicy_- Password Policy rulesicloud_- iCloud rulessettings_- Settings rules
Requirements:
- Lowercase letters and underscores only
- Must be unique across all rules
- Filename must match:
os_chrome_autoupdate_enabled.yaml
title
Human-readable name:
title: Ensure Chrome Auto-Update is Enabled
discussion
Multi-line explanation using YAML's | syntax. Use RFC 2119 keywords (MUST, SHOULD, MAY) to indicate requirement levels:
discussion: |
Google Chrome _MUST_ automatically update to ensure
the latest security patches are applied.
Outdated browsers are a common attack vector.
platforms
The platforms section defines which macOS versions to target and the enforcement commands:
platforms:
macOS:
'15.0':
benchmarks:
- name: cis_lvl1
enforcement_info:
check:
shell: /usr/bin/command_to_check
result:
string: 'expected_value'
fix:
shell: /usr/bin/command_to_fix
check
The check section verifies compliance:
check:
shell: /usr/bin/defaults read com.apple.screensaver askForPassword
result:
string: '1'
Tips:
- Use full paths (
/usr/bin/defaults, notdefaults) - Redirect stderr if needed (
2>/dev/null) - Return a simple, comparable value
result
The expected output from the check command. Supports multiple types:
result:
string: 'expected text'
result:
integer: 1
result:
boolean: true
result:
integer: $ODV
fix
The command to remediate non-compliant settings:
fix:
shell: /usr/bin/defaults write com.apple.screensaver askForPassword -bool true
Tips:
- Make fixes idempotent (safe to run multiple times)
- Test thoroughly before deploying
- Use full paths to binaries
Optional Fields
Additional References
Beyond what the Rule Builder generates, you can add more compliance framework mappings:
references:
nist:
cce:
macos_15:
- CCE-XXXXX-X
800-53r5: # Optional
- CM-7
- AC-6
disa:
cci: # Optional
- CCI-000381
srg: # Optional
- SRG-OS-000095-GPOS-00049
disa_stig:
macos_15:
- APPL-15-XXXXXX
cis: # Optional
benchmark:
macos_15:
- '2.5.1 (level 1)'
controls_v8:
- '4.1'
odv
Organization Defined Values allow customization per baseline:
odv:
hint:
datatype: number
description: Maximum failed login attempts before lockout
validation:
min: 1
max: 10
recommended: 5
cis_lvl1: 5
cis_lvl2: 3
stig: 3
ODV datatypes: string, number, integer, boolean, regex
Use $ODV in check/fix scripts to reference the value:
check:
shell: /usr/bin/pwpolicy -getpolicy | grep maxFailedAttempts
result:
integer: $ODV
mobileconfig_info
For rules enforceable via configuration profile:
mobileconfig_info:
- PayloadType: com.apple.screensaver
PayloadContent:
- askForPassword: true
askForPasswordDelay: 0
ddm_info
For Declarative Device Management:
ddm_info:
declarationtype: com.apple.configuration.screensaver.settings
ddm_key: AskForPassword
ddm_value: true
benchmarks
Specify which baselines and severity:
platforms:
macOS:
'15.0':
benchmarks:
- name: cis_lvl1
- name: disa_stig
severity: medium
Severity levels: low, medium, high, critical
tags
Categorization tags for filtering and organization:
tags:
- cis_lvl1
- 800-53r5_moderate
Common tags: cis_lvl1, cis_lvl2, disa_stig, 800-53r5_low, 800-53r5_moderate, 800-53r5_high
File Naming
Save your rule as {id}.yaml:
os_chrome_autoupdate_enabled.yaml
The filename must match the id field exactly. The Rule Builder handles this automatically.
Validation
MACE validates custom rules when loading:
| ✅ | Required fields present |
| ✅ | ID is unique |
| ✅ | YAML syntax is valid |
| ✅ | Result type is recognized |
| ✅ | Filename matches ID |
Invalid rules are skipped with a warning.