Skip to content

Commit c085ee3

Browse files
MJVLbergmeisterChristoph Bergmeister
authored
Add AvoidUsingAllowUnencryptedAuthentication (#1857)
* Add AvoidUsingAllowUnencryptedAuthentication rule * Add AvoidUsingAllowUnencryptedAuthentication docs and tests * Update docs/Rules/AvoidUsingAllowUnencryptedAuthentication.md Co-authored-by: Christoph Bergmeister <c.bergmeister@gmail.com> * Fix code review suggestions * Fix md code styling * bump rule count in tests again * Update docs/Rules/AvoidUsingAllowUnencryptedAuthentication.md --------- Co-authored-by: Christoph Bergmeister <c.bergmeister@gmail.com> Co-authored-by: Christoph Bergmeister <c.bergmeister2@shell.com>
1 parent c06e005 commit c085ee3

6 files changed

+204
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Management.Automation.Language;
8+
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
9+
#if !CORECLR
10+
using System.ComponentModel.Composition;
11+
#endif
12+
using System.Globalization;
13+
14+
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
15+
{
16+
/// <summary>
17+
/// AvoidUsingAllowUnencryptedAuthentication: Avoid sending credentials and secrets over unencrypted connections.
18+
/// </summary>
19+
#if !CORECLR
20+
[Export(typeof(IScriptRule))]
21+
#endif
22+
public class AvoidUsingAllowUnencryptedAuthentication : AvoidParameterGeneric
23+
{
24+
/// <summary>
25+
/// Condition on the cmdlet that must be satisfied for the error to be raised
26+
/// </summary>
27+
/// <param name="CmdAst"></param>
28+
/// <returns></returns>
29+
public override bool CommandCondition(CommandAst CmdAst)
30+
{
31+
return true;
32+
}
33+
34+
/// <summary>
35+
/// Condition on the parameter that must be satisfied for the error to be raised.
36+
/// </summary>
37+
/// <param name="CmdAst"></param>
38+
/// <param name="CeAst"></param>
39+
/// <returns></returns>
40+
public override bool ParameterCondition(CommandAst CmdAst, CommandElementAst CeAst)
41+
{
42+
return CeAst is CommandParameterAst && String.Equals((CeAst as CommandParameterAst).ParameterName, "AllowUnencryptedAuthentication", StringComparison.OrdinalIgnoreCase);
43+
}
44+
45+
/// <summary>
46+
/// Retrieves the error message
47+
/// </summary>
48+
/// <param name="FileName"></param>
49+
/// <param name="CmdAst"></param>
50+
/// <returns></returns>
51+
public override string GetError(string fileName, CommandAst cmdAst)
52+
{
53+
return String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingAllowUnencryptedAuthenticationError);
54+
}
55+
56+
/// <summary>
57+
/// GetName: Retrieves the name of this rule.
58+
/// </summary>
59+
/// <returns>The name of this rule</returns>
60+
public override string GetName()
61+
{
62+
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.AvoidUsingAllowUnencryptedAuthenticationName);
63+
}
64+
65+
/// <summary>
66+
/// GetCommonName: Retrieves the common name of this rule.
67+
/// </summary>
68+
/// <returns>The common name of this rule</returns>
69+
public override string GetCommonName()
70+
{
71+
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingAllowUnencryptedAuthenticationCommonName);
72+
}
73+
74+
/// <summary>
75+
/// GetDescription: Retrieves the description of this rule.
76+
/// </summary>
77+
/// <returns>The description of this rule</returns>
78+
public override string GetDescription()
79+
{
80+
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingAllowUnencryptedAuthenticationDescription);
81+
}
82+
83+
/// <summary>
84+
/// GetSourceType: Retrieves the type of the rule: builtin, managed or module.
85+
/// </summary>
86+
public override SourceType GetSourceType()
87+
{
88+
return SourceType.Builtin;
89+
}
90+
91+
/// <summary>
92+
/// GetSeverity: Retrieves the severity of the rule: error, warning or information.
93+
/// </summary>
94+
/// <returns></returns>
95+
public override RuleSeverity GetSeverity()
96+
{
97+
return RuleSeverity.Warning;
98+
}
99+
100+
/// <summary>
101+
/// DiagnosticSeverity: Retrieves the severity of the rule of type DiagnosticSeverity: error, warning or information.
102+
/// </summary>
103+
/// <returns></returns>
104+
public override DiagnosticSeverity GetDiagnosticSeverity()
105+
{
106+
return DiagnosticSeverity.Warning;
107+
}
108+
109+
/// <summary>
110+
/// GetSourceName: Retrieves the module/assembly name the rule is from.
111+
/// </summary>
112+
public override string GetSourceName()
113+
{
114+
return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
115+
}
116+
}
117+
}

Rules/Strings.resx

