Skip to content

Commit d836460

Browse files
authored
Improve guidance for use of SecureString (MicrosoftDocs#12097)
* Improve guidance for use of SecureString * Fix links
1 parent af2ebe0 commit d836460

File tree

2 files changed

+95
-78
lines changed

2 files changed

+95
-78
lines changed
Lines changed: 85 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: Advisory Development Guidelines
3-
ms.date: 10/05/2021
3+
ms.date: 05/22/2025
44
title: Advisory Development Guidelines
55
---
66
# Advisory Development Guidelines
@@ -19,31 +19,30 @@ guidelines.
1919
Because Windows PowerShell works directly with Microsoft .NET Framework objects, a .NET Framework
2020
object is often available that exactly matches the type the user needs to perform a particular
2121
operation. `InputObject` is the standard name for a parameter that takes such an object as input.
22-
For example, the sample `Stop-Proc` cmdlet in the [StopProc Tutorial](./stopproc-tutorial.md)
23-
defines an `InputObject` parameter of type Process that supports the input from the pipeline. The
24-
user can get a set of process objects, manipulate them to select the exact objects to stop, and then
25-
pass them to the `Stop-Proc` cmdlet directly.
22+
For example, the sample `Stop-Proc` cmdlet in the [StopProc Tutorial][03] defines an `InputObject`
23+
parameter of type Process that supports the input from the pipeline. The user can get a set of
24+
process objects, manipulate them to select the exact objects to stop, and then pass them to the
25+
`Stop-Proc` cmdlet directly.
2626

2727
### Support the Force Parameter (AD02)
2828

2929
Occasionally, a cmdlet needs to protect the user from performing a requested operation. Such a
3030
cmdlet should support a **Force** parameter to allow the user to override that protection if the
3131
user has permissions to perform the operation.
3232

33-
For example, the [Remove-Item](/powershell/module/microsoft.powershell.management/remove-item)
34-
cmdlet does not normally remove a read-only file. However, this cmdlet supports a **Force**
35-
parameter so a user can force removal of a read-only file. If the user already has permission to
36-
modify the read-only attribute, and the user removes the file, use of the **Force** parameter
37-
simplifies the operation. However, if the user does not have permission to remove the file, the
38-
**Force** parameter has no effect.
33+
For example, the [Remove-Item][18] cmdlet doesn't normally remove a read-only file. However, this
34+
cmdlet supports a **Force** parameter so a user can force removal of a read-only file. If the user
35+
already has permission to modify the read-only attribute, and the user removes the file, use of the
36+
**Force** parameter simplifies the operation. However, if the user doesn't have permission to remove
37+
the file, the **Force** parameter has no effect.
3938

4039
### Handle Credentials Through Windows PowerShell (AD03)
4140

4241
A cmdlet should define a `Credential` parameter to represent credentials. This parameter must be of
43-
type [System.Management.Automation.PSCredential](/dotnet/api/System.Management.Automation.PSCredential)
44-
and must be defined using a Credential attribute declaration. This support automatically prompts the
45-
user for the user name, for the password, or for both when a full credential is not supplied
46-
directly. For more information about the Credential attribute, see [Credential Attribute Declaration](./credential-attribute-declaration.md).
42+
type [System.Management.Automation.PSCredential][15] and must be defined using a Credential
43+
attribute declaration. This support automatically prompts the user for the user name, for the
44+
password, or for both when a full credential isn't supplied directly. For more information about the
45+
Credential attribute, see [Credential Attribute Declaration][01].
4746

4847
### Support Encoding Parameters (AD04)
4948

@@ -53,12 +52,13 @@ encoded in the binary form.
5352

5453
### Test Cmdlets Should Return a Boolean (AD05)
5554

56-
Cmdlets that perform tests against their resources should return a [System.Boolean](/dotnet/api/System.Boolean)
57-
type to the pipeline so that they can be used in conditional expressions.
55+
Cmdlets that perform tests against their resources should return a [System.Boolean][06] type to the
56+
pipeline so that they can be used in conditional expressions.
5857

5958
## Code Guidelines
6059

61-
The following guidelines should be considered when writing cmdlet code. When you find a guideline that applies to your situation, be sure to look at the Design guidelines for similar guidelines.
60+
The following guidelines should be considered when writing cmdlet code. When you find a guideline
61+
that applies to your situation, be sure to look at the Design guidelines for similar guidelines.
6262

6363
### Follow Cmdlet Class Naming Conventions (AC01)
6464

@@ -68,100 +68,116 @@ developers using Windows PowerShell because cmdlets are public types.
6868

6969
#### Define a Cmdlet in the Correct Namespace
7070

71-
You normally define the class for a cmdlet in a .NET Framework namespace that appends ".Commands" to
71+
You normally define the class for a cmdlet in a .NET Framework namespace that appends `.Commands` to
7272
the namespace that represents the product in which the cmdlet runs. For example, cmdlets that are
7373
included with Windows PowerShell are defined in the `Microsoft.PowerShell.Commands` namespace.
7474

7575
#### Name the Cmdlet Class to Match the Cmdlet Name
7676

7777
When you name the .NET Framework class that implements a cmdlet, name the class
78-
"*\<Verb>**\<Noun>**\<Command>*", where you replace the *\<Verb>* and *\<Noun>* placeholders with
79-
the verb and noun used for the cmdlet name. For example, the [Get-Process](/powershell/module/Microsoft.PowerShell.Management/Get-Process)
80-
cmdlet is implemented by a class called `GetProcessCommand`.
78+
`<Verb><Noun>Command`, where you replace the `<Verb>` and `<Noun>` placeholders with the verb and
79+
noun used for the cmdlet name. For example, the [Get-Process][17] cmdlet is implemented by a class
80+
called `GetProcessCommand`.
8181

8282
### If No Pipeline Input Override the BeginProcessing Method (AC02)
8383

84-
If your cmdlet does not accept input from the pipeline, processing should be implemented in the [System.Management.Automation.Cmdlet.BeginProcessing](/dotnet/api/System.Management.Automation.Cmdlet.BeginProcessing)
85-
method. Use of this method allows Windows PowerShell to maintain ordering between cmdlets. The first
86-
cmdlet in the pipeline always returns its objects before the remaining cmdlets in the pipeline get a
87-
chance to start their processing.
84+
If your cmdlet doesn't accept input from the pipeline, processing should be implemented in the
85+
[System.Management.Automation.Cmdlet.BeginProcessing][09] method. Use of this method allows Windows
86+
PowerShell to maintain ordering between cmdlets. The first cmdlet in the pipeline always returns its
87+
objects before the remaining cmdlets in the pipeline get a chance to start their processing.
8888

8989
### To Handle Stop Requests Override the StopProcessing Method (AC03)
9090

91-
Override the [System.Management.Automation.Cmdlet.StopProcessing](/dotnet/api/System.Management.Automation.Cmdlet.StopProcessing)
92-
method so that your cmdlet can handle stop signal. Some cmdlets take a long time to complete their
93-
operation, and they let a long time pass between calls to the Windows PowerShell runtime, such as
94-
when the cmdlet blocks the thread in long-running RPC calls. This includes cmdlets that make calls
95-
to the [System.Management.Automation.Cmdlet.WriteObject](/dotnet/api/System.Management.Automation.Cmdlet.WriteObject)
96-
method, to the [System.Management.Automation.Cmdlet.WriteError](/dotnet/api/System.Management.Automation.Cmdlet.WriteError)
97-
method, and to other feedback mechanisms that may take a long time to complete. For these cases the
98-
user might need to send a stop signal to these cmdlets.
91+
Override the [System.Management.Automation.Cmdlet.StopProcessing][12] method so that your cmdlet can
92+
handle stop signal. Some cmdlets take a long time to complete their operation, and they let a long
93+
time pass between calls to the Windows PowerShell runtime, such as when the cmdlet blocks the thread
94+
in long-running RPC calls. This includes cmdlets that make calls to the
95+
[System.Management.Automation.Cmdlet.WriteObject][14] method, to the
96+
[System.Management.Automation.Cmdlet.WriteError][13] method, and to other feedback mechanisms that
97+
may take a long time to complete. For these cases the user might need to send a stop signal to these
98+
cmdlets.
9999

100100
### Implement the IDisposable Interface (AC04)
101101

102-
If your cmdlet has objects that are not disposed of (written to the pipeline) by the [System.Management.Automation.Cmdlet.ProcessRecord](/dotnet/api/System.Management.Automation.Cmdlet.ProcessRecord)
103-
method, your cmdlet might require additional object disposal. For example, if your cmdlet opens a
104-
file handle in its [System.Management.Automation.Cmdlet.BeginProcessing](/dotnet/api/System.Management.Automation.Cmdlet.BeginProcessing)
105-
method and keeps the handle open for use by the [System.Management.Automation.Cmdlet.ProcessRecord](/dotnet/api/System.Management.Automation.Cmdlet.ProcessRecord)
106-
method, this handle has to be closed at the end of processing.
107-
108-
The Windows PowerShell runtime does not always call the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
109-
method. For example, the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
110-
method might not be called if the cmdlet is canceled midway through its operation or if a
111-
terminating error occurs in any part of the cmdlet. Therefore, the .NET Framework class for a cmdlet
112-
that requires object cleanup should implement the complete [System.IDisposable](/dotnet/api/System.IDisposable)
113-
interface pattern, including the finalizer, so that the Windows PowerShell runtime can call both the [System.Management.Automation.Cmdlet.EndProcessing](/dotnet/api/System.Management.Automation.Cmdlet.EndProcessing)
114-
and [System.IDisposable.Dispose*](/dotnet/api/System.IDisposable.Dispose) methods at the end of
115-
processing.
102+
If your cmdlet has objects that aren't disposed of (written to the pipeline) by the
103+
[System.Management.Automation.Cmdlet.ProcessRecord][11] method, your cmdlet might require additional
104+
object disposal. For example, if your cmdlet opens a file handle in its
105+
[System.Management.Automation.Cmdlet.BeginProcessing][09] method and keeps the handle open for use
106+
by the [System.Management.Automation.Cmdlet.ProcessRecord][11] method, this handle has to be closed
107+
at the end of processing.
108+
109+
The Windows PowerShell runtime doesn't always call the
110+
[System.Management.Automation.Cmdlet.EndProcessing][10] method. For example, the
111+
[System.Management.Automation.Cmdlet.EndProcessing][10] method might not be called if the cmdlet is
112+
canceled midway through its operation or if a terminating error occurs in any part of the cmdlet.
113+
Therefore, the .NET Framework class for a cmdlet that requires object cleanup should implement the
114+
complete [System.IDisposable][07] interface pattern, including the finalizer, so that the Windows
115+
PowerShell runtime can call both the [System.Management.Automation.Cmdlet.EndProcessing][10] and
116+
[System.IDisposable.Dispose*][08] methods at the end of processing.
116117

117118
### Use Serialization-friendly Parameter Types (AC05)
118119

119-
To support running your cmdlet on remote computers, use types that can be easily serialized on the
120-
client computer and then rehydrated on the server computer. The follow types are
121-
serialization-friendly.
120+
To support running your cmdlet on remote computers, use types that can be serialized on the client
121+
computer and then rehydrated on the server computer. The follow types are serialization-friendly.
122122

123123
Primitive types:
124124

125125
- Byte, SByte, Decimal, Single, Double, Int16, Int32, Int64, Uint16, UInt32, and UInt64.
126-
127126
- Boolean, Guid, Byte[], TimeSpan, DateTime, Uri, and Version.
128-
129127
- Char, String, XmlDocument.
130128

131129
Built-in rehydratable types:
132130

133131
- PSPrimitiveDictionary
134-
135132
- SwitchParameter
136-
137133
- PSListModifier
138-
139134
- PSCredential
140-
141135
- IPAddress, MailAddress
142-
143136
- CultureInfo
144-
145137
- X509Certificate2, X500DistinguishedName
146-
147138
- DirectorySecurity, FileSecurity, RegistrySecurity
148139

149140
Other types:
150141

151142
- SecureString
152-
153143
- Containers (lists and dictionaries of the above type)
154144

155145
### Use SecureString for Sensitive Data (AC06)
156146

157-
When handling sensitive data always use the [System.Security.Securestring](/dotnet/api/System.Security.SecureString)
158-
data type. This could include pipeline input to parameters, as well as returning sensitive data to
159-
the pipeline.
147+
When handling sensitive data always use the [System.Security.SecureString][16] data type. This could
148+
include pipeline input to parameters, as well as returning sensitive data to the pipeline.
160149

161-
## See Also
162-
163-
[Required Development Guidelines](./required-development-guidelines.md)
150+
While .NET recommends against using **SecureString** for new development, PowerShell continues to
151+
support the **SecureString** class for backward compatibility. Using a **SecureString** is still
152+
more secure than using a plain text string. PowerShell still relies on the **SecureString** type to
153+
avoid accidentally exposing the contents to the console or in logs. Use **SecureString** carefully,
154+
because it can be easily converted to a plain text string. For a full discussion about using
155+
**SecureString**, see the [System.Security.SecureString class][01] documentation.
164156

165-
[Strongly Encouraged Development Guidelines](./strongly-encouraged-development-guidelines.md)
157+
## See Also
166158

167-
[Writing a Windows PowerShell Cmdlet](./writing-a-windows-powershell-cmdlet.md)
159+
[Required Development Guidelines][02]
160+
161+
[Strongly Encouraged Development Guidelines][04]
162+
163+
[Writing a Windows PowerShell Cmdlet][05]
164+
165+
<!-- link references -->
166+
[01]: ./credential-attribute-declaration.md
167+
[02]: ./required-development-guidelines.md
168+
[03]: ./stopproc-tutorial.md
169+
[04]: ./strongly-encouraged-development-guidelines.md
170+
[05]: ./writing-a-windows-powershell-cmdlet.md
171+
[06]: xref:System.Boolean
172+
[07]: xref:System.IDisposable
173+
[08]: xref:System.IDisposable.Dispose
174+
[09]: xref:System.Management.Automation.Cmdlet.BeginProcessing
175+
[10]: xref:System.Management.Automation.Cmdlet.EndProcessing
176+
[11]: xref:System.Management.Automation.Cmdlet.ProcessRecord
177+
[12]: xref:System.Management.Automation.Cmdlet.StopProcessing
178+
[13]: xref:System.Management.Automation.Cmdlet.WriteError%2A
179+
[14]: xref:System.Management.Automation.Cmdlet.WriteObject%2A
180+
[15]: xref:System.Management.Automation.PSCredential
181+
[16]: xref:System.Security.SecureString
182+
[17]: xref:Microsoft.PowerShell.Management.Get-Process
183+
[18]: xref:Microsoft.PowerShell.Management.Remove-Item

reference/docs-conceptual/security/security-features.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: PowerShell has several features designed to improve the security of your scripting environment.
3-
ms.date: 09/19/2024
3+
ms.date: 05/22/2025
44
title: PowerShell security features
55
---
66
# PowerShell security features
@@ -14,7 +14,7 @@ PowerShell loads configuration files and runs scripts. This feature helps preven
1414
malicious scripts. You can use a Group Policy setting to set execution policies for computers and
1515
users. Execution policies only apply to the Windows platform.
1616

17-
For more information see [about_Execution_Policies][02].
17+
For more information, see [about_Execution_Policies][02].
1818

1919
## Use of the SecureString class
2020

@@ -25,16 +25,17 @@ using passwords and rely on other means to authenticate, such as certificates or
2525
authentication.
2626

2727
PowerShell continues to support the **SecureString** class for backward compatibility. Using a
28-
**SecureString** is still more secure than using a plain text string. By default, PowerShell doesn't
29-
show the unprotected value of a **SecureString** object. However, **SecureString** can be easily
30-
converted to a plain text string. For a full discussion about using **SecureString**, see the
31-
[System.Security.SecureString class][01] documentation.
28+
**SecureString** is still more secure than using a plain text string. PowerShell still relies on the
29+
**SecureString** type to avoid accidentally exposing the contents to the console or in logs. Use
30+
**SecureString** carefully, because it can be easily converted to a plain text string. For a full
31+
discussion about using **SecureString**, see the [System.Security.SecureString class][01]
32+
documentation.
3233

3334
## Module and script block logging
3435

3536
Module Logging allows you to enable logging for selected PowerShell modules. This setting is
3637
effective in all sessions on the computer. PowerShell records pipeline execution events for the
37-
specified modules in the Windows PowerShell log in Event Viewer.
38+
specified modules in the Windows PowerShell event log.
3839

3940
Script Block Logging enables logging for the processing of commands, script blocks, functions, and
4041
scripts - whether invoked interactively, or through automation. PowerShell logs this information to
@@ -52,8 +53,8 @@ The Windows Antimalware Scan Interface (AMSI) is an API that allows applications
5253
an antimalware scanner, such as Windows Defender, to scan for malicious payloads. Beginning with
5354
PowerShell 5.1, PowerShell running on Windows 10 (and higher) passes all script blocks to AMSI.
5455

55-
PowerShell 7.3 extends the data that's sent to AMSI for inspection. It now includes all invocations
56-
of .NET method members.
56+
PowerShell 7.3 extends the data it sends to AMSI for inspection. It now includes all .NET method
57+
invocations.
5758

5859
For more information about AMSI, see [How AMSI helps][09].
5960

0 commit comments

Comments
 (0)