dotnet / dotnet/command-line-api

SARIF invocation properties from InvocationContext

Open
#1,795 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
3.7k
Forks
428
PR merge metrics
No merged PRs in 30d

Description

I have a tool that uses System.CommandLine and can create a [Static Analysis Results Interchange Format (SARIF) Version 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html) log file. SARIF defines the [`invocation.commandLine`](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317569), [`invocation.arguments`](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317570), and [`invocation.responseFiles`](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317571) properties in which the tool can save information about how it was invoked. I'd like to implement that in the tool. I am not requesting any changes in System.CommandLine for this purpose, but I am curious if anyone else has implemented something similar.

It would be easy to use `string[] args` from the Main method for the SARIF `invocation.arguments` property, and [Environment.CommandLine](https://docs.microsoft.com/dotnet/api/system.environment.commandline?view=netstandard-2.0) for the SARIF `invocation.commandLine` property. However, I hope I can instead get the information from System.CommandLine somehow, for these reasons:

* System.CommandLine parses the response file syntax, and I'd rather not reimplement that parsing just for the sake of the SARIF `invocation.responseFiles` property, especially if the syntax can change later ().
* If the command line contains passwords or other sensitive information, then those should be redacted from the log file. I hope I can somehow mark the Argument\ and Option\ instances as sensitive and then redact the values if [SymbolResult.Symbol](https://docs.microsoft.com/dotnet/api/system.commandline.parsing.symbolresult.symbol) is so marked. I can imagine several ways to mark them:
- During initialization, create a List\ that contains all the sensitive Argument\ and Option\ instances.
- Derive classes SensitiveArgument\ and SensitiveOption\. Having to forward the constructors would be a bit annoying.
- Define struct SensitiveString, and use Argument\ and Option\. (Alternatively [SecureString](https://docs.microsoft.com/dotnet/api/system.security.securestring?view=netstandard-2.0), but that is cumbersome to use and no longer recommended.)
- Add a marker [ICompletionSource](https://docs.microsoft.com/dotnet/api/system.commandline.completions.icompletionsource) to [Argument.Completions](https://docs.microsoft.com/dotnet/api/system.commandline.argument.completions). That would be somewhat weird.

For the SARIF `invocation.arguments` property, there are [ParseResult.Directives](https://docs.microsoft.com/dotnet/api/system.commandline.parsing.parseresult.directives) and [ParseResult.Tokens](https://docs.microsoft.com/dotnet/api/system.commandline.parsing.parseresult.tokens), which would let the tool check the sensitivity markers, but I cannot fully reconstruct the original `string[] args` from them:

* The order of directives is not preserved. I suppose that wouldn't be a problem in practice, but it feels a bit dirty.
* No public way to distinguish between `--option=value`, `--option:value`, and `--option` `value`. Non-public reflection could perhaps do it by checking whether both tokens have the same [Token.Position](https://github.com/dotnet/command-line-api/blob/209b724a3c843253d3071e8348c353b297b0b8b5/src/System.CommandLine/Parsing/Token.cs#L32). As above, the difference shouldn't matter in practice.
* No obvious way to know which tokens came from response files, or which response files were even used. Could be worked around by disabling response files. (The tool doesn't need very long command lines because it reads configuration files.)

So, it seems I can make the tool log a `invocation.arguments` property that is good enough although not quite perfect, but I cannot make it log `invocation.commandLine` (too difficult to redact) nor `invocation.responseFiles` (too difficult to find which files were used, and the tokens from the files will be in `invocation.arguments`).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.