diff --git a/.github/workflows/docs-quality.yml b/.github/workflows/docs-quality.yml index 598e841..53daa9f 100644 --- a/.github/workflows/docs-quality.yml +++ b/.github/workflows/docs-quality.yml @@ -5,6 +5,7 @@ on: paths: - '**/*.md' - 'scripts/check_docs.py' + - 'scripts/check_editorial.py' - 'practice-labs/case-studies/**' - '.github/workflows/docs-quality.yml' push: @@ -23,9 +24,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: '3.12' + - name: Check added prose for editorial style + run: python scripts/check_editorial.py --base HEAD^ - name: Validate internal Markdown links run: python scripts/check_docs.py - name: Validate synthetic case study datasets diff --git a/contributing/README.md b/contributing/README.md index 7b87bfe..b63fb28 100644 --- a/contributing/README.md +++ b/contributing/README.md @@ -4,6 +4,19 @@ Follow the [RootGuard Documentation Design System](../design-system/README.md) f [Technical Content Review Register](content-review-register.md) tracks prioritised legacy corrections and validation status. +## Writing in plain English + +RootGuard is a public technical reference, not an internal status report or marketing brochure. + +- Write for a practising analyst or engineer. State the task, prerequisites, procedure, expected observations and limitations without promotional introductions. +- Use direct verbs such as **inspect**, **query**, **compare**, **preserve**, **verify** and **escalate**. +- Avoid em dashes in prose. Prefer a full stop, colon, semicolon or a rewritten sentence. +- Avoid stock phrases such as *ever-evolving threat landscape*, *cutting-edge*, *seamlessly*, *game changer*, *unlock the power of*, *delve into* and *robust solution*. Replace them with a specific claim or remove them. +- Do not repeat generic warning banners on every page. Put important requirements next to the relevant command or decision. +- Do not describe examples as comprehensive, complete, validated or production-ready unless the article provides evidence for that claim. +- Preserve literal syntax in KQL, PowerShell, command output, quoted source material and URLs. Language cleanup must never alter executable logic. +- Read the final article aloud. Remove filler, repeated ideas and unnecessary adjectives. + ## Publishing principles - Prefer evidence-based guidance, clear prerequisites and explicit limitations over unsupported claims. diff --git a/defensive-security/dfir/end-to-end-playbooks/credential-theft.md b/defensive-security/dfir/end-to-end-playbooks/credential-theft.md index bbe89ba..d781e3c 100644 --- a/defensive-security/dfir/end-to-end-playbooks/credential-theft.md +++ b/defensive-security/dfir/end-to-end-playbooks/credential-theft.md @@ -1,8 +1,6 @@ # Credential Theft: Operational Incident Investigation Playbook -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. +**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. **Review:** 20 October 2026 · **Owner:** SOC/CSIRT · **Authorisation:** Follow local incident command, privacy and evidence procedures. > **Important:** Queries below are *investigation pivots*, not finished alerts. Microsoft Defender XDR Advanced Hunting and Microsoft Sentinel Log Analytics use different tables and schema. Execute each query only in its stated environment. Preserve evidence, record approvals and do not delay urgent containment when harm is ongoing. @@ -15,7 +13,7 @@ 4. Preserve relevant logs, incident exports and endpoint artefacts through approved tools. Track collection time, retention gaps and custody. 5. Keep **observations**, **hypotheses** and **confirmed conclusions** in separate notes. -**Technology coverage:** Microsoft Entra, Defender XDR, Windows AD, workload identities +**Technology coverage:** Microsoft Entra, Defender XDR, Windows AD, workload identities **Trigger:** suspicious authentication, token exposure, credential addition, role change or endpoint credential-access alert. ## 2. Confirm telemetry prerequisites @@ -30,7 +28,7 @@ let User = "analyst@example.invalid"; SigninLogs | where TimeGenerated > ago(72h) and UserPrincipalName =~ User | project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, - ResultType, ConditionalAccessStatus, CorrelationId + ResultType, ConditionalAccessStatus, CorrelationId | order by TimeGenerated desc ``` @@ -57,7 +55,7 @@ DeviceProcessEvents | where Timestamp > ago(72h) | where ProcessCommandLine has_any ("lsass","comsvcs.dll","procdump") | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, - InitiatingProcessFileName, SHA1 + InitiatingProcessFileName, SHA1 | order by Timestamp desc ``` diff --git a/defensive-security/dfir/end-to-end-playbooks/lateral-movement.md b/defensive-security/dfir/end-to-end-playbooks/lateral-movement.md index f78f23f..922783d 100644 --- a/defensive-security/dfir/end-to-end-playbooks/lateral-movement.md +++ b/defensive-security/dfir/end-to-end-playbooks/lateral-movement.md @@ -1,8 +1,6 @@ # Lateral Movement: Operational Incident Investigation Playbook -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. +**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. **Review:** 20 October 2026 · **Owner:** SOC/CSIRT · **Authorisation:** Follow local incident command, privacy and evidence procedures. > **Important:** Queries below are *investigation pivots*, not finished alerts. Microsoft Defender XDR Advanced Hunting and Microsoft Sentinel Log Analytics use different tables and schema. Execute each query only in its stated environment. Preserve evidence, record approvals and do not delay urgent containment when harm is ongoing. @@ -15,7 +13,7 @@ 4. Preserve relevant logs, incident exports and endpoint artefacts through approved tools. Track collection time, retention gaps and custody. 5. Keep **observations**, **hypotheses** and **confirmed conclusions** in separate notes. -**Technology coverage:** Defender for Endpoint, Windows Security/System, AD, network and change records +**Technology coverage:** Defender for Endpoint, Windows Security/System, AD, network and change records **Trigger:** unexpected remote administrative activity, privileged logon, remote service/task or cross-host execution. ## 2. Confirm telemetry prerequisites @@ -29,9 +27,9 @@ Check table availability, licences, audit policy, retention, time synchronisatio DeviceProcessEvents | where Timestamp > ago(48h) | where FileName in~ ("psexec.exe","wmic.exe","winrs.exe","mstsc.exe") - or ProcessCommandLine has_any ("Invoke-Command","Enter-PSSession") + or ProcessCommandLine has_any ("Invoke-Command","Enter-PSSession") | project Timestamp, DeviceName, AccountName, FileName, - ProcessCommandLine, InitiatingProcessFileName, ReportId + ProcessCommandLine, InitiatingProcessFileName, ReportId | order by Timestamp desc ``` @@ -45,7 +43,7 @@ DeviceLogonEvents | where Timestamp > ago(48h) | where LogonType in~ ("Network","RemoteInteractive") | project Timestamp, DeviceName, AccountName, LogonType, - RemoteIP, ActionType, FailureReason + RemoteIP, ActionType, FailureReason | order by Timestamp desc ``` @@ -59,7 +57,7 @@ DeviceNetworkEvents | where Timestamp > ago(48h) | where RemotePort in (135,139,445,3389,5985,5986) | project Timestamp, DeviceName, InitiatingProcessFileName, - RemoteIP, RemotePort, ActionType + RemoteIP, RemotePort, ActionType | order by Timestamp desc ``` diff --git a/defensive-security/dfir/end-to-end-playbooks/phishing-compromise.md b/defensive-security/dfir/end-to-end-playbooks/phishing-compromise.md index 0e5b137..2434b0e 100644 --- a/defensive-security/dfir/end-to-end-playbooks/phishing-compromise.md +++ b/defensive-security/dfir/end-to-end-playbooks/phishing-compromise.md @@ -1,8 +1,6 @@ # Phishing Compromise: Operational Incident Investigation Playbook -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. +**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. **Review:** 20 October 2026 · **Owner:** SOC/CSIRT · **Authorisation:** Follow local incident command, privacy and evidence procedures. > **Important:** Queries below are *investigation pivots*, not finished alerts. Microsoft Defender XDR Advanced Hunting and Microsoft Sentinel Log Analytics use different tables and schema. Execute each query only in its stated environment. Preserve evidence, record approvals and do not delay urgent containment when harm is ongoing. @@ -15,7 +13,7 @@ 4. Preserve relevant logs, incident exports and endpoint artefacts through approved tools. Track collection time, retention gaps and custody. 5. Keep **observations**, **hypotheses** and **confirmed conclusions** in separate notes. -**Technology coverage:** Defender for Office 365, Defender XDR, Entra ID, Exchange Online +**Technology coverage:** Defender for Office 365, Defender XDR, Entra ID, Exchange Online **Trigger:** malicious email, user click, credential submission, mailbox change or suspicious endpoint execution. ## 2. Confirm telemetry prerequisites @@ -31,7 +29,7 @@ EmailEvents | where Timestamp > ago(7d) | where RecipientEmailAddress =~ TargetMailbox | project Timestamp, NetworkMessageId, RecipientEmailAddress, - SenderFromAddress, Subject, DeliveryAction, ThreatTypes + SenderFromAddress, Subject, DeliveryAction, ThreatTypes | order by Timestamp desc ``` @@ -58,7 +56,7 @@ DeviceProcessEvents | where Timestamp > ago(48h) and DeviceName =~ Host | where InitiatingProcessFileName in~ ("winword.exe","excel.exe","outlook.exe","msedge.exe") | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, - InitiatingProcessFileName, InitiatingProcessCommandLine, SHA1 + InitiatingProcessFileName, InitiatingProcessCommandLine, SHA1 | order by Timestamp desc ``` diff --git a/defensive-security/dfir/end-to-end-playbooks/ransomware.md b/defensive-security/dfir/end-to-end-playbooks/ransomware.md index 3a6ddb7..2df1532 100644 --- a/defensive-security/dfir/end-to-end-playbooks/ransomware.md +++ b/defensive-security/dfir/end-to-end-playbooks/ransomware.md @@ -1,8 +1,6 @@ # Ransomware: Operational Incident Investigation Playbook -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. +**Operational status:** Practitioner workflow; KQL syntax and outcomes require testing against your deployed product schema. Not production-validated. **Review:** 20 October 2026 · **Owner:** SOC/CSIRT · **Authorisation:** Follow local incident command, privacy and evidence procedures. > **Important:** Queries below are *investigation pivots*, not finished alerts. Microsoft Defender XDR Advanced Hunting and Microsoft Sentinel Log Analytics use different tables and schema. Execute each query only in its stated environment. Preserve evidence, record approvals and do not delay urgent containment when harm is ongoing. @@ -15,7 +13,7 @@ 4. Preserve relevant logs, incident exports and endpoint artefacts through approved tools. Track collection time, retention gaps and custody. 5. Keep **observations**, **hypotheses** and **confirmed conclusions** in separate notes. -**Technology coverage:** Defender for Endpoint, Windows/AD, backup systems, network controls +**Technology coverage:** Defender for Endpoint, Windows/AD, backup systems, network controls **Trigger:** mass file modification, ransom note, backup tampering, encryption or extortion claim. ## 2. Confirm telemetry prerequisites @@ -30,7 +28,7 @@ DeviceProcessEvents | where Timestamp > ago(24h) | where ProcessCommandLine has_any ("vssadmin","wbadmin","bcdedit") | project Timestamp, DeviceName, AccountName, FileName, - ProcessCommandLine, InitiatingProcessFileName, SHA1, ReportId + ProcessCommandLine, InitiatingProcessFileName, SHA1, ReportId | order by Timestamp desc ``` @@ -44,8 +42,8 @@ let Host = "REPLACE_WITH_DEVICE_NAME"; DeviceFileEvents | where Timestamp > ago(24h) and DeviceName =~ Host | summarize FileEvents=count(), DistinctPaths=dcount(FolderPath), - Samples=make_set(FileName, 12) - by bin(Timestamp, 15m), InitiatingProcessFileName + Samples=make_set(FileName, 12) + by bin(Timestamp, 15m), InitiatingProcessFileName | order by Timestamp desc ``` @@ -59,7 +57,7 @@ let Host = "REPLACE_WITH_DEVICE_NAME"; DeviceNetworkEvents | where Timestamp > ago(24h) and DeviceName =~ Host | project Timestamp, DeviceName, InitiatingProcessFileName, - RemoteIP, RemotePort, RemoteUrl, ActionType + RemoteIP, RemotePort, RemoteUrl, ActionType | order by Timestamp desc ``` diff --git a/defensive-security/dfir/field-guides/evidence-acquisition-and-integrity.md b/defensive-security/dfir/field-guides/evidence-acquisition-and-integrity.md index 01d0488..c1639d3 100644 --- a/defensive-security/dfir/field-guides/evidence-acquisition-and-integrity.md +++ b/defensive-security/dfir/field-guides/evidence-acquisition-and-integrity.md @@ -1,7 +1,5 @@ # Evidence Acquisition and Integrity -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - **Status:** Procedure template requiring organisational approval and tool-specific validation. ## Before acquisition diff --git a/defensive-security/dfir/field-guides/windows-artifact-interpretation.md b/defensive-security/dfir/field-guides/windows-artifact-interpretation.md index 6098b2f..660eabe 100644 --- a/defensive-security/dfir/field-guides/windows-artifact-interpretation.md +++ b/defensive-security/dfir/field-guides/windows-artifact-interpretation.md @@ -1,7 +1,5 @@ # Windows Forensic Artefacts: Interpretation Reference -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - **Status:** Technical reference; artefact meaning and location depend on Windows build and configuration. | Artefact | What it may help establish | Important limitation | diff --git a/defensive-security/dfir/field-guides/windows-endpoint-triage.md b/defensive-security/dfir/field-guides/windows-endpoint-triage.md index d5ec11f..c040abc 100644 --- a/defensive-security/dfir/field-guides/windows-endpoint-triage.md +++ b/defensive-security/dfir/field-guides/windows-endpoint-triage.md @@ -1,8 +1,6 @@ # Windows Endpoint Triage: First-Response Field Guide -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**Reviewed:** 20 October 2026 +**Reviewed:** 20 October 2026 **Status:** Methodology reference; commands must be validated and authorised locally. ## Initial decisions diff --git a/detection-engineering/threat-detection/ad-detections-and-mitigations/dcsync.md b/detection-engineering/threat-detection/ad-detections-and-mitigations/dcsync.md index 8c0a470..4d0a40e 100644 --- a/detection-engineering/threat-detection/ad-detections-and-mitigations/dcsync.md +++ b/detection-engineering/threat-detection/ad-detections-and-mitigations/dcsync.md @@ -11,9 +11,9 @@ DCSync (MITRE ATT&CK T1003.006) abuses Active Directory Directory Replication Se - Collect Windows Security Event **4662** from domain controllers and configure the necessary Directory Service Access auditing and directory object SACLs. Event 4662 is not automatically generated for every DCSync attempt. - Inspect actual `SecurityEvent` records and their `Properties` and `AccessMask` contents. Schema and event rendering vary by agent and collection method. - Relevant replication extended-right GUIDs include: - - `1131f6aa-9c07-11d1-f79f-00c04fc2dcd2` — DS-Replication-Get-Changes - - `1131f6ad-9c07-11d1-f79f-00c04fc2dcd2` — DS-Replication-Get-Changes-All - - `89e95b76-444d-4c62-991a-0facbeda640c` — DS-Replication-Get-Changes-In-Filtered-Set + - `1131f6aa-9c07-11d1-f79f-00c04fc2dcd2` , DS-Replication-Get-Changes + - `1131f6ad-9c07-11d1-f79f-00c04fc2dcd2` , DS-Replication-Get-Changes-All + - `89e95b76-444d-4c62-991a-0facbeda640c` , DS-Replication-Get-Changes-In-Filtered-Set Event 4662 reports object operations on the domain controller. It does **not** reliably give the network originator's IP address. Neither Event 4672 nor ordinary LDAP connections alone prove DCSync activity. diff --git a/detection-engineering/threat-detection/ad-detections-and-mitigations/golden-ticket.md b/detection-engineering/threat-detection/ad-detections-and-mitigations/golden-ticket.md index b6a00e4..ff5e6ed 100644 --- a/detection-engineering/threat-detection/ad-detections-and-mitigations/golden-ticket.md +++ b/detection-engineering/threat-detection/ad-detections-and-mitigations/golden-ticket.md @@ -1,9 +1,7 @@ # Golden Ticket: Detection and Response -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**ATT&CK:** [T1558.001](https://attack.mitre.org/techniques/T1558/001/) -**Reviewed:** 20 October 2026 +**ATT&CK:** [T1558.001](https://attack.mitre.org/techniques/T1558/001/) +**Reviewed:** 20 October 2026 **Validation:** Concept / unvalidated; verify all fields and behaviour in an authorised lab. ## Threat overview @@ -31,13 +29,13 @@ SecurityEvent | where TimeGenerated > ago(24h) | where EventID == 4769 | extend Requester = tostring(Account), - Service = tostring(ServiceName), - SourceAddress = tostring(IpAddress) + Service = tostring(ServiceName), + SourceAddress = tostring(IpAddress) | where isnotempty(Requester) | summarize Requests=count(), DistinctServices=dcount(Service), - Services=make_set(Service, 30), - Sources=make_set(SourceAddress, 20) - by Requester, bin(TimeGenerated, 1h) + Services=make_set(Service, 30), + Sources=make_set(SourceAddress, 20) + by Requester, bin(TimeGenerated, 1h) | order by DistinctServices desc, Requests desc ``` diff --git a/detection-engineering/threat-detection/ad-detections-and-mitigations/kerberoasting.md b/detection-engineering/threat-detection/ad-detections-and-mitigations/kerberoasting.md index 52f3b2c..50e58b2 100644 --- a/detection-engineering/threat-detection/ad-detections-and-mitigations/kerberoasting.md +++ b/detection-engineering/threat-detection/ad-detections-and-mitigations/kerberoasting.md @@ -1,9 +1,7 @@ # Kerberoasting: Detection and Investigation -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - -**ATT&CK:** [T1558.003](https://attack.mitre.org/techniques/T1558/003/) -**Review date:** 20 October 2026 +**ATT&CK:** [T1558.003](https://attack.mitre.org/techniques/T1558/003/) +**Review date:** 20 October 2026 **Validation:** Concept / unvalidated; domain-controller telemetry must be confirmed. ## Threat overview @@ -28,13 +26,13 @@ SecurityEvent | where TimeGenerated > ago(24h) | where EventID == 4769 | extend RequestingAccount = tostring(Account), - ClientAddress = tostring(IpAddress), - TargetService = tostring(ServiceName) + ClientAddress = tostring(IpAddress), + TargetService = tostring(ServiceName) | where isnotempty(RequestingAccount) and isnotempty(TargetService) | summarize Requests=count(), - Services=dcount(TargetService), - TargetServices=make_set(TargetService, 30) - by RequestingAccount, ClientAddress, WindowStart=bin(TimeGenerated, 15m) + Services=dcount(TargetService), + TargetServices=make_set(TargetService, 30) + by RequestingAccount, ClientAddress, WindowStart=bin(TimeGenerated, 15m) | where Services >= 5 | order by Services desc, Requests desc ``` diff --git a/detection-engineering/threat-detection/ad-detections-and-mitigations/password-spraying.md b/detection-engineering/threat-detection/ad-detections-and-mitigations/password-spraying.md index 4186ee4..30dce26 100644 --- a/detection-engineering/threat-detection/ad-detections-and-mitigations/password-spraying.md +++ b/detection-engineering/threat-detection/ad-detections-and-mitigations/password-spraying.md @@ -1,7 +1,5 @@ # Password Spraying: Detection and Investigation -> **RootGuard technical reference** · **Environment:** Verify product, platform and telemetry prerequisites · **Validation:** Refer to the status below; examples are not automatically production-ready. - **ATT&CK:** [T1110.003](https://attack.mitre.org/techniques/T1110/003/) **Review date:** 20 October 2026 **Validation:** Concept / unvalidated; verify with your environment's telemetry. diff --git a/detection-engineering/threat-detection/ad-detections-and-mitigations/silver-ticket.md b/detection-engineering/threat-detection/ad-detections-and-mitigations/silver-ticket.md index 7ab56b6..e8b9348 100644 --- a/detection-engineering/threat-detection/ad-detections-and-mitigations/silver-ticket.md +++ b/detection-engineering/threat-detection/ad-detections-and-mitigations/silver-ticket.md @@ -1,7 +1,7 @@ # Silver Ticket: Detection and Response -**ATT&CK:** [T1558.002](https://attack.mitre.org/techniques/T1558/002/) -**Reviewed:** 20 October 2026 +**ATT&CK:** [T1558.002](https://attack.mitre.org/techniques/T1558/002/) +**Reviewed:** 20 October 2026 **Validation:** Concept / unvalidated; verify on representative services. ## Threat overview @@ -30,10 +30,10 @@ SecurityEvent | where EventID == 4624 | where AuthenticationPackageName =~ "Kerberos" | extend AccountName = tostring(Account), - SourceAddress = tostring(IpAddress) + SourceAddress = tostring(IpAddress) | summarize Logons=count(), Accounts=make_set(AccountName, 30), - Sources=make_set(SourceAddress, 20) - by Computer, LogonType, bin(TimeGenerated, 1h) + Sources=make_set(SourceAddress, 20) + by Computer, LogonType, bin(TimeGenerated, 1h) | order by Logons desc ``` diff --git a/scripts/check_editorial.py b/scripts/check_editorial.py new file mode 100644 index 0000000..8b267af --- /dev/null +++ b/scripts/check_editorial.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Review newly added public Markdown prose for em dashes and stock phrases. + +Use with: python scripts/check_editorial.py --base origin/master +The check reads only added lines in the git diff. Existing legacy prose remains +a separate, tracked editorial backlog. Code blocks are ignored in whole-file mode. +""" +import argparse +import pathlib +import re +import subprocess +import sys + +PHRASES = [ + "ever-evolving threat landscape", "cutting-edge", "game changer", + "unlock the power of", "delve into", "seamlessly integrate", + "in today's digital landscape", +] +PATTERN = re.compile("|".join(re.escape(p) for p in PHRASES), re.IGNORECASE) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--base", default="HEAD^") + args = parser.parse_args() + diff = subprocess.run( + ["git", "diff", "--unified=0", args.base, "HEAD", "--", "*.md"], + capture_output=True, text=True, check=True, + ).stdout + path = "" + issues = [] + for line in diff.splitlines(): + if line.startswith("+++ b/"): + path = line[6:] + elif line.startswith("+") and not line.startswith("+++"): + if path == "contributing/README.md": + continue + added = line[1:] + # Skip likely code, tables of technical syntax, or URL lines. + if added.lstrip().startswith((" ", "`", "http", "#!")): + continue + found = PATTERN.search(added) + if "—" in added or found: + issues.append((path, added[:180])) + for path, excerpt in issues: + print(f"Editorial review required: {path}: {excerpt}") + if issues: + print("Remove em dashes or stock language from newly added prose.") + return 1 + print("New Markdown prose editorial checks passed.") + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/start-here/README.md b/start-here/README.md index 31b654c..d3f8b6c 100644 --- a/start-here/README.md +++ b/start-here/README.md @@ -25,13 +25,13 @@ ## Content labels -**Operational playbook** — step-by-step investigative workflow with decision gates and response criteria. +**Operational playbook**, step-by-step investigative workflow with decision gates and response criteria. -**Technical reference** — focused explanation of a technique, artefact, query or platform. +**Technical reference**, focused explanation of a technique, artefact, query or platform. -**Practical exercise** — optional synthetic training material, never evidence from a real incident. +**Practical exercise**, optional synthetic training material, never evidence from a real incident. -**Validation status** — technical claims may be subject to static review, syntax testing, lab verification or production validation. Follow the label on each document. +**Validation status**, technical claims may be subject to static review, syntax testing, lab verification or production validation. Follow the label on each document. For command and query testing, use the [Runbook Execution and Validation Matrix](../defensive-security/dfir/runbooks/runbook-execution-validation-matrix.md).