+12
Original file line numberDiff line numberDiff line change
@@ -1206,4 +1206,16 @@
12061206
<data name="AvoidExclaimOperatorCorrectionDescription" xml:space="preserve">
12071207
<value>Replace ! with -not</value>
12081208
</data>
1209+
<data name="AvoidUsingAllowUnencryptedAuthenticationCommonName" xml:space="preserve">
1210+
<value>Avoid AllowUnencryptedAuthentication Switch</value>
1211+
</data>
1212+
<data name="AvoidUsingAllowUnencryptedAuthenticationDescription" xml:space="preserve">
1213+
<value>Avoid sending credentials and secrets over unencrypted connections.</value>
1214+
</data>
1215+
<data name="AvoidUsingAllowUnencryptedAuthenticationError" xml:space="preserve">
1216+
<value>The insecure AllowUsingUnencryptedAuthentication switch was used. This should be avoided except for compatability with legacy systems.</value>
1217+
</data>
1218+
<data name="AvoidUsingAllowUnencryptedAuthenticationName" xml:space="preserve">
1219+
<value>AvoidUsingAllowUnencryptedAuthentication</value>
1220+
</data>
12091221
</root>

Tests/Engine/GetScriptAnalyzerRule.tests.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Describe "Test Name parameters" {
6363

6464
It "get Rules with no parameters supplied" {
6565
$defaultRules = Get-ScriptAnalyzerRule
66-
$expectedNumRules = 69
66+
$expectedNumRules = 70
6767
if ($PSVersionTable.PSVersion.Major -le 4)
6868
{
6969
# for PSv3 PSAvoidGlobalAliases is not shipped because
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
BeforeAll {
5+
$settings = @{
6+
IncludeRules = @('PSAvoidUsingAllowUnencryptedAuthentication')
7+
Rules = @{
8+
PSAvoidUsingAllowUnencryptedAuthentication = @{
9+
Enable = $true
10+
}
11+
}
12+
}
13+
}
14+
15+
Describe "AvoidUsingAllowUnencryptedAuthentication" {
16+
Context "When there are violations" {
17+
It "detects unencrypted authentication violations" {
18+
(Invoke-ScriptAnalyzer -ScriptDefinition 'Invoke-WebRequest foo -AllowUnencryptedAuthentication' -Settings $settings).Count | Should -Be 1
19+
(Invoke-ScriptAnalyzer -ScriptDefinition 'Invoke-RestMethod foo -AllowUnencryptedAuthentication' -Settings $settings).Count | Should -Be 1
20+
(Invoke-ScriptAnalyzer -ScriptDefinition 'iwr foo -AllowUnencryptedAuthentication' -Settings $settings).Count | Should -Be 1
21+
}
22+
23+
It "detects arbitrary cmdlets" {
24+
(Invoke-ScriptAnalyzer -ScriptDefinition 'Invoke-CustomWebRequest foo -AllowUnencryptedAuthentication' -Settings $settings).Count | Should -Be 1
25+
}
26+
27+
}
28+
29+
Context "When there are no violations" {
30+
It "does not flag safe usage" {
31+
(Invoke-ScriptAnalyzer -ScriptDefinition 'Invoke-WebRequest foo' -Settings $settings).Count | Should -Be 0
32+
}
33+
34+
It "does not flag cases with unrelated parameters" {
35+
(Invoke-ScriptAnalyzer -ScriptDefinition 'Invoke-WebRequest foo -Method Get' -Settings $settings).Count | Should -Be 0
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
description: Avoid sending credentials and secrets over unencrypted connections
3+
ms.custom: PSSA v1.22.0
4+
ms.date: 11/06/2022
5+
ms.topic: reference
6+
title: AvoidUsingAllowUnencryptedAuthentication
7+
---
8+
# AvoidUsingAllowUnencryptedAuthentication
9+
10+
**Severity Level: Warning**
11+
12+
## Description
13+
14+
Avoid using the `AllowUnencryptedAuthentication` switch on `Invoke-WebRequest`, `Invoke-RestMethod`, and other webrequest cmdlets, which sends credentials and secrets over unencrypted connections.
15+
This should be avoided except for compatability with legacy systems.
16+
17+
For more details, see the documentation warning [here](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/invoke-webrequest#-allowunencryptedauthentication).
18+
19+
## How
20+
21+
Avoid using the `AllowUnencryptedAuthentication` switch.
22+
23+
## Example 1
24+
25+
### Wrong
26+
27+
```powershell
28+
Invoke-WebRequest foo -AllowUnencryptedAuthentication
29+
```
30+
31+
### Correct
32+
33+
```powershell
34+
Invoke-WebRequest foo
35+
```

docs/Rules/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The PSScriptAnalyzer contains the following rule definitions.
2727
| [AvoidSemicolonsAsLineTerminators](./AvoidSemicolonsAsLineTerminators.md) | Warning | No | |
2828
| [AvoidShouldContinueWithoutForce](./AvoidShouldContinueWithoutForce.md) | Warning | Yes | |
2929
| [AvoidTrailingWhitespace](./AvoidTrailingWhitespace.md) | Warning | Yes | |
30+
| [AvoidUsingAllowUnencryptedAuthentication](./AvoidUsingAllowUnencryptedAuthentication.md) | Warning | Yes | |
3031
| [AvoidUsingBrokenHashAlgorithms](./AvoidUsingBrokenHashAlgorithms.md) | Warning | Yes | |
3132
| [AvoidUsingCmdletAliases](./AvoidUsingCmdletAliases.md) | Warning | Yes | Yes<sup>2</sup> |
3233
| [AvoidUsingComputerNameHardcoded](./AvoidUsingComputerNameHardcoded.md) | Error | Yes | |

0 commit comments

Comments
 (0)