├── .github └── workflows │ └── CI.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── action.yml ├── test-data └── unsecure-script.ps1 └── workflow.yml /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the main branch 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | 21 | # The type of runner that the job will run on 22 | runs-on: ${{ matrix.os }} 23 | strategy: 24 | matrix: 25 | os: [ubuntu-latest, windows-latest, macos-latest] 26 | # Steps represent a sequence of tasks that will be executed as part of the job 27 | steps: 28 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 29 | - uses: actions/checkout@v2 30 | 31 | - name: Run PSScriptAnalyzer 32 | uses: ./ # Uses an action in the root directory 33 | with: 34 | path: '.\' 35 | recurse: true 36 | includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' 37 | output: 'results.sarif' 38 | - name: Upload SARIF results file 39 | uses: github/codeql-action/upload-sarif@v1 40 | with: 41 | sarif_file: results.sarif 42 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PSScriptAnalyzer Action 2 | Github action for running PSScriptAnalyzer and use ConvertToSARIF to generate a SARIF file. 3 | 4 | # Getting Started 5 | To run this action add the step below in your GitHub Action: 6 | ```yaml 7 | - name: Run PSScriptAnalyzer 8 | uses: microsoft/psscriptanalyzer-action@v1.0 9 | with: 10 | path: .\ 11 | recurse: true 12 | output: results.sarif 13 | ``` 14 | The above yaml code scans all the code in your repository and outputs the results to `result.sarif` at the CWD. 15 | 16 | # YAML 17 | See the [input section](#Inputs) for more info about the inputs. 18 | ```yaml 19 | - name: Run PSScriptAnalyzer 20 | uses: psscriptanalyzer-action 21 | with: 22 | path: 23 | customRulePath: 24 | recurseCustomRulePath: 25 | excludeRule: 26 | includeDefaultRules: 27 | includeRule: 28 | severity: 29 | recurse: 30 | suppressedOnly: 31 | fix: 32 | enableExit: 33 | settings: 34 | output: 35 | ignorePattern: 36 | ``` 37 | 38 | # Inputs 39 | The inputs for the action. The inputs `output` and `ignorePattern` are action specific. The rest are mapped to the parameters of PSScriptAnalyzer. 40 | Every input is of type string. 41 | 42 | To provide an array follow the format `'"value.fake", "value1.fake", ....'` 43 | ## path 44 | Specifies the path to the scripts or module to be analyzed. Wildcard characters are supported. Default value is: `.\`. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-path). 45 | ```yaml 46 | with: 47 | path: .\ 48 | ``` 49 | ```yaml 50 | with: 51 | path: .\src 52 | ``` 53 | ## customRulePath 54 | Specifies the path to the scripts or module to be analyzed. Wildcard characters are supported. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-customrulepath). 55 | ```yaml 56 | with: 57 | customRulePath: '".\customRule.ps1"' 58 | ``` 59 | ```yaml 60 | with: 61 | customRulePath: '".\customRule.ps1", "customRule2.ps1"' 62 | ``` 63 | 64 | ## recurseCustomRulePath 65 | Uses only the custom rules defined in the specified paths to the analysis. To still use the built-in rules, add the -IncludeDefaultRules switch. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-recursecustomrulepath). 66 | ```yaml 67 | with: 68 | recurseCustomRulePath: true 69 | ``` 70 | ```yaml 71 | with: 72 | recurseCustomRulePath: false 73 | ``` 74 | 75 | ## excludeRule 76 | Omits the specified rules from the Script Analyzer test. Wildcard characters are supported. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-excluderule). 77 | ```yaml 78 | with: 79 | # exclude one rule 80 | excludeRule: '"PSAvoidLongLines"' 81 | ``` 82 | ```yaml 83 | with: 84 | # exclude multiple rules 85 | excludeRule: '"PSAvoidLongLines", "PSAlignAssignmentStatement"' 86 | ``` 87 | 88 | ## includeDefaultRules 89 | Uses only the custom rules defined in the specified paths to the analysis. To still use the built-in rules, add the -IncludeDefaultRules switch. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-includedefaultrules). 90 | ```yaml 91 | with: 92 | includeDefaultRules: true 93 | ``` 94 | ```yaml 95 | with: 96 | includeDefaultRules: false 97 | ``` 98 | 99 | ## includeRule 100 | Runs only the specified rules in the Script Analyzer test. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-includerule). 101 | ```yaml 102 | with: 103 | # Include one rule 104 | includeRule: '"PSAvoidUsingInvokeExpression"' 105 | ``` 106 | ```yaml 107 | with: 108 | # Include multiple rules 109 | includeRule: '"PSAvoidUsingInvokeExpression", "PSAvoidUsingConvertToSecureStringWithPlainText"' 110 | ``` 111 | 112 | ## severity 113 | After running Script Analyzer with all rules, this parameter selects rule violations with the specified severity. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-severity). 114 | ```yaml 115 | with: 116 | # Report only rule violations with error severity 117 | severity: '"Error"' 118 | ``` 119 | ```yaml 120 | with: 121 | # Report only rule violations with error and warning severity 122 | severity: '"Error", "Warning"' 123 | ``` 124 | ## recurse 125 | Script Analyzer on the files in the Path directory and all subdirectories recursively. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-recurse). 126 | ```yaml 127 | with: 128 | recurse: true 129 | ``` 130 | ```yaml 131 | with: 132 | recurse: false 133 | ``` 134 | 135 | ## suppressedOnly 136 | Returns rules that are suppressed, instead of analyzing the files in the path. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-suppressedonly). 137 | ```yaml 138 | with: 139 | suppressedOnly: true 140 | ``` 141 | ```yaml 142 | with: 143 | suppressedOnly: false 144 | ``` 145 | 146 | ## fix 147 | Fixes certain warnings which contain a fix in their DiagnosticRecord. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-fix). 148 | ```yaml 149 | with: 150 | fix: true 151 | ``` 152 | ```yaml 153 | with: 154 | fix: false 155 | ``` 156 | 157 | ## enableExit 158 | Exits PowerShell and returns an exit code equal to the number of error records. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-enableexit). 159 | ```yaml 160 | with: 161 | enableExit: true 162 | ``` 163 | 164 | ```yaml 165 | with: 166 | enableExit: false 167 | ``` 168 | 169 | ## settings 170 | File path that contains user profile or hash table for ScriptAnalyzer. Does not support passing a hashtable as an argument. More info [here](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Cmdlets/Invoke-ScriptAnalyzer.md#-settings). 171 | ```yaml 172 | with: 173 | settings: .\settings.psd1 174 | ``` 175 | 176 | ## output 177 | File path that defines where the SARIF output will be stored. 178 | ```yaml 179 | with: 180 | output: results.sarif 181 | ``` 182 | 183 | ## ignorePattern 184 | Exclude specific files from the SARIF results. Uses regex pattern. 185 | ```yaml 186 | with: 187 | # Any file or folder that have the name test will not be present in the SARIF file. 188 | ignorePattern: 'tests' 189 | ``` 190 | 191 | # Project 192 | 193 | > This repo has been populated by an initial template to help get you started. Please 194 | > make sure to update the content to build a great experience for community-building. 195 | 196 | As the maintainer of this project, please make a few updates: 197 | 198 | - Improving this README.MD file to provide a great experience 199 | - Updating SUPPORT.MD with content about this project's support experience 200 | - Understanding the security reporting process in SECURITY.MD 201 | - Remove this section from the README 202 | 203 | ## Contributing 204 | 205 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 206 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 207 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 208 | 209 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 210 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 211 | provided by the bot. You will only need to do this once across all repos using our CLA. 212 | 213 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 214 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 215 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 216 | 217 | ## Trademarks 218 | 219 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft 220 | trademarks or logos is subject to and must follow 221 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). 222 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. 223 | Any use of third-party trademarks or logos are subject to those third-party's policies. 224 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/spot](https://aka.ms/spot). CSS will work with/help you to determine next steps. More details also available at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). 7 | - **Not sure?** Fill out a SPOT intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Run PSScriptAnalyzer' 2 | author: 'ankatopo' 3 | description: 'Run PSScriptAnalyzer' 4 | branding: 5 | icon: "check" 6 | color: "gray-dark" 7 | inputs: 8 | path: 9 | description: 'Specifies the path to the scripts or module to be analyzed. Wildcard characters are supported.' 10 | required: true 11 | default: '.\' 12 | customRulePath: 13 | description: 'Uses only the custom rules defined in the specified paths to the analysis. To still use the built-in rules, add the -IncludeDefaultRules switch.' 14 | required: false 15 | recurseCustomRulePath: 16 | description: 'Adds rules defined in subdirectories of the CustomRulePath location.' 17 | required: false 18 | excludeRule: 19 | description: 'Omits the specified rules from the Script Analyzer test. Wildcard characters are supported.' 20 | required: false 21 | includeDefaultRules: 22 | description: 'Invoke default rules along with Custom rules.' 23 | required: false 24 | includeRule: 25 | description: 'Runs only the specified rules in the Script Analyzer test.' 26 | required: false 27 | severity: 28 | description: 'After running Script Analyzer with all rules, this parameter selects rule violations with the specified severity.' 29 | required: false 30 | recurse: 31 | description: 'Runs Script Analyzer on the files in the Path directory and all subdirectories recursively.' 32 | required: false 33 | suppressedOnly: 34 | description: 'Returns rules that are suppressed, instead of analyzing the files in the path.' 35 | required: false 36 | fix: 37 | description: 'Fixes certain warnings which contain a fix in their DiagnosticRecord.' 38 | required: false 39 | enableExit: 40 | description: 'Exits PowerShell and returns an exit code equal to the number of error records.' 41 | required: false 42 | settings: 43 | description: 'File path that contains user profile or hash table for ScriptAnalyzer.' 44 | required: false 45 | output: 46 | description: 'Specifies where the path for the sarif file' 47 | required: true 48 | default: 'results.sarif' 49 | ignorePattern: 50 | description: 'Exclude specific files from the sarif results. Uses regex pattern.' 51 | required: false 52 | runs: 53 | using: "composite" 54 | steps: 55 | - name: Run PSScriptAnalyzer and ConvertToSARIF 56 | shell: pwsh 57 | run: | 58 | $analyzerModule = Get-Module -ListAvailable -Name PSScriptAnalyzer 59 | if ($null -eq $analyzerModule) { 60 | Install-Module -Name PSScriptAnalyzer -Force 61 | } 62 | 63 | $sarifModule = Get-Module -ListAvailable -Name ConvertToSARIF 64 | if ($null -eq $sarifModule) { 65 | Install-Module -Name ConvertToSARIF -Force 66 | } 67 | Import-Module -Name ConvertToSARIF -Force 68 | 69 | $htPSA = [ordered]@{ Path = '${{ inputs.path }}'; } 70 | Write-Output "Modules installed, now running tests." 71 | if(![string]::IsNullOrEmpty('${{ inputs.customRulePath }}')) { $htPSA.add('CustomRulePath', @(${{ inputs.customRulePath }})) } 72 | if(![string]::IsNullOrEmpty('${{ inputs.recurseCustomRulePath }}')) { $htPSA.add('RecurseCustomRulePath', $true) } 73 | if(![string]::IsNullOrEmpty('${{ inputs.excludeRule }}')) { $htPSA.add('ExcludeRule', @(${{ inputs.excludeRule }})) } 74 | if(![string]::IsNullOrEmpty('${{ inputs.includeDefaultRules }}') -and '${{ inputs.includeDefaultRules }}' -ne 'false') { $htPSA.add('IncludeDefaultRules', $true) } 75 | if(![string]::IsNullOrEmpty('${{ inputs.includeRule }}')) { $htPSA.add('IncludeRule', @(${{ inputs.includeRule }})) } 76 | if(![string]::IsNullOrEmpty('${{ inputs.severity }}')) { $htPSA.add('Severity', @(${{ inputs.severity }})) } 77 | if(![string]::IsNullOrEmpty('${{ inputs.recurse }}') -and '${{ inputs.includeDefaultRules }}' -ne 'false') { $htPSA.add('Recurse', $true) } 78 | if(![string]::IsNullOrEmpty('${{ inputs.suppressedOnly }}')) { $htPSA.add('SuppressedOnly', $true) } 79 | if(![string]::IsNullOrEmpty('${{ inputs.fix }}')) { $htPSA.add('Fix', $true) } 80 | if(![string]::IsNullOrEmpty('${{ inputs.enableExit }}')) { $htPSA.add('EnableExit', $true) } 81 | if(![string]::IsNullOrEmpty('${{ inputs.settings }}')) { $htPSA.add('Settings', '${{ inputs.settings }}') } 82 | $htCTS = [ordered]@{ FilePath = '${{ inputs.output }}'; } 83 | if(![string]::IsNullOrEmpty('${{ inputs.ignorePattern }}')) { $htCTS.add('IgnorePattern', '${{ inputs.ignorePattern }}') } 84 | Invoke-ScriptAnalyzer @htPSA | ConvertTo-SARIF @htCTS 85 | -------------------------------------------------------------------------------- /test-data/unsecure-script.ps1: -------------------------------------------------------------------------------- 1 | ConvertTo-SecureString "fake" -AsPlainText -Force 2 | -------------------------------------------------------------------------------- /workflow.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/microsoft/psscriptanalyzer-action 2 | # For more information on PSScriptAnalyzer in general, see 3 | # https://github.com/PowerShell/PSScriptAnalyzer 4 | 5 | name: PSScriptAnalyzer Scan 6 | 7 | on: 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | jobs: 14 | build: 15 | name: PSScriptAnalyzer Scan 16 | runs-on: ubuntu-latest 17 | steps: 18 | # Checkout the repository to the GitHub Actions runner 19 | - name: Checkout code 20 | uses: actions/checkout@v2 21 | 22 | - name: Run PSScriptAnalyzer 23 | uses: ./ 24 | with: 25 | # Check https://github.com/microsoft/psscriptanalyzer-action for more info about the options. 26 | # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. 27 | path: .\ 28 | recurse: true 29 | # Include your own basic security rules. Removing this option will run all the rules 30 | includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' 31 | output: results.sarif 32 | 33 | # Upload the SARIF file generated in the previous step 34 | - name: Upload SARIF results file 35 | uses: github/codeql-action/upload-sarif@v1 36 | with: 37 | sarif_file: results.sarif 38 | --------------------------------------------------------------------------------