-
Notifications
You must be signed in to change notification settings - Fork 19
Rename Azure CTS to Microsoft's Signing Transparency (MST) #151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Renamed projects: CoseSign1.Transparent.CTS -> MST, CoseSignTool.CTS.Plugin -> MST.Plugin - Updated all namespaces, classes, and methods from CTS/AzureCts to MST - Renamed commands: cts_register -> mst_register, cts_verify -> mst_verify - Updated all documentation to reflect Microsoft's Signing Transparency branding - Added official blog post link to MST.md - All 935 unit tests passing
| (CoseSign1Message? message, byte[] signatureBytes, PluginExitCode result) = | ||
| await TestMstCommand.TestReadAndDecodeCoseMessage(tempFile, CancellationToken.None, null); |
Check warning
Code scanning / CodeQL
Useless assignment to local variable Warning test
message
This assignment to
signatureBytes
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 5 hours ago
To fix the problem, remove the tuple variables (message and signatureBytes) whose values are never read or used after assignment. In C#, when deconstructing a tuple and you do not need certain values, you can use the discard operator _ for those tuple elements. Specifically, change the variable names message and signatureBytes to _ in the tuple deconstruction on line 153 of CoseSignTool.MST.Plugin.Tests/MstCommandBaseLoggingTests.cs. This makes it clear that these values are intentionally not used and silences the warning. No additional methods, imports, or definitions are required for this fix.
-
Copy modified line R153
| @@ -150,7 +150,7 @@ | ||
| try | ||
| { | ||
| // Act & Assert - should not throw | ||
| (CoseSign1Message? message, byte[] signatureBytes, PluginExitCode result) = | ||
| (_, _, PluginExitCode result) = | ||
| await TestMstCommand.TestReadAndDecodeCoseMessage(tempFile, CancellationToken.None, null); | ||
| Assert.AreEqual(PluginExitCode.InvalidArgumentValue, result); | ||
| } |
| // Arrange | ||
| MockLogger logger = new MockLogger(); | ||
| IConfiguration configuration = CreateConfiguration(new Dictionary<string, string?>()); | ||
| CancellationTokenSource cts = new CancellationTokenSource(); |
Check warning
Code scanning / CodeQL
Missing Dispose call on local IDisposable Warning test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 5 hours ago
The best way to fix this issue is to ensure that the CancellationTokenSource is disposed after use. The simplest and safest way is to wrap its usage in a using statement within the unit test. Specifically, in the HandleCommonException_WithCancellation_LogsError test method in CoseSignTool.MST.Plugin.Tests/MstCommandBaseLoggingTests.cs, the code block that creates and uses cts should use a using statement so that Dispose() is called automatically, even if an exception is thrown during the test's execution. No additional methods, imports, or definitions are required.
-
Copy modified lines R249-R252 -
Copy modified lines R254-R255 -
Copy modified lines R257-R260
| @@ -246,16 +246,18 @@ | ||
| // Arrange | ||
| MockLogger logger = new MockLogger(); | ||
| IConfiguration configuration = CreateConfiguration(new Dictionary<string, string?>()); | ||
| CancellationTokenSource cts = new CancellationTokenSource(); | ||
| cts.Cancel(); | ||
| OperationCanceledException exception = new OperationCanceledException(cts.Token); | ||
| using (CancellationTokenSource cts = new CancellationTokenSource()) | ||
| { | ||
| cts.Cancel(); | ||
| OperationCanceledException exception = new OperationCanceledException(cts.Token); | ||
|
|
||
| // Act | ||
| PluginExitCode result = TestMstCommand.TestHandleCommonException(exception, configuration, cts.Token, logger); | ||
| // Act | ||
| PluginExitCode result = TestMstCommand.TestHandleCommonException(exception, configuration, cts.Token, logger); | ||
|
|
||
| // Assert | ||
| Assert.AreEqual(PluginExitCode.UnknownError, result); | ||
| Assert.IsTrue(logger.LoggedMessages.Any(m => m.Message.Contains("Operation was cancelled"))); | ||
| // Assert | ||
| Assert.AreEqual(PluginExitCode.UnknownError, result); | ||
| Assert.IsTrue(logger.LoggedMessages.Any(m => m.Message.Contains("Operation was cancelled"))); | ||
| } | ||
| } | ||
|
|
||
| [TestMethod] |
| foreach (KeyValuePair<string, string> kvp in filePaths) | ||
| { | ||
| if (!File.Exists(kvp.Value)) | ||
| { | ||
| logger?.LogError($"{kvp.Key} file not found: {kvp.Value}"); | ||
| return PluginExitCode.UserSpecifiedFileNotFound; | ||
| } | ||
| } |
Check notice
Code scanning / CodeQL
Missed opportunity to use Where Note
implicitly filters its target sequence
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 5 hours ago
To fix this issue, we should replace the foreach loop and internal if statement with a LINQ query that finds the first missing file path (where File.Exists(kvp.Value) returns false). If such a file is found, log the error and return the respective exit code, else return success. This can be accomplished by using .FirstOrDefault(...) on the dictionary's entries filtered via .Where(kvp => !File.Exists(kvp.Value)). This removes a level of indentation and makes it clear that only entries for nonexistent files are relevant. No new imports are needed, as LINQ is available by default. Edit only the lines within ValidateFilePaths in CoseSignTool.MST.Plugin/MstCommandBase.cs.
-
Copy modified lines R56-R57 -
Copy modified lines R59-R60 -
Copy modified lines R63-R64
| @@ -53,15 +53,15 @@ | ||
| /// <returns>PluginExitCode indicating validation result.</returns> | ||
| protected static PluginExitCode ValidateFilePaths(Dictionary<string, string> filePaths, IPluginLogger? logger = null) | ||
| { | ||
| foreach (KeyValuePair<string, string> kvp in filePaths) | ||
| var missingFile = filePaths.FirstOrDefault(kvp => !File.Exists(kvp.Value)); | ||
| if (!missingFile.Equals(default(KeyValuePair<string, string>))) | ||
| { | ||
| if (!File.Exists(kvp.Value)) | ||
| { | ||
| logger?.LogError($"{kvp.Key} file not found: {kvp.Value}"); | ||
| return PluginExitCode.UserSpecifiedFileNotFound; | ||
| } | ||
| logger?.LogError($"{missingFile.Key} file not found: {missingFile.Value}"); | ||
| return PluginExitCode.UserSpecifiedFileNotFound; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| return PluginExitCode.Success; | ||
| } | ||
|
|
| catch (Exception ex) | ||
| { | ||
| logger?.LogError($"Failed to decode COSE Sign1 message from {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); | ||
| } |
Check notice
Code scanning / CodeQL
Generic catch clause Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 5 hours ago
To fix the problem, we should replace the overly broad catch (Exception ex) with a set of more specific catch blocks tailored for the kinds of errors likely to occur in this context:
- For
await File.ReadAllBytesAsync(signaturePath, ...), possible exceptions includeIOException,UnauthorizedAccessException,ArgumentException, andPathTooLongException. - For
CoseMessage.DecodeSign1(signatureBytes), common exceptions might includeCryptographicExceptionif the data is invalid/malformed.
The best approach is to use multiple specific catch blocks for:
IOExceptionUnauthorizedAccessExceptionArgumentExceptionPathTooLongExceptionCryptographicException(fromSystem.Security.Cryptography)- An optional final catch for any other
Exceptiontypes if you require catching everything else (but ideally not catch critical exceptions that inherit fromSystemExceptiondirectly).
You should also add using System.Security.Cryptography; if it is not already present for CryptographicException.
Only the exception blocks in the ReadAndDecodeCoseMessage method, within CoseSignTool.MST.Plugin/MstCommandBase.cs, need changing. If logging the exception remains important, keep the log lines in each specific catch.
-
Copy modified line R8 -
Copy modified line R84 -
Copy modified lines R86-R109
| @@ -5,7 +5,7 @@ | ||
|
|
||
| using System.Text.Json; | ||
| using System.Security.Cryptography.Cose; | ||
|
|
||
| using System.Security.Cryptography; | ||
| /// <summary> | ||
| /// Base class for Microsoft's Signing Transparency (MST) commands that provides common functionality | ||
| /// for parameter validation, file operations, error handling, and result output. | ||
| @@ -81,8 +81,32 @@ | ||
| CoseSign1Message message = CoseMessage.DecodeSign1(signatureBytes); | ||
| return (message, signatureBytes, PluginExitCode.Success); | ||
| } | ||
| catch (Exception ex) | ||
| catch (IOException ex) | ||
| { | ||
| logger?.LogError($"IO error reading signature file {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); | ||
| } | ||
| catch (UnauthorizedAccessException ex) | ||
| { | ||
| logger?.LogError($"Access denied to signature file {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); | ||
| } | ||
| catch (ArgumentException ex) | ||
| { | ||
| logger?.LogError($"Invalid path for signature file {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); | ||
| } | ||
| catch (PathTooLongException ex) | ||
| { | ||
| logger?.LogError($"File path too long: {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); | ||
| } | ||
| catch (System.Security.Cryptography.CryptographicException ex) | ||
| { | ||
| logger?.LogError($"Failed to decode COSE Sign1 message from {signaturePath}: {ex.Message}"); | ||
| logger?.LogException(ex); | ||
| return (null, Array.Empty<byte>(), PluginExitCode.InvalidArgumentValue); |
| catch (Exception ex) | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } |
Check notice
Code scanning / CodeQL
Generic catch clause Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 5 hours ago
To address the generic catch clause, modify the catch (Exception ex) in ExecuteAsync to catch only known, operational exception types that can realistically occur during command execution and be meaningfully handled (such as IOException, TimeoutException, JsonException, and COSE-related exceptions). Fatal exceptions (such as OutOfMemoryException, StackOverflowException, ThreadAbortException) should not be caught, as per established guidelines. These changes should only be made in ExecuteAsync method in CoseSignTool.MST.Plugin/MstCommandBase.cs as shown.
To implement this, replace the generic catch block at lines 263-266 with multiple specific catch blocks for expected exceptions, each calling HandleCommonException as before. If the handler already expects these types, you do not need to change its logic. If additional types (such as OperationCanceledException) are not handled, you may wish to add a final catch for these or allow them to propagate.
No changes are needed to imports, unless you wish to reference additional exception types (which are all standard here).
-
Copy modified line R263 -
Copy modified lines R267-R282
| @@ -260,10 +260,26 @@ | ||
|
|
||
| return operationResult.exitCode; | ||
| } | ||
| catch (Exception ex) | ||
| catch (IOException ex) | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } | ||
| catch (TimeoutException ex) | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } | ||
| catch (JsonException ex) | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } | ||
| catch (CryptographicException ex) | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } | ||
| catch (OperationCanceledException ex) // If cancellation is to be handled gracefully | ||
| { | ||
| return HandleCommonException(ex, configuration, cancellationToken, Logger); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> |
This pull request updates the codebase and test suite to replace all references to "CTS" (Code Transparency Service) with "MST" (Microsoft's Signing Transparency), reflecting a naming change across related projects, tests, and workflow configurations. The changes ensure consistency in naming and project references throughout the repository.
Project and workflow updates:
.github/workflows/dotnet.ymlworkflow configuration, updating both test execution and build steps. [1] [2]CoseSign1.Transparent.CTS.Tests.csprojtoCoseSign1.Transparent.MST.Tests.csprojand updated its project references to use MST.Documentation updates: