Skip to content

feat(repair): eight more findings carry the edit their message asks for - #20

Merged
fadwen merged 1 commit into
fix/graph-retry-and-group-countfrom
feat/repair-mechanical-fixes
Oct 6, 2026
Merged

fadwen merged 1 commit into
fix/graph-retry-and-group-countfrom
feat/repair-mechanical-fixes

Conversation

@fadwen

@fadwen fadwen commented Oct 6, 2026

Copy link
Copy Markdown
Owner

Summary

Repair-IntuneScript applied three fixes: the script-scope return, the encoding and the padded requirement value. Thirteen other findings told the reader what to change in words a program could apply, and left the change to them. Eight of them now carry that edit as a Fix, so Repair-IntuneScript makes it. Each edit is the one the finding's own message asks for; where it would leave a broken statement, the finding has no fix and stays. Messages, severities and evidence are unchanged, so docs/Rules.md is unchanged.

Stacked on #19 (base branch); the diff is this change only. Merge #16 through #19, then this.

Changes

Rule Edit Withheld when
IslInteractiveCall -Force on Install-Module, Install-PackageProvider, Install-Package, Update-Module, Uninstall-Module; -Confirm:$false on Register-PSRepository the call is Set-ExecutionPolicy, which IslExecutionPolicyCall removes instead
IslInteractiveCall Get-Credential -Credential $x, where $x can only be a credential (#13), becomes $x
IslExecutionPolicyCall the Set-ExecutionPolicy statement is removed it is inside a pipeline, or a value
IslOutputIssue -ErrorAction SilentlyContinue on the probing cmdlet, in Win32 detection and requirement scripts
IslExitCodeIssue exit N becomes exit 1, the value Intune reads it as
IslArchitectureIssue $env:ProgramFiles becomes $env:ProgramW6432, set in 32-bit and 64-bit processes alike
IslArm64Assumption 'AMD64' as the pattern of a -match becomes `'ARM64 AMD64'`
IslRelativePath $PWD becomes $PSScriptRoot a member follows it, as in $PWD.Path, which $PSScriptRoot has not
IslPowerShell7Syntax the #Requires -Version 7 line is removed

The #Requires finding now sits on its line rather than on the whole script, which the fix needs and which reads better. Not taken on: the relative path literal (needs Join-Path $PSScriptRoot, a change of shape), 'Program Files' and System32 in a literal (a literal to an expression, or a folder that exists only in a 32-bit process on a 64-bit Windows), and utf8NoBOM (changing it changes the bytes written).

Help, README and the changelog list the edits; MAML rebuilt.

Verification

  • Unit and integration suites pass on PowerShell 7.6.6; the repair, rule and rule-reference tests pass on Windows PowerShell 5.1 (143 of 143). PSScriptAnalyzer (Error and Warning) is clean; no line over 115 characters; docs/Rules.md regenerates unchanged.
  • Tests: each of the ten edits applied through Repair-IntuneScript with the file's text checked afterwards and no fixable finding left; the four withheld cases, each with its finding still reported and the file untouched.

Notes

  • Two edits on the same text, such as a Set-ExecutionPolicy call reported by both IslExecutionPolicyCall and IslInteractiveCall, would be skipped by the repair's text check with a warning; that is why the second rule gives that call no -Force.
  • -ErrorAction SilentlyContinue is attached to the first unguarded cmdlet only, as the finding is; a script with several gets one per repair run.

@fadwen fadwen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Notes on the lines whose reason the diff does not show.

}
# The switch the message asks for, added to the call. Set-ExecutionPolicy gets none: the
# agent launches with -ExecutionPolicy Bypass, and IslExecutionPolicyCall removes the call
if ($commandName -ne 'Set-ExecutionPolicy') {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Two fixes on one extent collide: Repair-IntuneScript applies edits from the end of the file and checks each against the current text, so the second edit on the same call would be skipped with a warning. IslExecutionPolicyCall removes the call; this rule steps aside for it.

# The call is removed when it is a statement on its own: in a pipeline, or as a value, taking
# it out would leave a broken statement with nothing to say so
$pipeline = $command.Parent
$alone = $pipeline.GetType().Name -eq 'PipelineAst' -and @($pipeline.PipelineElements).Count -eq 1 -and

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

NamedBlockAst is the script body or a begin/process/end block; StatementBlockAst is the body of an if, a loop, a try or a function. Anywhere else, a pipeline element, a sub-expression, an assignment's right side, the empty replacement would leave a syntax error.

# would match nothing at all
$parent = $literal.Parent
$matched = $parent.GetType().Name -eq 'BinaryExpressionAst' -and
"$($parent.Operator)" -in 'Imatch', 'Inotmatch', 'Cmatch', 'Cnotmatch' -and $parent.Right -eq $literal

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The literal has to be the right operand: as the left operand of -match it is the input, not the pattern, and an alternation there would be compared against the variable's text.

Evidence = ('exit 2 and exit -1 both triggered the remediation and ended as Recurred ' +
'(REM-EXIT-2, REM-EXIT-NEG1); docs say only exit 1 does')
# Intune reads every non-zero exit as 1 already; writing it makes the report match
Fix = @{ Replacement = 'exit 1' }

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

exit 2 and exit -1 both ran the remediation and ended as Recurred (REM-EXIT-2, REM-EXIT-NEG1), so the device already behaves as if the script said exit 1; the edit changes the report, not the behaviour.

if ($requires -and $requires.RequiredPSVersion -and $requires.RequiredPSVersion.Major -ge 6) {
# The requirement is a comment token, not a node; the finding sits on that line, and the
# fix takes the line out. What the script then does under 5.1 the other findings say
$requiresToken = @($Context.Tokens | Where-Object {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ScriptRequirements knows the version but not where the line is; the token list does. The finding moved from the whole script to that line because a replacement needs an extent that is exactly the text to replace.

Evidence = $evidence
}
# $PSScriptRoot is a string where $PWD is a PathInfo, so $PWD.Path and the like get no edit
if ($variable.Parent.GetType().Name -ne 'MemberExpressionAst') {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

$PWD is a PathInfo and $PSScriptRoot a string: $PWD.Path would become $PSScriptRoot.Path, which is $null. The finding stays for a person to rewrite as $PSScriptRoot alone.

Repair-IntuneScript applied three fixes: the script-scope return, the
encoding and the padded requirement value. Thirteen other findings told
the reader what to change in words a program could apply, and left the
change to them. Eight of them now carry it as a Fix:

- IslInteractiveCall: -Force on Install-Module, Install-PackageProvider,
  Install-Package, Update-Module and Uninstall-Module; -Confirm:$false
  on Register-PSRepository; a Get-Credential -Credential call handed a
  credential that can only be one already built is replaced by that
  credential, since the call returns what it was handed.
- IslExecutionPolicyCall: the Set-ExecutionPolicy statement is removed.
- IslOutputIssue: -ErrorAction SilentlyContinue on the probing cmdlet.
- IslExitCodeIssue: exit N becomes exit 1, the value Intune reads it as.
- IslArchitectureIssue: $env:ProgramFiles becomes $env:ProgramW6432.
- IslArm64Assumption: 'AMD64' as the pattern of a -match becomes
  'ARM64|AMD64'.
- IslRelativePath: $PWD becomes $PSScriptRoot.
- IslPowerShell7Syntax: the #Requires -Version 7 line is removed, and
  the finding sits on that line rather than on the whole script.

Where the edit would leave a broken statement there is no fix and the
finding stays: Set-ExecutionPolicy inside a pipeline or as a value,
'AMD64' compared with -eq, $PWD followed by a member. Set-ExecutionPolicy
without -Force gets no -Force either; its removal is the fix. Messages,
severities and evidence are unchanged, so docs/Rules.md is unchanged.
@fadwen
fadwen added this pull request to stack #24 October 6, 2026 16:17
@fadwen
fadwen merged commit 836f806 into main Oct 6, 2026
4 checks passed
@fadwen
fadwen deleted the feat/repair-mechanical-fixes branch October 6, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant