dutchcoders/transfer.sh · error
err.Error()
Error message
err.Error()
What it means
virusTotalHandler uploads a just-received file to VirusTotal for scanning. virustotal.NewVirusTotal(key) validates the API key; if it is empty/invalid the constructor errors and the raw error text is returned with HTTP 500. Note the code does not return immediately, so execution may continue into vt.Scan with a nil vt — a latent nil-pointer risk in this source.
Source
Thrown at server/virustotal.go:48
"github.com/gorilla/mux"
"github.com/Aetherinox/go-virustotal"
)
func (s *Server) virusTotalHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
filename := sanitize(vars["filename"])
contentLength := r.ContentLength
contentType := r.Header.Get("Content-Type")
s.logger.Printf("Submitting to VirusTotal: %s %d %s", filename, contentLength, contentType)
vt, err := virustotal.NewVirusTotal(s.VirusTotalKey)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
reader := r.Body
result, err := vt.Scan(filename, reader)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
s.logger.Println(result)
_, _ = w.Write([]byte(fmt.Sprintf("%v\n", result.Permalink)))
}
View on GitHub (pinned to c37bfd9579)
Solutions
- Set the VIRUS_TOTAL_KEY environment variable (or equivalent config) with a valid VirusTotal API key and restart the server
- Verify the key is active on the VirusTotal account dashboard
- If VirusTotal scanning is not wanted, disable the integration instead of leaving an empty key
- As a hardening fix, add `return` after http.Error so the nil vt is never used
- Check container/secret configuration so the env var actually reaches the process
Example fix
// before
vt, err := virustotal.NewVirusTotal(s.VirusTotalKey)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
// after
vt, err := virustotal.NewVirusTotal(s.VirusTotalKey)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
} Defensive patterns
Strategy: validation
Validate before calling
# fail fast at deploy time if the VirusTotal key is missing
[ -n "$VIRUS_TOTAL_KEY" ] || { echo 'VIRUS_TOTAL_KEY not set'; exit 1; }
curl -s -o /dev/null -w '%{http_code}' "https://www.virustotal.com/vtapi/v2/url/report?apikey=$VIRUS_TOTAL_KEY&resource=example.com" | grep -q 200 Type guard
null
Try / catch
try {
const res = await fetch(uploadUrl, {method:'POST', body:form});
if (!res.ok) throw new Error('upload rejected: ' + await res.text());
} catch (err) {
if (/apikey|VirusTotal/i.test(String(err))) { /* fix VIRUS_TOTAL_KEY config */ }
} Prevention
- Set and verify VIRUS_TOTAL_KEY in every deployment environment
- Add a startup check that the key is present and valid
- Disable the VirusTotal integration explicitly when unused instead of leaving an empty key
- Wire the key via secret manager, not ad-hoc env edits
When it happens
Trigger: POST upload with the VirusTotal integration enabled while VIRUS_TOTAL_KEY is unset, empty, or malformed such that virustotal.NewVirusTotal returns an error.
Common situations: Missing VIRUS_TOTAL_KEY environment variable in the deployment; key rotated/revoked; config file not passed to the server process; Docker/K8s secret not wired into the container environment.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
AI-assisted analysis of dutchcoders/transfer.sh@c37bfd9579 (2026-09-05).
Data as JSON: /api/errors/59304a1c8891542d.
Report an issue: GitHub.