2026-09-18 · Q&A guide

When to Use SecureString in .NET for Sensitive Data

SecureString encrypts memory and lets you control disposal, but it’s not always the right choice for modern .NET applications.

What SecureString Actually Does

SecureString stores text in an encrypted buffer that the CLR keeps in protected memory. When you append characters the buffer is reallocated and re‑encrypted. Once you call MakeReadOnly the buffer is locked and cannot be modified. The garbage collector can later zero the buffer, reducing the chance that a memory dump reveals the secret.

// Basic SecureString lifecycle
var ss = new SecureString();
foreach (char c in "Password123") ss.AppendChar(c);
ss.MakeReadOnly();
// ss can now be passed to APIs that accept SecureString

Real‑World Scenarios That Benefit

Use SecureString when you need to: - Pass credentials to Win32 APIs such as SqlConnectionStringBuilder or WindowsIdentity. - Store a password in memory for a short period while a user logs in. - Reduce the window of exposure in memory‑dump‑prone environments (e.g., legacy Windows services).

var pwd = new SecureString();
foreach (char c in "secret") pwd.AppendChar(c);
var cred = new NetworkCredential("user", pwd);

Why the String Constructor Is Forbidden

SecureString has no constructor that accepts a plain string because that would create an immutable copy in memory that could not be cleared. The only way to build a SecureString is by appending individual characters, so you can control exactly when the buffer is allocated and encrypted. This pattern forces you to avoid accidental exposure of the plaintext in a single object that the GC cannot scrub.

// ❌ This is disallowed
// var ss = new SecureString("password");

Practical Usage Patterns

Typical pattern: 1. Read a password from a secure prompt. 2. Append each character to a SecureString. 3. Mark it read‑only. 4. Pass it to an API that accepts SecureString. 5. Dispose the SecureString when finished. Always wrap the usage in a try/finally or using block so the buffer is zeroed.

using (var pwd = new SecureString())
{
    foreach (char c in Console.ReadLine()) pwd.AppendChar(c);
    pwd.MakeReadOnly();
    // use pwd
}

Limitations and Modern Alternatives

- SecureString is not supported in .NET Core 3.0+ on non‑Windows platforms. - Many modern APIs now accept plain strings and rely on OS‑level protection. - For cross‑platform code, consider using a memory‑protected byte array or a third‑party library like Microsoft.AspNetCore.DataProtection. - In many cases, the complexity outweighs the benefit, especially if the secret is only used once and then discarded.

// Example of a custom protected buffer
public sealed class ProtectedBytes : IDisposable
{
    private byte[] _data;
    public ProtectedBytes(byte[] data) { _data = data; }
    public void Dispose() { Array.Clear(_data, 0, _data.Length); }
}

Takeaway: SecureString protects in‑memory secrets, but its usefulness is limited to specific Windows‑only scenarios; for most modern .NET code, simpler patterns or platform‑specific protection are preferable.

People also ask

Can I convert a SecureString back to a plain string?

Yes, using Marshal.SecureStringToBSTR, but you should do it only once and immediately clear the buffer.

Is SecureString thread‑safe?

No, you must synchronize access; it is not designed for concurrent use.

Does SecureString prevent all memory‑dump attacks?

It mitigates them by encrypting the buffer, but if an attacker can read process memory, they can still recover the key used for encryption.

Inspired by a public discussion on Stack Overflow. This article is an original explanation for learners.

← All posts