{"record":{"id":"59304a1c8891542d","repo":"dutchcoders/transfer.sh","slug":"err-error-59304a","errorCode":null,"errorMessage":"err.Error()","messagePattern":"err\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/virustotal.go","lineNumber":48,"sourceCode":"\n\t\"github.com/gorilla/mux\"\n\n\t\"github.com/Aetherinox/go-virustotal\"\n)\n\nfunc (s *Server) virusTotalHandler(w http.ResponseWriter, r *http.Request) {\n\tvars := mux.Vars(r)\n\n\tfilename := sanitize(vars[\"filename\"])\n\n\tcontentLength := r.ContentLength\n\tcontentType := r.Header.Get(\"Content-Type\")\n\n\ts.logger.Printf(\"Submitting to VirusTotal: %s %d %s\", filename, contentLength, contentType)\n\n\tvt, err := virustotal.NewVirusTotal(s.VirusTotalKey)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n\n\treader := r.Body\n\n\tresult, err := vt.Scan(filename, reader)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n\n\ts.logger.Println(result)\n\t_, _ = w.Write([]byte(fmt.Sprintf(\"%v\\n\", result.Permalink)))\n}\n","sourceCodeStart":30,"sourceCodeEnd":61,"githubUrl":"https://github.com/dutchcoders/transfer.sh/blob/c37bfd95797fd6da8a6da53fc13d191994b3f687/server/virustotal.go#L30-L61","documentation":"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.","triggerScenarios":"POST upload with the VirusTotal integration enabled while VIRUS_TOTAL_KEY is unset, empty, or malformed such that virustotal.NewVirusTotal returns an error.","commonSituations":"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.","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"],"exampleFix":"// before\nvt, err := virustotal.NewVirusTotal(s.VirusTotalKey)\nif err != nil {\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n}\n// after\nvt, err := virustotal.NewVirusTotal(s.VirusTotalKey)\nif err != nil {\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n    return\n}","handlingStrategy":"validation","validationCode":"# fail fast at deploy time if the VirusTotal key is missing\n[ -n \"$VIRUS_TOTAL_KEY\" ] || { echo 'VIRUS_TOTAL_KEY not set'; exit 1; }\ncurl -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","typeGuard":"null","tryCatchPattern":"try {\n  const res = await fetch(uploadUrl, {method:'POST', body:form});\n  if (!res.ok) throw new Error('upload rejected: ' + await res.text());\n} catch (err) {\n  if (/apikey|VirusTotal/i.test(String(err))) { /* fix VIRUS_TOTAL_KEY config */ }\n}","preventionTips":["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"],"tags":["http-500","virustotal","api-key","missing-env-var"],"backgroundTag":"missing-api-key","analyzedSha":"c37bfd95797fd6da8a6da53fc13d191994b3f687","analyzedAt":"2026-09-05T10:21:07.548Z","contentChangedAt":"2026-09-05T10:21:07.548Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}