Open rjmholt opened 4 years ago
I am really looking forward on this,
Few doubts,
[SuppressMessageAttribute('MyRules\FooBar', 'Justification')]
?
Would it be nice if there is a way to register all (the new design allows me to specify more than one namespace) my custom rule namespace in PSSA, so that it will internally handle all the rules from that space ? Or something like below ?
Invoke-ScriptAnalyzer -CustomRulePath some.psm1 -CustomRuleSpace MyRule
Feel free to ignore if this sounds bad
What would be the default if not overridden ? script name ?
Currently you can't construct the attribute without a name, so you're forced to provide it. However perhaps it makes sense to use a default like:
Rule
suffix if there is one for class-defined rulesAssuming that I override the custom rule namespace, how would the suppression look like ?
Yeah, suppression would look pretty much as you lay out.
Would it be nice if there is a way to register all (the new design allows me to specify more than one namespace) my custom rule namespace in PSSA, so that it will internally handle all the rules from that space ?
That's actually a really good consideration. The current settings proposal includes specifying a rule collection by path and then adding settings for each rule. You would then need to specify each rule you want to enable from that collection. Thinking on that now, that's cumbersome (if nicely explicit), but the problem is that any rules that require configuration settings must have those settings provided to be able to run. This makes me think that:
TryGetDefaultConfiguration()
or something)$Configuration
parameterFrom the start that I wrote my own custom rule a few years ago, I am still wondering how to install a rule in the environment. Meaning in the same scope as where PSScriptAnalyzer
is installed (everywhere where I have access to the Invoke-ScriptAnalyzer
command).
It looks like an too obvious question, so I am wondering if I might just completely missed something...
The document Creating custom rules, states:
PSScriptAnalyzer uses the Managed Extensibility Framework (MEF) to import all rules defined in the assembly. It can also consume rules written in PowerShell scripts.
but how do I install/add my custom PowerShell rule into the complete MEF framework?
When calling Invoke-ScriptAnalyzer, users can specify custom rules using the CustomizedRulePath parameter.
but I would like my PowerShell rule to be included automatically together with the standard rules
PSScriptAnalyzer.psd1
settings file but that is specific a folder hierarchy.
C:\Users\...\PowerShell\Modules\PSScriptAnalyzer\1.21.0\PSScriptAnalyzer.psd1PSScriptAnalyzer.psd1
but that will break the signature.(See also the section Here’s how to get this on your system: in the PowerShell Injection Hunter document, are that the minimum steps to install custom rules?)
@jegannathanmaniganadan,
Would it be nice if there is a way to register all (the new design allows me to specify more than one namespace) my custom rule namespace in PSSA, so that it will internally handle all the rules from that space ?
Exactly. In fact I would even expect PSScriptAnalyzer to automatically pickup any (PowerShell) rule that I installed in my environment (through a repository as the PowerShell Gallery) or manually, e.g.:
Import-Module .\AvoidDynamicVariables.psm1
IMO, it should be possible that the command Invoke-AnalyzeScript
filters the installed (PowerShell) custom rules from general commands e.g. like:
Get-Command -Verb Measure | Where-Object { $_.OutputType.Name -eq [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord] }
(or additional filters, e.g. sources that start or end with ".Rule
", e.g.: .\AvoidDynamicVariables.Rule.psm1
.)
And simply includes them when invoked.
PSScriptAnalyzer today supports external implementation of rules in PowerShell script.
Alongside the proposal to allow custom binary rules (https://github.com/PowerShell/PSScriptAnalyzer/issues/1543), PSScriptAnalyzer should also look at how rules written in PowerShell are implemented to ensure that PS script rules:
To address these goals, some proposals are:
Standard assumed arguments
PS script functions today have a very loose parameter contract that expects parameters that either end with the
Ast
suffix or theToken
suffix, this means:Instead script rules should be required to accept a clear and concrete set of parameters, similar to the way
TabExpansion2
does:Additional points:
[CmdletBinding()]
, positional and pipeline arguments don't matter to PSSA, as it will simply invoke rules withnew PSCommand().AddCommand(<script rule>).AddParameter("Ast", ast).AddParameter("Tokens", tokens).AddParameter("ScriptFilePath", scriptFilePath)
$Tokens
parameter should be immutable and ideally is aSystem.Collections.Generic.IReadOnlyList<Token>
. But this may not work well with PowerShell, so theToken[]
type may be preferable, with an understanding that mutating the token array is against the contractAttribute based rule definition
Today, PS script rules are:
To be consistent with https://github.com/PowerShell/PSScriptAnalyzer/issues/1543 and addressing https://github.com/PowerShell/PSScriptAnalyzer/issues/1545, rules instead should be declared with attributes:
We could also provide a type accelerator for this attribute to reduce it to
[Rule(...)]
.This attribute would provide the possibility of namespace override:
[Rule(..., Namespace = "MyRules")]
.Write-Diagnostic instead of needing to construct diagnostic objects
Today script rules must construct and emit diagnostic objects themselves. This means:
New-Object
callsInstead, a PowerShell-native solution would be for PSSA to introduce a new cmdlet that hooks back into the hosting script analyzer:
This command can:
Constrain and document the assumptions script rules can make about their executing context
Finally, today it's not clear what assumptions a script rule should make about the context in which it's run, in particular whether it shares context with the environment running
Invoke-ScriptAnalyzer
.So that PSSA can be as efficient as possible, the only assumptions script rules should make about their running environment are:
Invoke-ScriptAnalyzer
, since it may be hosted)In particular, some assumptions we don't want are:
Invoke-ScriptAnalyzer
Example
So an example of a rule defined with the new proposed API would be something like this:
This rule can be referenced with
MyRules/UseApprovedVerbs
in settings.Further considerations
IReadOnlyList<Token>
?process
blocks and have all inputs piped in withValueFromPipelineByPropertyName
? (This might improve performance)Write-Diagnostic
the right implementation? In particular, how do we ensure every diagnostic has aRuleInfo
object associated with it that links back to the providing rule (and ideally is referentially equal to allRuleInfo
objects referring to the same rule)?Write-Diagnostic
actually emit an object, or should it add objects to a list within PSSA?object
, since PowerShell will handle any type there?