.NET Framework 2.0 Security Checklists

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Chaitanya Bijwe


Assembly Design Considerations

  • Target trust environment is identified. Permissions available to partial trust code and APIs that require additional permissions are identified.
  • Design exposes a minimal number of public interfaces to limit the assembly's attack surface.

Class Design Considerations

  • To reduce visibility, classes and members use the most restrictive access modifier possible.
  • Base classes that are not intended to be derived from are sealed.
  • Strong naming or code access security is used to restrict code access.
  • Input is not trusted. Input is validated for type, range, format and length.
  • Fields are private. Properties are used to expose fields.
  • Properties are read-only unless write access is specifically required.
  • Where appropriate, private default constructors are used to prevent object instantiation.
  • Static constructors are private.

Strong Names

  • If required, strong names are used
  • Strong names are not relied upon to create tamper-proof assemblies.
  • Delay signing is used to reduce the chance of private key compromise or to enable the use of a single public key across a team.
  • In full trust scenarios, StrongNameIdentityPermission is not relied upon to restrict code that can call the assembly.


  • Except where necessary, APTCA usage is avoided.
  • Assemblies marked with APTCA are subjected to thorough security code review.
  • SecurityTransparent and SecurityCritical attributes are used appropriately.

Exception Management

  • Structured exception handling is used instead of returning error codes.
  • Sensitive data is not logged.
  • System or sensitive application information is not revealed. Only generic error messages are returned to the end user.
  • Code is not subject to exception filter issues where the filter higher in the call stack executes before code in a finally block.
  • Where appropriate, an exception management system is used.
  • Code fails early to avoid unnecessary processing.

File I/O

  • Code avoids untrusted input for file names and file paths.
  • If file names must be accepted through input, the names and locations are first validated.
  • Security decisions are not based on user-supplied file names.
  • Where possible, absolute file paths are used.
  • Where appropriate, file I/O is constrained within the application's context.


  • Sensitive data stored in HKEY_LOCAL_MACHINE is protected by ACLs.
  • Sensitive data in the registry is encrypted.

Communication Security

  • Transport-level encryption is used to protect secrets over the network. IPSec is used to protect the communication channel between two servers, and SSL is used for more granular channel protection for an application.
  • Where appropriate, the System.Net.Security.NegotiateStream class is used for a TCP channel with .NET remoting.

Event Log

  • Sensitive data is not logged in the event log.
  • Event log data is not exposed to unauthorized users.

Data Access

  • Connection strings are not hard coded. Connection strings are stored in configuration files.
  • Connection strings are encrypted if they contain credentials.
  • To prevent SQL injection, input is validated and parameterized stored procedures are used.


  • Delegates are not accepted from untrusted sources.
  • Where appropriate, permissions to the delegate are restricted.
  • Permissions are not asserted before delegate is called.


  • The ISerializable interface or the NonSerialized attribute are used to control serialization of sensitive data.
  • Serialized data streams are validated when they are deserialized.


  • Multithreaded code does not cache the results of security checks.
  • Impersonation tokens are not lost; they flow to the newly created thread.
  • Static class constructors are synchronized.
  • Dispose methods are synchronized.


  • Full assembly names are used when Activator.CreateInstance loads add-ins.
  • Separate, low-trust application domains are used for assemblies created with user input.
  • Assemblies are not loaded dynamically based on user input for assembly or type names.
  • Untrusted code does not use Reflection.Emit to create dynamic assemblies.
  • Unless required, dynamic assemblies created by Reflection.Emit are not persisted.
  • Assembly.ReflectionOnlyLoadFrom is used only if you need to inspect code.


  • Secrets are not stored in code.
  • Where appropriate, obfuscation is used to make intellectual property theft more difficult.


  • Platform-provided cryptographic services are used. Custom cryptography algorithms are not used.
  • Appropriate key sizes are used.
  • GenerateKey is used to generate random keys for a managed symmetric cryptographic class.
  • Where appropriate, DPAPI is used to protect secrets and to reduce or eliminate key management.
  • PasswordDeriveBytes is used for password-based encryption.
  • Keys are not stored in code.
  • Access to persisted keys is restricted (for example with ACLs).
  • Keys are cycled periodically.
  • Exported private keys are protected.

Sensitive Data

  • Where appropriate, SecureString is used rather than System.String.
  • Secrets are held in memory for only a limited time.
  • Protected configuration is used to protect sensitive data and secrets in configuration files.

Unmanaged Code

  • Naming conventions are used (safe, native, unsafe) to identify unmanaged APIs.
  • Unmanaged API calls are isolated in a wrapper assembly.
  • String parameters that are passed to native code are constrained and validated to reduce the risk of buffer overrun, integer overflow, and other vulnerabilities.
  • Array bounds are validated when an array is used to pass input to a native API.
  • File path lengths are checked when a file name and path are passed to an unmanaged API.
  • Unmanaged code is compiled with the /GS switch to enable stack probes.
  • Unmanaged code is inspected for potentially dangerous APIs.
  • Unmanaged types or handles are not exposed to partially trusted code.
  • The SuppressUnmanagedCode attribute is used only if assembly takes precautions to ensure that malicious code cannot coerce it into performing unwanted operations.
  • Pointers are held in private fields to prevent access violation or attempt to dereference them to gain access to sensitive information.
Personal tools