Skip to content

Added CIS M365v5 SPO tests#1433

Open
HenrikPiecha wants to merge 5 commits intomaester365:mainfrom
HenrikPiecha:CISM365v57-SPO
Open

Added CIS M365v5 SPO tests#1433
HenrikPiecha wants to merge 5 commits intomaester365:mainfrom
HenrikPiecha:CISM365v57-SPO

Conversation

@HenrikPiecha
Copy link
Contributor

Description

Added SharePoint Online admin center tests from CIS Microsoft 365 v5.0.0
All the tests are related to the PowerShell module Microsoft.Online.SharePoint.PowerShell.

@merill please check the invocation as discussed.
The tests with Tag SpoTenant should only be executed when running interactivly as the ps module currently does not support read-only permission or service principal authentication from powershell 7.

Running the connection is mandatory:

Connect-SPOService -Url https://<tenant>-admin.sharepoint.com

Contribution Checklist

Before submitting this PR, please confirm you have completed the following:

  • [x ] 📖 Read the guidelines for contributing to this repository.
  • [ x] 🧪 Ensure the build and unit tests pass by running /powershell/tests/pester.ps1 on your local system.

 

Join us at the Maester repository discussions 💬 or Entra Discord 🧑‍💻 for more help and conversations!

@SamErde
Copy link
Contributor

SamErde commented Feb 17, 2026

I'm excited to see these in action, @HenrikPiecha!

As you noted above, these will not work in some contexts. Can you add checks to the beginning of the Pester test for these so it will fail gracefully and return a relevant SkippedBecause reason to the results report? Let us know if you'd like any help with that!

The tests with Tag SpoTenant should only be executed when running interactivly as the ps module currently does not support read-only permission or service principal authentication from powershell 7.

Running the connection is mandatory:

Connect-SPOService -Url https://<tenant>-admin.sharepoint.com

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds 7 new SharePoint Online (SPO) tests based on CIS Microsoft 365 v5.0.0 benchmark recommendations. These tests validate SPO tenant configuration settings related to external sharing, guest access, custom scripts, and malware protection. All tests use the Microsoft.Online.SharePoint.PowerShell module and require interactive connection via Connect-SPOService.

