From 1c68f3f5ee6052aa86b0e50dc2308d9bde2eb020 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Mon, 20 May 2024 20:39:32 +0800 Subject: [PATCH] Add check before scan feature to CLI Related to #76 Adds a feature to check if a file is already scanned before initiating a new scan using the `--check-before-scan` flag with the `vt scan file` command. - Implements a new flag `--check-before-scan` in `cmd/scan.go` to enable the pre-check feature. - Modifies the `fileScanner` struct to include a `checkBeforeScan` boolean field. - Adds logic in the `fileScanner.Do` method to check if the file is already scanned by calculating the file's hash and querying it before proceeding with a new scan. - Updates the `README.md` to document the usage of the new `--check-before-scan` flag. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/VirusTotal/vt-cli/issues/76?shareId=c6d9605a-3f1b-4676-b6d0-c0ce931a9fbb). --- README.md | 10 ++++++++++ cmd/scan.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/README.md b/README.md index 9db14d2..13a44e5 100644 --- a/README.md +++ b/README.md @@ -375,3 +375,13 @@ $ vt url http://www.virustotal.com --include=_id,_type,**.result ``` The `--exclude` option works similarly to `--include` but instead of including the matching fields in the output, it includes everything except the matching fields. You can use this option when you want to keep most of the fields, but leave out a few of them that are not interesting. If you use `--include` and `--exclude` simultaneously `--include` enters in action first, including only the fields that match the `--include` patterns, while `--exclude` comes in after that, removing any remaining field that matches the `--exclude` patterns. + +### Scan a file and check if it's already scanned + +To scan a file and check if it's already scanned before initiating a new scan, you can use the `--check-before-scan` flag with the `vt scan file` command. This feature allows you to save time and resources by avoiding unnecessary scans of files that have already been analyzed by VirusTotal. + +```sh +$ vt scan file --check-before-scan +``` + +If the file has already been scanned, the CLI will output the existing analysis result without scanning the file again. If the file has not been scanned before, it will be uploaded for analysis, and the CLI will return the analysis ID as usual. diff --git a/cmd/scan.go b/cmd/scan.go index 2d181bd..14db1e0 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -78,6 +78,7 @@ type fileScanner struct { showInVT bool waitForCompletion bool password string + checkBeforeScan bool } func (s *fileScanner) Do(path interface{}, ds *utils.DoerState) string { @@ -101,6 +102,25 @@ func (s *fileScanner) Do(path interface{}, ds *utils.DoerState) string { } defer f.Close() + if s.checkBeforeScan { + fileInfo, err := f.Stat() + if err != nil { + return err.Error() + } + fileSize := fileInfo.Size() + hash, err := utils.GetFileHash(f, fileSize) + if err != nil { + return err.Error() + } + analysis, err := s.cli.GetObject(vt.URL("files/%s", hash)) + if err == nil { + // If file is found, print the existing analysis result and return. + s.printer.PrintObject(analysis) + return "" + } + // If file is not found, proceed with the scan. + } + var analysis *vt.Object if s.password != "" { analysis, err = s.scanner.ScanFileWithParameters( @@ -181,6 +201,7 @@ func NewScanFileCmd() *cobra.Command { showInVT: viper.GetBool("open"), waitForCompletion: viper.GetBool("wait"), password: viper.GetString("password"), + checkBeforeScan: viper.GetBool("check-before-scan"), printer: p, cli: client} c.DoWithStringsFromReader(s, argReader) @@ -193,6 +214,7 @@ func NewScanFileCmd() *cobra.Command { addPasswordFlag(cmd.Flags()) addWaitForCompletionFlag(cmd.Flags()) addIncludeExcludeFlags(cmd.Flags()) + cmd.Flags().Bool("check-before-scan", false, "Check if the file is already scanned before scanning") cmd.MarkZshCompPositionalArgumentFile(1) return cmd