diff options
Diffstat (limited to 'docs/BACKLOG.md')
| -rw-r--r-- | docs/BACKLOG.md | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 87ec4b3..a520ae0 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -10,6 +10,7 @@ number and gains a status rather than being renumbered. | 3 | Expose kept cases so qtmaildir can tag spam | ? | open, unsized | | 4 | `Report-Type: phishing` is unverified against x-arf | XS | closed | | 5 | `report.build()` raises KeyError on an identity with no email | XS | closed | +| 6 | VirusTotal as a destination, or as enrichment | S | open, deferred | ## 1. Skip boilerplate namespace URLs @@ -183,3 +184,67 @@ remaining gap is a hand-edited config and the error message it deserves. alone, since where the check lives decides whether the user sees an exit code and a sentence or a traceback. Not a leak: the failure is loud and nothing is sent. + +## 6. VirusTotal as a destination, or as enrichment + +**Deferred**, not rejected. Recorded with the findings so it is reconsidered +from checked documentation rather than from memory. + +**Observed.** The report spec's addendum settles three destinations, MISP, +AbuseIPDB and URLhaus. VirusTotal was examined in the same pass and left out. + +**What the documentation says**, read 2026-09-10 from `docs.virustotal.com` +and the endpoint index at `virustotal.readme.io/llms.txt`: + +- The only submission endpoints are `POST /urls` and file upload. **There is + no endpoint that submits a domain or an IP address as a new indicator.** + `POST /ip/{ip}/analyse` and `POST /domains/{domain}/analyse` re-analyse data + VirusTotal already holds, which is not reporting. +- Files are submitted as FILES. This tool holds an attachment's sha256 and + never the attachment, so a hash IOC earns no VirusTotal submission either. +- The auth header is `x-apikey`. + +So its submit side accepts URLs and nothing else, which is exactly URLhaus's +accepted type. There is no case where VirusTotal earns a row and URLhaus does +not. + +**Why it was left out.** The overlap above, plus a difference in kind: +`POST /urls` means "scan this", not "this is malicious". It carries no verdict, +no category and no comment, so the argument the x-arf body makes, what happened +and what is wanted, has nowhere to land. Recording a judgement would mean a +second call to `POST /urls/{id}/votes` with different semantics. URLhaus is +purpose-built for reporting a malicious URL and takes a threat classification +and tags. + +**The interesting half is the READ side, and it collides with a property.** +`GET /domains/{d}` and `GET /ip/{ip}` answer questions review actually has: +how old is this domain, has anyone else flagged this host, is this dedicated +attacker infrastructure or a compromised legitimate one. That would change +what a user writes in a report and whether they send one. + +Two obstacles, and the second is the real one: + +- The second property says nothing is ever fetched or resolved. A VirusTotal + lookup asks a third party ABOUT an indicator rather than fetching it, so no + tracker fires and nothing confirms the address is live. That is the same + shape as an RDAP query, which the tool already makes. The property survives. +- The fourth property is the obstacle. A query discloses which host is being + investigated, and `contacts.is_queryable()` is the single admission point + that exists because that leak happened three times. **A URL lookup cannot + pass it**: VirusTotal's URL endpoint takes a URL, and the fourth property is + precisely that a query carries a bare host or IP and never a URL. Redacting + the URL first does not rescue it, since a redacted URL hashes to a different + `/urls/{id}` than the real one and the lookup returns nothing. Domain and IP + lookups are bare values and would be fine. + +There is also a preference cost: VirusTotal is Google-owned, and every lookup +tells Google which infrastructure a named consultant is investigating. RDAP +carries the same disclosure but is unavoidable if the tool wants an abuse +contact; this would be optional convenience. + +**Before building.** Use the tool on real cases first and find out whether +review actually feels under-informed. Enrichment built against a guess about +what review will want is the first rung of the ladder failing. If it is built, +it is a `contacts`-time enrichment over domains and IPs through the existing +admission point, writing what it learns into the manifest, and it needs its +own spec: it changes a module that is already swept and settled. |