Changes:

  • Added 7 PowerShell test functions (Test-MtSpo*) for SPO tenant security checks
  • Added corresponding Pester tests tagged with 'SpoTenant'
  • Added website and PowerShell documentation for all 7 tests
  • Updated maester-config.json with test metadata (MT.1113-MT.1119)
  • Exported new functions in Maester.psd1 module manifest

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
tests/Maester/Spo/Test-SpoTenant.Tests.ps1 New Pester test file containing 7 SPO tenant configuration tests (MT.1113-MT.1119)
powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 Tests Microsoft Entra B2B integration (CIS 7.2.2)
powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 Tests custom script restrictions on site collections (CIS 7.3.4)
powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 Tests default sharing link type restrictions (CIS 7.2.7)
powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 Tests default sharing link permissions (CIS 7.2.11)
powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 Tests guest access expiration settings (CIS 7.2.9)
powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 Tests guest resharing restrictions (CIS 7.2.5)
powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 Tests malicious file download prevention (CIS 7.3.1)
powershell/public/maester/spo/*.md Documentation files for each test function
website/docs/tests/maester/MT.111*.md Website documentation for each test with CIS benchmark details
tests/maester-config.json Configuration entries for all 7 new tests with severity levels
powershell/Maester.psd1 Module manifest updated to export 7 new SPO functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

[CmdletBinding()]
[OutputType([bool])]
param()
Write-Verbose "Testing default sharing link type in SharePoint Online..."
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verbose message says "Testing default sharing link type" but this function tests custom script execution on site collections. The message should be updated to reflect the actual test being performed, such as "Testing custom script execution restrictions on site collections..."

Suggested change
Write-Verbose "Testing default sharing link type in SharePoint Online..."
Write-Verbose "Testing custom script execution restrictions on SharePoint Online site collections..."

Copilot uses AI. Check for mistakes.

$return = $true
try {
$noncompliantSites = Get-SPOSite | Where-Object { $_.DenyAddAndCustomizePages -eq "Disabled" -and $_.Url -notlike "*-my.sharepoint.com/" }
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL filter $_.Url -notlike "*-my.sharepoint.com/" has a trailing slash that may not match URLs consistently. SharePoint URLs may or may not have trailing slashes. Consider using $_.Url -notlike "*-my.sharepoint.com/*" with a wildcard after the slash, or remove the slash entirely: $_.Url -notlike "*-my.sharepoint.com*".

Suggested change
$noncompliantSites = Get-SPOSite | Where-Object { $_.DenyAddAndCustomizePages -eq "Disabled" -and $_.Url -notlike "*-my.sharepoint.com/" }
$noncompliantSites = Get-SPOSite | Where-Object { $_.DenyAddAndCustomizePages -eq "Disabled" -and $_.Url -notlike "*-my.sharepoint.com*" }

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A -match operator with a regex pattern could also be used to check for an optional trailing slash.

It 'MT.1118: Ensure that SharePoint guest users cannot share items they dont own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' {
$result = Test-MtSpoGuestCannotShareUnownedItem
if ($null -ne $result) {
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.'
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word "dont" should be "don't" (with apostrophe) in the Because message.

Suggested change
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.'
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they don't own.'

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot, the suggested fix would break quoting because this string already uses single quotes. It should be don''t or wrap the whole string in double quotes and then add the apostrophe to "don't."

$return = $true
try {
$spoTenant = Get-SPOTenant
if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -le 30) {
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition checks if ExternalUserExpireInDays is less than or equal to 30, but doesn't handle the case where ExternalUserExpirationRequired is true but ExternalUserExpireInDays might be 0 or negative (if such values are possible). Consider adding validation for positive values or documenting the expected behavior when the value is 0.

Suggested change
if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -le 30) {
if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -gt 0 -and $spoTenant.ExternalUserExpireInDays -le 30) {

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +35
It 'MT.1118: Ensure that SharePoint guest users cannot share items they dont own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' {
$result = Test-MtSpoGuestCannotShareUnownedItem
if ($null -ne $result) {
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.'
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word "dont" should be "don't" (with apostrophe) in the test description.

Suggested change
It 'MT.1118: Ensure that SharePoint guest users cannot share items they dont own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' {
$result = Test-MtSpoGuestCannotShareUnownedItem
if ($null -ne $result) {
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.'
It 'MT.1118: Ensure that SharePoint guest users cannot share items they don't own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' {
$result = Test-MtSpoGuestCannotShareUnownedItem
if ($null -ne $result) {
$result | Should -Be $true -Because 'SharePoint guest users cannot share items they don't own.'

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot, the suggested fix would break quoting because this string already uses single quotes. It should be don''t or wrap the whole string in double quotes and then add the apostrophe to "don't."

@SamErde SamErde added enhancement New feature or request maester-test Related to a Maester test sharepoint Microsoft SharePoint labels Feb 17, 2026
SamErde and others added 4 commits February 17, 2026 13:13
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@SamErde
Copy link
Contributor

SamErde commented Feb 17, 2026

BTW, you do not need to specify a severity tag in the Pester test files if they are added to the maester-config.json file.

@merill
Copy link
Contributor

merill commented Feb 18, 2026

@HenrikPiecha one catch I noticed with the SPO cmdlets is they don't work on non Windows devices like macOS.

Do you know if these tests can make use of PnP PowerShell? I believe that module has been updated PS7.

https://learn.microsoft.com/en-us/powershell/sharepoint/sharepoint-pnp/sharepoint-pnp-cmdlets

I believe this would also solve the interactive issue because PnP supports app only as well.

Do you know off the top of your head if these cmdlets are only available in SPO.

Another addition we need to make is to ./website/docs/installation.md and include the SPO (or PnP) module in the optional steps.

If not, folks would never know that they need to connect to SPO/PnP to run thes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request maester-test Related to a Maester test sharepoint Microsoft SharePoint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments