0.26.0: fix what the claims audit found, in code and help - #1
Merged
Merged
Conversation
…ownPath resolved against the wrong directory Test-IntuneDeployedScript and Compare-IntuneDeployedScript overwrote their Settings parameter with a body-level $settings hashtable (variable names are case-insensitive) and then checked $PSBoundParameters inside a nested function, where it is the nested function's own; the analysis and the settings comparison never saw -Settings. -Id without -Name matched every policy because -Name defaults to '*'. Get-IntuneScriptHealth wrote a relative -MarkdownPath against the process directory instead of the PowerShell location. Each has a regression test.
Repair-IntuneScript and Test-IntuneScript enumerated a folder through ForEach-Object -MemberName, which honours -WhatIf and returned nothing. Repair decoded a BOM-less non-UTF-8 file as UTF-8 and wrote U+FFFD in place of every non-ASCII character; it now reads such a file in the ANSI code page (Get-IslOemEncoding -Kind ANSI) and the encoding rule reports it as ANSI, Information, with the same fix. A type declared in a directive is declared, so it earns no assumed-context note. An explicit -IncludeRule sets the settings file's exclusions aside. Should-PassIntuneAnalysis takes a pipeline of files. The SARIF export gives a rule the level of its most severe finding, writes an absolute file URI for a script outside -Root, and resolves a relative -Path against the PowerShell location. The harness throws for a script that does not exist. Get-IntuneAgentTimeline -Id keeps the timeline whose id it is and counts a relationship report as an outcome. The drift compare is case-sensitive. A user-context app on All devices is flagged like one on a device group. Health reads 'assigned to nobody' from the assignments, so -SkipAnalysis keeps it. A filter value no device reports is 'matches every device' for -ne and -notIn. Only -Confirm:$false silences a prompt; $ErrorActionPreference = 'Stop' is not a guard; a module the parser cannot find is not PowerShell 7 syntax; two parameters that exist on neither host left the 7-only table; the size rule names Win32 scripts and says their limits are assumed; a message typo. The rule reference keeps literal $names. The manifest description names the whole module; the Duration column shows days; the workflow template splits SCRIPT_PATHS in both jobs; two stray empty files are gone. Every fix has a test.
…e code does Every passage the claims audit flagged is corrected: what each result carries (RunAs, the stderr tail as IntuneError, SignatureStatus always present), the complete status lists, the events Get-IntuneAgentLog names and its Id rule, what -SkipRegistry leaves out, the ARM64 note on the x64 default, the base requirements Test-IntuneWin32Requirement covers, how names are matched and which local files count as NotInTenant, the Attention rules, the Applied count under -WhatIf, the SARIF rule level, the filter examples' full output, the file-name inference rules, and the settings precedence. The README's repository links are absolute because the README ships and docs/ and Validation/ do not. An explicit -EnforceSignatureCheck:$false is explicit. ModuleVersion 0.26.0 with the changelog entry, the manifest release note and the CLAUDE.md invariant on parameter shadowing.
…starts; scopes as the Graph reference lists them Verified on the lab device as SYSTEM with the branch module: -Context System runs in session 0 as NT AUTHORITY\SYSTEM, -Credential runs interactively in the account's own session when it has one, the task and the run folder are removed afterwards. The stored-password path for an account without the batch logon right no longer answers 0x80070569 there: the task sits Ready with 0x00041303 and no error, and the launcher waited out its timeout. Five seconds of that after Start-ScheduledTask is now the refusal, with a test and a Findings note. The Graph reference lists creating an export job as a write, so Get-IntuneScriptHealth's help and warning name the ReadWrite scopes instead of DeviceManagementManagedDevices.Read.All; remediations need DeviceManagementScripts.Read.All, which two examples omitted; the group member read needs only GroupMember.ReadBasic.All. Live against the dev tenant: pre-flight 106 policies in 106 s, health 16 policies in 24 s with the export at 11-17 s.
… as Graph shows them A remediation's changed result reaches Graph with the agent's next hourly report batch: a fix at 01:37:34 UTC on the lab device arrived at 02:42:58 UTC, seconds after the batch upload, and an unchanged result is never re-reported, so lastStateUpdateDateTime is the last change rather than the last run. Platform script states arrived 2-8 s after the device's log line, app install states 30-39 s after. The report line's Result codes, matched against Graph on both lab devices: 3 no issue, 4 the remediation ran (fixed or recurred), 5 the detection script failed; the timeline help had called 4 fixed and 3 failed. Findings carries the measurement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Version 0.26.0. A claims audit of the module: every statement the README, the 25 command help pages, the about topic, the generated rule reference, the examples and the changelog make about behaviour was checked against the source and, where it needs no tenant or elevation, by running it. Statements that needed a tenant, SYSTEM or a signed-in lab account were checked against the dev tenant and the lab device. This pull request fixes what did not hold, in code where the code was wrong and in the documentation where the text was, with a regression test for each code fix.
No command changes shape. Every fix restores behaviour the documentation already promised.
Code fixes
Test-IntuneDeployedScript,Compare-IntuneDeployedScript,Get-IntuneScriptHealth-Settingsnever reached the analysis or the settings comparison. A body-level$settingshashtable overwrote the parameter (variable names are case-insensitive), and$PSBoundParameterswas tested inside a nested function, where it is that function's own.-Idwithout-Nameselected every policy, because-Namedefaults to*and selection was name or id.-Idalone selects by id.Repair-IntuneScript,Test-IntuneScriptForEach-Object -MemberName, which honours-WhatIf;Repair -Path <folder> -WhatIfreturned nothing.Repair-IntuneScript,IslEncodingIssueTest-IntuneScriptExcludeRulebeat an explicit-IncludeRule;-EnforceSignatureCheck:$falsewas not explicit.Should-PassIntuneAnalysisExport-IntuneFindingSarifwarning; a finding outside-Rootwas written as an escaped relative URI under the root; a relative-Pathwas resolved against the process directory (as wasGet-IntuneScriptHealth -MarkdownPath).-Credential0x80070569; on the lab device it sits Ready with0x00041303("has not run yet") and no error, and the launcher waited out the whole timeout.Start-ScheduledTaskis reported as the refusal, with the same hint.Get-IntuneAgentTimeline-Idreturned every timeline whose lines mentioned the id (a relationship report names two apps); a relationship report was never an outcome.Compare-IntuneDeployedScriptTest-IntuneDeployedScriptGet-IntuneScriptHealth-SkipAnalysiscalled an unassigned policy Healthy, because the check read a finding.IslFilterIssuecalled-ne/-notInwith an unreported value "never matches";IslInteractiveCalltook a bare-Confirmas silencing;IslOutputIssuetook$ErrorActionPreference = 'Stop'as a guard;IslPowerShell7Syntaxreportedusing module <missing>as syntax and listed two parameters that exist on neither host;IslScriptSizecalled Win32 scripts remediations.Durationcolumn dropped days; the workflow template did not splitSCRIPT_PATHSin its runtime job; two empty files underdocs/; the rule reference replaced literal$PSScriptRootwith<value>.Documentation fixes
DeviceManagementScripts.Read.Allfor remediations and platform scripts (two examples omitted it),DeviceManagementConfiguration.Read.Allfor assignment filters,DeviceManagementApps.Read.Allfor apps,GroupMember.ReadBasic.Allfor the member read. Creating an export job is listed as a write, soGet-IntuneScriptHealthnames the ReadWrite scopes instead ofDeviceManagementManagedDevices.Read.All, in the help and in its warning.RunAson every harness result,IntuneErroras the stderr tail,SignatureStatusalways present), the complete status lists, the eventsGet-IntuneAgentLognames and its Id rule, what-SkipRegistryleaves out, the ARM64 note on the x64 default, the base requirementsTest-IntuneWin32Requirementcovers, name matching andNotInTenantsemantics, the Attention rules,Appliedunder-WhatIf, the SARIF rule level, the assignment-filter examples' full output, the file-name inference rules, the settings precedence.docs/andValidation/do not.CLAUDE.mdrecords the parameter-shadowing invariant.Validation/Findings.mdrecords the 2026-09-29 re-check of the stored-password path.Verification
docs/Rules.mdregenerated.Build/Publish-Module.ps1 -WhatIfstages and verifies 0.26.0.Test-IntuneDeployedScriptover 106 policies in 106 s;Compare-IntuneDeployedScriptin 2 s;Get-IntuneScriptHealthover 16 policies in 24 s with the app install export at 11-17 s.-Context Systemruns in session 0 asNT AUTHORITY\SYSTEMwith the system profile;-Credentialfor an account holding a console session runs interactively in that session (RunAs(Interactive)); the stored-password path for the same account without the batch logon right is refused and reported in 11 s; no scheduled task and no run folder remain afterwards.lastStateUpdateDateTimeis the last change, not the last run. The device's report line carries Result 4 for a fix and for a recurrence alike; the timeline help now says so.After merge,
git tag v0.26.0 && git push origin v0.26.0publishes.