---
title: "Using virustotal"
author: "Gaurav Sood"
date: "`r Sys.Date()`"
vignette: >
  %\VignetteIndexEntry{Using virustotal}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
# Every chunk shows code without running it: the API needs a key and a
# network, and CRAN has neither. Sample output shown inline was captured
# from real responses.
knitr::opts_chunk$set(eval = FALSE)
```

## Using virustotal

The virustotal package provides access to the VirusTotal API v3, allowing you
to scan files and URLs for malware, get domain and IP intelligence, and
retrieve comprehensive threat analysis reports.

### Installation

From CRAN:

```{r install}
install.packages("virustotal")
```

Or the development version from GitHub, with pak:

```{r install_dev}
pak::pak("themains/virustotal")
```

#### Load the library

```{r load}
library(virustotal)
```

#### Authentication

1. Get your free API key from [VirusTotal](https://www.virustotal.com/)
2. Set it once per session:

```{r api_key}
set_key("your_api_key_here")
```

Or set the `VIRUSTOTAL_API_KEY` environment variable (for example in
`~/.Renviron`) and skip `set_key()` entirely. The historical
`VirustotalToken` variable is still honored.

### Core Functions

#### File Analysis

**Scan a file for malware:**

```{r scan_file}
result <- scan_file("path/to/suspicious_file.exe")
analysis_id <- result$data$id
```

**Get file analysis report:**

```{r file_report}
report <- file_report("99017f6eebbac24f351415dd410d522d")
report
```

```
## VirusTotal API Response
## ======================
##
## Type: File Report
## ID: 99017f6eebbac24f351415dd410d522d
## Resource Type: file
##
## Detection Summary:
##   Malicious: 61
##   Suspicious: 0
##   Undetected: 4
##   Harmless: 0
```

The raw response stays a list underneath:

```{r file_report_raw}
scan_results <- report$data$attributes$last_analysis_results
detections <- sum(sapply(scan_results, function(x) x$category == "malicious"))
```

**Request file rescan:**

```{r rescan_file}
rescan_result <- rescan_file("99017f6eebbac24f351415dd410d522d")
new_analysis_id <- rescan_result$data$id
```

#### URL Analysis

**Scan a URL:**

```{r scan_url}
url_result <- scan_url("http://www.example.com")
analysis_id <- url_result$data$id
```

**Get URL analysis report:**

```{r url_report}
report <- url_report("http://www.google.com")
scan_results <- report$data$attributes$last_analysis_results
```

#### Domain Intelligence

```{r domain}
domain_info <- domain_report("google.com")

categories <- domain_info$data$attributes$categories
whois_data <- domain_info$data$attributes$whois
dns_records <- domain_info$data$attributes$last_dns_records
```

#### IP Address Intelligence

```{r ip}
ip_info <- ip_report("8.8.8.8")

country <- ip_info$data$attributes$country
asn <- ip_info$data$attributes$asn
network <- ip_info$data$attributes$network
```

### Rate Limiting, Retries and Timeouts

The package paces itself to the public API's allowance (4 requests per
minute) and retries transient failures (HTTP 429 and 503), honoring the
server's `Retry-After` header. Four options control this:

```{r options}
options(
  virustotal.requests_per_minute = 1000, # premium keys can go faster
  virustotal.max_tries = 3, # attempts per request
  virustotal.timeout = 60, # seconds
  virustotal.throttle = TRUE # FALSE disables client-side pacing
)
```

### Error Handling

API failures are typed conditions, so specific failures can be handled
without string-matching messages:

```{r errors}
tryCatch(
  file_report("0000000000000000000000000000000000000000"),
  virustotal_rate_limit_error = function(e) {
    message("Out of quota; retry after ", e$retry_after, "s")
  },
  virustotal_auth_error = function(e) message("Check the API key"),
  virustotal_error = function(e) message("VT error: ", conditionMessage(e))
)
```

The classes are `virustotal_auth_error`, `virustotal_rate_limit_error` (with
a `retry_after` field), `virustotal_validation_error` (bad input, thrown
before any network traffic), and their parent `virustotal_error`.
