Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
232552a
Custom Scripts Test System
Zacgoose Feb 21, 2026
cacc642
feat(exchange): add OOO calendar options (block calendar, decline inv…
kris6673 Mar 16, 2026
d094188
Add API endpoints for Intune Application Deployment Templates
Mar 17, 2026
aac2f4e
refactor: replace bulk Graph request with per-method foreach loop
kris6673 Mar 19, 2026
951d2db
Dev to hf (#1939)
KelvinTegelaar Mar 19, 2026
c30c96a
support group memberships in user templates and filter unavailable li…
Mar 19, 2026
5ecdc29
fix: text replacement for when tenant filter is unspecified
JohnDuprey Mar 20, 2026
94c0157
feat: Enhance security and functionality across multiple modules
JohnDuprey Mar 20, 2026
db380d0
Fix: Silly issue with removing legacy addins
Zacgoose Mar 20, 2026
1fc8a50
Fix: Silly issue with removing legacy addins (#1943)
KelvinTegelaar Mar 20, 2026
e5da743
Update Add-CIPPW32ScriptApplication.ps1
TecharyJames Mar 20, 2026
4f4eb48
fix: Optimize tenant processing by pre-expanding tenant groups in aud…
JohnDuprey Mar 21, 2026
2ef12d9
fix(groups): sanitize mailNickname for security group creation
Mar 21, 2026
963a98e
fix(group-templates): add validation for username and groupType
Mar 21, 2026
b25e385
feat(security): add MDE onboarding status report with caching
Mar 22, 2026
121a2cb
pr
Zacgoose Mar 22, 2026
0e4d015
Revert "pr"
Zacgoose Mar 22, 2026
92c41ae
feat: add group membership support to user templates
Mar 22, 2026
5132af4
feat: Add Invoke-ExecCompareIntunePolicy function
kris6673 Mar 21, 2026
88d4002
Refactor: MFA method removal to individual requests (#1938)
KelvinTegelaar Mar 22, 2026
ba8713b
feat: add MDE onboarding status report with caching (#1949)
KelvinTegelaar Mar 22, 2026
698e11c
Feat/variables in intune custom application (#1944)
KelvinTegelaar Mar 22, 2026
d6975d2
Fix: Make API client creation more resilient for entra replication time
Zacgoose Mar 23, 2026
f0fe415
Namespace scoped variable protection
Zacgoose Mar 23, 2026
8484e39
cleanup code
Mar 23, 2026
60e57dd
cleanup unnecessary checks
Mar 23, 2026
11c6bc0
fix: cleanup of standard template when removed
JohnDuprey Mar 23, 2026
c396867
fix: update inclusion/exclusion logic for tenant alignment
JohnDuprey Mar 23, 2026
cecaff6
fix: add initialDomainName support to logs and exo request
JohnDuprey Mar 23, 2026
c85052a
Add cmdlets to remove extension API keys
Zacgoose Mar 24, 2026
1eb4862
Add standardized webhook schema support
Zacgoose Mar 24, 2026
1d546e1
fix: Check extension standard
JohnDuprey Mar 24, 2026
152153e
feat: Check browser extension improvements
JohnDuprey Mar 24, 2026
a39e57f
fix: update extension name
JohnDuprey Mar 24, 2026
9916990
feat: Add OOO calendar options for Exchange (#1911)
JohnDuprey Mar 24, 2026
71468ca
fix: optimize role member retrieval in Invoke-ListRoles function
JohnDuprey Mar 24, 2026
8dc3091
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
JohnDuprey Mar 24, 2026
ab9cb1d
Add litigation/retention mailbox fields
Zacgoose Mar 25, 2026
452b987
Add webhook auth and tenant filter support
Zacgoose Mar 25, 2026
083040d
Add username space handling to user defaults
Zacgoose Mar 25, 2026
a48bc46
Add cmdlets to remove extension API keys (#1956)
KelvinTegelaar Mar 25, 2026
3b48260
Add username space handling to user defaults (#1959)
KelvinTegelaar Mar 25, 2026
f0a1227
Add litigation/retention mailbox fields (#1958)
KelvinTegelaar Mar 25, 2026
f47fb05
Fix: sanitize mailnickname (#1948)
KelvinTegelaar Mar 25, 2026
e73af4d
Feat: Add standardized webhook schema support and authentication meth…
KelvinTegelaar Mar 25, 2026
5b2797b
Fix: Make API client creation more resilient for entra replication ti…
KelvinTegelaar Mar 25, 2026
79a2c7b
Merge branch 'dev' into feat/create-template-from-user
KelvinTegelaar Mar 25, 2026
a1b9730
feat: support group memberships in user templates and filter unavaila…
KelvinTegelaar Mar 25, 2026
15fdda2
String lists and arrays can be dumb
rvdwegen Mar 25, 2026
4a08c8b
Get-CIPPAlertLongLivedAppCredentials backend
rvdwegen Mar 25, 2026
23fea8a
Add app and service principal expiry checks
Zacgoose Mar 25, 2026
056f915
Get-CIPPAlertRoleEscalableGroups
rvdwegen Mar 25, 2026
9c6a684
fix: promote nested component values to top level in standard templat…
JohnDuprey Mar 25, 2026
02bd795
fix: ensure ExecutedTime is cleared for one-time task reruns in Invok…
JohnDuprey Mar 25, 2026
e8c0d32
refactor: Defender deployment into separate helper scripts
JohnDuprey Mar 25, 2026
8e6b320
refactor: Move all orchestrator invocations to Start-CIPPOrchestrator
JohnDuprey Mar 25, 2026
20e2ce9
fix: limit record type filters to improve search performance
JohnDuprey Mar 25, 2026
de7a1ef
fix: ensure orchestrator tables are created before processing input
JohnDuprey Mar 25, 2026
f90fa92
refactor: use Add-CIPPGroupMember for group assignment in user creation
Mar 25, 2026
59e63b3
Add Invoke-CIPPStandardColleagueImpersonationAlert function
chris-dewey-1991 Mar 25, 2026
6ef0ca9
fix: Add InvokingCommand to webhook alert test
JohnDuprey Mar 25, 2026
f0a15bf
fix: add AnyTenant designation for access checks
JohnDuprey Mar 25, 2026
cd28fd8
chore: fix write-host logging for storage commands
JohnDuprey Mar 25, 2026
2d9f247
Filter SMTP sign-ins by date range
Zacgoose Mar 26, 2026
f8eeeb6
chore: update license files to newest MS version
kris6673 Mar 26, 2026
133fdd4
Add Invoke-CIPPStandardColleagueImpersonationAlert function (#1961)
KelvinTegelaar Mar 26, 2026
109d4e1
Fixes double compressed input object being passed to CIPPOrchestrator
Zacgoose Mar 26, 2026
8cd39e2
Fixes double compressed input object being passed to CIPPOrchestrator…
Zacgoose Mar 26, 2026
23d24d4
Add app and service principal expiry checks (#1960)
KelvinTegelaar Mar 26, 2026
544bc72
chore: Update license files to latest Microsoft version (#1963)
KelvinTegelaar Mar 26, 2026
d108dd0
feat: Intune Policy Comparison endpoint and comparison engine fixes (…
KelvinTegelaar Mar 26, 2026
053946d
Feat: Filter SMTP sign-ins by date range (#1962)
KelvinTegelaar Mar 26, 2026
eaa6894
Merge branch 'dev' into custom-scripts
KelvinTegelaar Mar 26, 2026
57359c7
Custom Scripts Test System (#1815)
KelvinTegelaar Mar 26, 2026
00e3185
feat: Add API endpoints for Intune Application Deployment Templates (…
KelvinTegelaar Mar 26, 2026
bafec9c
Merge branch 'dev' into feat/add-groups-to-user-template
KelvinTegelaar Mar 26, 2026
ab098b3
feat: add group membership support to user templates (#1952)
KelvinTegelaar Mar 26, 2026
0fdab99
fix because wrong commit picked
KelvinTegelaar Mar 26, 2026
a738b56
fix: improve tenant group management
JohnDuprey Mar 26, 2026
d8f1856
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
JohnDuprey Mar 26, 2026
35c7fb8
feat: add GroupType property to group objects in Get-TenantGroups fun…
JohnDuprey Mar 26, 2026
6e216e6
small fixes to make things prettier.
KelvinTegelaar Mar 26, 2026
5190635
group duplicate fix.
KelvinTegelaar Mar 26, 2026
52d538b
fix: handle duplicate group and location matches in New-CIPPCAPolicy …
JohnDuprey Mar 26, 2026
d42f25d
fixes group adding
KelvinTegelaar Mar 26, 2026
941e521
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
KelvinTegelaar Mar 26, 2026
e0fcf7c
Fix group based removal #5673
KelvinTegelaar Mar 26, 2026
d73587e
manage secrets and certs
rvdwegen Mar 26, 2026
fa674f8
Reporting DB manual run fix
Zacgoose Mar 27, 2026
7ddb4ff
Fix: Reporting DB manual run fix (#1965)
Zacgoose Mar 27, 2026
6305f38
chore: Update SAM permissions
JohnDuprey Mar 27, 2026
c4d7587
Run custom scripts as individual CIPP tests
Zacgoose Mar 27, 2026
9ac00ae
enable/disable actions
Zacgoose Mar 27, 2026
fc86b9e
Make cache task creation more durable
Zacgoose Mar 27, 2026
572633b
feat: Local dev - Add Proxyman CA support in Docker and profile
JohnDuprey Mar 27, 2026
a839a6c
Tweaks
Zacgoose Mar 27, 2026
022d169
Tweaks (#1969)
Zacgoose Mar 27, 2026
956900b
Fix: Make cache task creation more durable (#1966)
KelvinTegelaar Mar 27, 2026
f56b353
feat: Add Copilot readiness tests
JohnDuprey Mar 27, 2026
e595e8a
fix: Handle QuarantineTemplate in drift and alignment functions
JohnDuprey Mar 27, 2026
c30cbdc
fix: copilot readiness tests to use reports.office.com endpoint
JohnDuprey Mar 27, 2026
978659d
fix: reschedule onboarding to continue +15 minutes after relationship…
JohnDuprey Mar 27, 2026
bcd5d6a
feat: Add more Copilot & Purview cache tasks and readiness tests
JohnDuprey Mar 27, 2026
9b12354
feat: Implement Invoke-ListGraphReports function for report retrieval
JohnDuprey Mar 27, 2026
0f59cc4
stuff for report builder
KelvinTegelaar Mar 28, 2026
17e7d09
stuff for report builder
KelvinTegelaar Mar 28, 2026
4d6269c
new report builder
KelvinTegelaar Mar 28, 2026
4fe5620
fix: Improve app name formatting in Copilot readiness reports and set…
JohnDuprey Mar 28, 2026
5f2ca52
fix: permission with some reports requiring delegated
JohnDuprey Mar 28, 2026
eff725b
remove a bit of slop
KelvinTegelaar Mar 28, 2026
0c236c9
Merge branch 'dev' into custom-scripts-fixes
Zacgoose Mar 28, 2026
0fc469d
Fix: Custom scripts fixes (#1967)
Zacgoose Mar 28, 2026
9aed799
Report stuff
KelvinTegelaar Mar 29, 2026
f94b579
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
KelvinTegelaar Mar 29, 2026
ec3d650
Fix Teams Phone DIDs removal failing due to missing Content-Type head…
Mar 29, 2026
ebb2bcd
refactor: Optimize tests to run per suite
JohnDuprey Mar 30, 2026
3792c1d
Support custom report updates, prebuilt report fixes
Zacgoose Mar 30, 2026
ce310f7
new generic reports
KelvinTegelaar Mar 30, 2026
46f0488
more generic reports
KelvinTegelaar Mar 30, 2026
72cc73a
more tests and standards.json update
KelvinTegelaar Mar 30, 2026
1e4459e
more tests and standards.json update
KelvinTegelaar Mar 30, 2026
7f0ba27
Support custom report updates, prebuilt report fixes (#1973)
JohnDuprey Mar 30, 2026
3a19557
Fix: Teams Phone DIDs removal failing due to missing Content-Type hea…
JohnDuprey Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ yarn.lock
/*.ps1
!/profile.ps1
.DS_Store
proxyman.pem
35 changes: 35 additions & 0 deletions CIPPDBCacheTypes.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@
"friendlyName": "OneDrive Usage",
"description": "OneDrive usage statistics"
},
{
"type": "OfficeActivations",
"friendlyName": "Office Activations",
"description": "Microsoft 365 app activation counts per user per platform (Windows, Mac, Mobile)"
},
{
"type": "CopilotReadinessActivity",
"friendlyName": "Copilot Readiness Activity",
"description": "Per-user Copilot readiness signals (update channel, Teams, Outlook, Office docs) over 30 days"
},
{
"type": "ConditionalAccessPolicies",
"friendlyName": "Conditional Access Policies",
Expand Down Expand Up @@ -328,5 +338,30 @@
"type": "DetectedApps",
"friendlyName": "Detected Apps",
"description": "All detected applications with devices where each app is installed"
},
{
"type": "SensitivityLabels",
"friendlyName": "Sensitivity Labels",
"description": "Microsoft Purview sensitivity labels configured in the tenant"
},
{
"type": "DlpCompliancePolicies",
"friendlyName": "DLP Compliance Policies",
"description": "Data Loss Prevention compliance policies from the Purview compliance portal"
},
{
"type": "CopilotUsageUserDetail",
"friendlyName": "Copilot Usage User Detail",
"description": "Per-user Microsoft 365 Copilot usage details across apps (30-day period)"
},
{
"type": "CopilotUserCountSummary",
"friendlyName": "Copilot User Count Summary",
"description": "Aggregate active Copilot user counts by app (30-day period)"
},
{
"type": "CopilotUserCountTrend",
"friendlyName": "Copilot User Count Trend",
"description": "Daily Copilot active user count trend (7-day period)"
}
]
1,277 changes: 1,168 additions & 109 deletions Config/standards.json

Large diffs are not rendered by default.

8,261 changes: 4,146 additions & 4,115 deletions ConversionTable.csv

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY . /home/site/wwwroot

# Optionally install Proxyman CA certificate if proxyman.pem exists in the build context
RUN if [ -f /home/site/wwwroot/proxyman.pem ]; then \
apt-get update && apt-get install -y --no-install-recommends ca-certificates && \
cp /home/site/wwwroot/proxyman.pem /usr/local/share/ca-certificates/proxyman.crt && \
update-ca-certificates && \
rm -rf /var/lib/apt/lists/*; \
fi
109 changes: 109 additions & 0 deletions Modules/CIPPCore/Private/ConvertTo-StringList.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
function ConvertTo-StringList {
<#
.SYNOPSIS
Turns encoded list data into something you can foreach over.

.DESCRIPTION
String input: if it is JSON (object or array), it is converted first; otherwise comma/semicolon/newline
splitting applies. Other shapes: wrapper objects, or an existing array/list. After conversion, the return
value is always foreach-able (empty collection is @()). Arrays and IList instances are returned
as-is — they are already foreach-able without conversion.
This exists because front end multi-value input is annoying to deal with.

.PARAMETER InputObject
Encoded list (string/JSON), wrapper object, or an existing array/list.

.PARAMETER PropertyNames
On hashtables/PSCustomObjects, property names to read in order.

.OUTPUTS
Always an enumerable suitable for: foreach ($item in (ConvertTo-StringList ...)) { }
#>
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[Alias('Input', 'Value')]
[AllowNull()]
$InputObject,

[string[]]$PropertyNames = @('Items', 'Value')
)

# Output must be foreach-able; $null input yields empty collection.
if ($null -eq $InputObject) {
return @()
}

if ($InputObject -is [string]) {
$s = $InputObject.Trim()
if (-not $s) {
return @()
}
if ($s.StartsWith('[') -or $s.StartsWith('{')) {
try {
$parsed = $s | ConvertFrom-Json -ErrorAction Stop
return ConvertTo-StringList -InputObject $parsed -PropertyNames $PropertyNames
} catch {
}
}
return @(
$s -split '[,;\r\n]+' | ForEach-Object { $_.Trim() } | Where-Object { $_ }
)
}

if ($InputObject -is [Array]) {
return $InputObject
}
if ($InputObject -is [System.Collections.IList] -and $InputObject -isnot [string]) {
return $InputObject
}

if ($InputObject -is [hashtable]) {
if ($InputObject.Count -eq 0) {
return @()
}
foreach ($name in $PropertyNames) {
if ($InputObject.ContainsKey($name)) {
return ConvertTo-StringList -InputObject $InputObject[$name] -PropertyNames $PropertyNames
}
}
foreach ($p in $InputObject.GetEnumerator() | Sort-Object { $_.Key }) {
$v = $p.Value
if ($null -eq $v) { continue }
if ($v -is [string] -or ($v -is [System.Collections.IEnumerable] -and $v -isnot [hashtable] -and $v -isnot [pscustomobject])) {
return ConvertTo-StringList -InputObject $v -PropertyNames @()
}
}
$single = "$InputObject".Trim()
if ($single) {
return , @($single)
}
return @()
}

if ($InputObject -is [pscustomobject]) {
foreach ($name in $PropertyNames) {
if ($InputObject.PSObject.Properties.Name -contains $name) {
return ConvertTo-StringList -InputObject $InputObject.$name -PropertyNames $PropertyNames
}
}
foreach ($p in $InputObject.PSObject.Properties) {
$v = $p.Value
if ($null -eq $v) { continue }
if ($v -is [string] -or ($v -is [System.Collections.IEnumerable] -and $v -isnot [hashtable] -and $v -isnot [pscustomobject])) {
return ConvertTo-StringList -InputObject $v -PropertyNames @()
}
}
$single = "$InputObject".Trim()
if ($single) {
return , @($single)
}
return @()
}

$t = "$InputObject".Trim()
if ($t) {
return , @($t)
}
return @()
}
78 changes: 78 additions & 0 deletions Modules/CIPPCore/Private/Test-CIPPConditionFilter.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
function Test-CIPPConditionFilter {
<#
.SYNOPSIS
Returns a sanitized PowerShell condition string for an audit log / delta query condition.
.DESCRIPTION
Validates operator and property name against allowlists, sanitizes input values,
then returns a safe condition string suitable for [ScriptBlock]::Create().

This replaces the old Invoke-Expression pattern which was vulnerable to code injection
through unsanitized user-controlled fields.
.PARAMETER Condition
A single condition object with Property.label, Operator.value, and Input.value.
.OUTPUTS
[string] A sanitized PowerShell condition string, or $null if validation fails.
.FUNCTIONALITY
Internal
#>
[CmdletBinding()]
[OutputType([string])]
param(
[Parameter(Mandatory = $true)]
$Condition
)

# Operator allowlist - only these PowerShell comparison operators are permitted
$AllowedOperators = @(
'eq', 'ne', 'like', 'notlike', 'match', 'notmatch',
'gt', 'lt', 'ge', 'le', 'in', 'notin',
'contains', 'notcontains'
)

# Property name validation - only alphanumeric, underscores, and dots allowed
$SafePropertyRegex = [regex]'^[a-zA-Z0-9_.]+$'

# Value sanitization - block characters that enable code injection
$UnsafeValueRegex = [regex]'[;|`\$\{\}]'

$propertyName = $Condition.Property.label
$operatorValue = $Condition.Operator.value.ToLower()
$inputValue = $Condition.Input.value

# Validate operator against allowlist
if ($operatorValue -notin $AllowedOperators) {
Write-Warning "Blocked invalid operator '$($Condition.Operator.value)' in condition for property '$propertyName'"
return $null
}

# Validate property name to prevent injection via property paths
if (-not $SafePropertyRegex.IsMatch($propertyName)) {
Write-Warning "Blocked invalid property name '$propertyName' in condition"
return $null
}

# Build sanitized condition string
if ($inputValue -is [array]) {
# Sanitize each array element
$sanitizedItems = foreach ($item in $inputValue) {
$itemStr = [string]$item
if ($UnsafeValueRegex.IsMatch($itemStr)) {
Write-Warning "Blocked unsafe value in array for property '$propertyName': '$itemStr'"
return $null
}
$itemStr -replace "'", "''"
}
if ($null -eq $sanitizedItems) { return $null }
$arrayAsString = $sanitizedItems | ForEach-Object { "'$_'" }
$value = "@($($arrayAsString -join ', '))"
} else {
$valueStr = [string]$inputValue
if ($UnsafeValueRegex.IsMatch($valueStr)) {
Write-Warning "Blocked unsafe value for property '$propertyName': '$valueStr'"
return $null
}
$value = "'$($valueStr -replace "'", "''")'"
}

return "`$(`$_.$propertyName) -$operatorValue $value"
}
Loading