Fix unsafe XML crypto snippets under System.Security.Cryptography.Xml - #13013
Fix unsafe XML crypto snippets under System.Security.Cryptography.Xml#13013krwq wants to merge 1 commit into
Conversation
Apply safe-by-default patterns to signing/verification and encryption samples: - Wrap XmlDocument.Load in XmlReader.Create so DTD processing is prohibited and no XmlResolver is used. - Replace parameterless SignedXml.CheckSignature() with the overload that takes a caller-provided trusted key. - For the CheckSignatureReturningKey sample, compare the returned key against a trusted key before accepting the signature.
There was a problem hiding this comment.
Pull request overview
This PR hardens the System.Security.Cryptography.Xml C# documentation snippets to be safer by default when loading XML and validating XML signatures, reducing the risk of XXE-style issues and “trust any key” signature-validation mistakes.
Changes:
- Updates many snippets to load XML via
XmlReaderinstead of directXmlDocument.Load(...). - Replaces parameterless
SignedXml.CheckSignature()with overloads that require a caller-provided trusted key. - Improves the
CheckSignatureReturningKeysample to validate that the returned signing key matches a trusted key.
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 38 comments.
Show a summary per file
| File | Description |
|---|---|
| snippets/csharp/System.Security.Cryptography.Xml/XmlDsigXsltTransform/Overview/sample.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/XmlDsigXPathTransform/Overview/sample.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/XmlDsigC14NWithCommentsTransform/Overview/sampleenvelope.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/XmlDsigC14NWithCommentsTransform/Overview/sampledetached.cs | Passes a trusted key into detached-signature verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/X509IssuerSerial/Overview/sample.cs | Switches XML loading to XmlReader in signing/verification flow. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/XmlDsigExcC14NWithCommentsTransformUrl/sample.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/XmlDsigExcC14NTransformUrl/example.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/Overview/sample.cs | Adds trusted-key signature verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/Overview/exampleenvelope.cs | Switches XML loading to XmlReader in envelope signing/verification. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignatureReturningKey/exampleenvelope.cs | Verifies signature then compares returned key to a trusted key; switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignature/xmldsigenvkeyedhashalg.cs | Switches XML loading to XmlReader in keyed-hash signature example. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignature/xmldsigdetachedkeyedhashalg.cs | Switches XML loading to XmlReader in detached keyed-hash signature example. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignature/sample.cs | Switches XML loading to XmlReader in certificate-subject verification flow. |
| snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignature/exampledetached.cs | Switches XML loading to XmlReader in detached signature verification flow. |
| snippets/csharp/System.Security.Cryptography.Xml/Signature/Overview/sample.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/Reference/.ctor/sample.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/KeyReference/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/KeyInfoX509Data/Overview/examplecreateenvelope.cs | Switches XML loading to XmlReader during signing. |
| snippets/csharp/System.Security.Cryptography.Xml/KeyInfoX509Data/.ctor/sample.cs | Switches XML loading to XmlReader in signing/verification flow. |
| snippets/csharp/System.Security.Cryptography.Xml/KeyInfo/Overview/xmldsigenv.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/KeyInfo/Overview/xmldsigdetach.cs | Passes a trusted key into detached-signature verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/IRelDecryptor/Overview/sample.cs | Requires a trusted key for signature checking and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptionProperty/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/Overview/sample4.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/Overview/sample3.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/Overview/sample2.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/Overview/sample1.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedXml/AddKeyNameMapping/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedType/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedKey/Overview/example.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/EncryptedData/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/DSAKeyValue/Overview/exampleenvelope.cs | Passes a trusted key into verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/DSAKeyValue/Overview/exampledetached.cs | Passes a trusted key into detached-signature verification and switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/DataReference/Overview/sample.cs | Switches XML loading to XmlReader. |
| snippets/csharp/System.Security.Cryptography.Xml/DataObject/Overview/source1.cs | Introduces trusted-key signature verification and switches XML loading to XmlReader. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| public static void CheckSignatureWithEncryptedGrant(string fileName, IRelDecryptor decryptor, AsymmetricAlgorithm trustedKey) | ||
| { | ||
| // Create a new XML document. |
| // Verify the signature and retrieve the key that produced it. | ||
| AsymmetricAlgorithm signingKey; | ||
| if (!signedXml.CheckSignatureReturningKey(out signingKey)) | ||
| return false; | ||
|
|
||
| // A valid signature only proves possession of some key. | ||
| // The caller must confirm the returned key matches a key it trusts. | ||
| if (signingKey is RSA rsa) | ||
| { | ||
| RSAParameters expected = TrustedKey.ExportParameters(false); | ||
| RSAParameters actual = rsa.ExportParameters(false); | ||
| return expected.Modulus.SequenceEqual(actual.Modulus) | ||
| && expected.Exponent.SequenceEqual(actual.Exponent); | ||
| } | ||
|
|
||
| return false; |
|
The comments by Copilot about passing an XmlReaderSettings isn't needed now. It used to be needed as the default behavior on .NET Framework was target framework version dependent. If you had an app targeting .NET 4.5, the default behavior was to do DTD processing and provide a default implementation of the XmlResolver which would download referenced/included files. Because you might not know which target framework version your code would be running against, if it was library code, then it's safest to be explicit. All currently supported versions of .NET Framework and .NET have safe defaults so it's not needed. It's only if someone is still targeting an out of support version of .NET Framework, or explicitly opted in to the unsafe behavior that this would be a concern. |
Apply safe-by-default patterns to signing/verification and encryption samples:
Internal previews
Toggle expand/collapse
Note
This table shows the first 30 preview links (sorted alphabetically by file path) found in the OPS build report. For the full list, select OpenPublishing.Build Details within checks.