How to Scan File Uploads for Malware on Railway
If your Railway app accepts file uploads, those files aren't scanned for malware. Railway handles deployment, networking, and scaling — but it won't check whether an uploaded file is safe before your app stores or serves it.
AttachmentScanner adds malware scanning with a single API call. Files are checked against multiple antivirus engines and you get back a clear result: clean, malicious, or suspicious.
This guide covers adding scanning to a Railway service. For the full picture on scanning strategies, see the complete guide to scanning user uploads.
Set Your Service Variables
Sign up for an account to get your API token and scanner URL. Add them as service variables in your Railway dashboard, or via the CLI:
railway variables set ATTACHMENT_SCANNER_URL=https://scans.attachmentscanner.com
railway variables set ATTACHMENT_SCANNER_API_TOKEN=your_token_here
That's all the configuration you need. Your app reads these like any other environment variable.
Your First Scan
Test the connection with the EICAR test file — a standardised test file that every antivirus engine detects:
curl -H "Authorization: Bearer $ATTACHMENT_SCANNER_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.attachmentscanner.com/eicar.com"}' \
-XPOST $ATTACHMENT_SCANNER_URL/v1.0/scans
{
"status": "found",
"filename": "eicar.com",
"matches": ["Eicar-Test-Signature"]
}
That's it — scanning is working. Now let's integrate it into your app.
Scanning from Your App
The examples below use TypeScript, but AttachmentScanner works with any language. See the documentation for examples in Ruby, Python, Go, and more.
Scan by URL
If your files are in cloud storage, pass a URL and AttachmentScanner fetches the file directly:
const response = await fetch(
`${process.env.ATTACHMENT_SCANNER_URL}/v1.0/scans`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTACHMENT_SCANNER_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: fileUrl }),
}
);
const result = await response.json();
if (result.status === "found") {
// Reject the upload
}
Scan a File Upload Directly
To scan a file from a multipart upload, send it as multipart/form-data:
const formData = new FormData();
formData.append("file", fileBuffer, filename);
const response = await fetch(
`${process.env.ATTACHMENT_SCANNER_URL}/v1.0/scans`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTACHMENT_SCANNER_API_TOKEN}`,
},
body: formData,
}
);
Going Async: The Recommended Approach
The examples above are synchronous — your server blocks while the scan runs. For production, use async scanning with callbacks. Your upload handler returns immediately, and AttachmentScanner POSTs the result to your callback URL when the scan finishes.
// Upload handler — returns immediately
await fetch(`${process.env.ATTACHMENT_SCANNER_URL}/v1.0/scans`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ATTACHMENT_SCANNER_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: presignedUrlFor(stagedPath),
async: true,
callback: "https://your-app.up.railway.app/webhooks/scan-complete",
}),
});
return res.status(202).json({ status: "processing" });
The uploads guide covers the full async pattern
including callback handling, staging areas, and the warning status.
Works Everywhere
AttachmentScanner is cloud-agnostic — the same API works whether you're on Railway, Heroku, Fly.io, Vercel, or your own infrastructure. If you move between platforms, the integration stays the same.
Getting Started
- Sign up and grab your API token
- Set
ATTACHMENT_SCANNER_URLandATTACHMENT_SCANNER_API_TOKENas Railway service variables - Test with EICAR to confirm scanning works
- Set up async scanning with callbacks for production
If you need help with your integration, get in touch — we're always happy to help.
AttachmentScanner Team
Other Articles
Scan File Uploads on Heroku
AttachmentScanner Team
Scanning User Uploads for Malware
AttachmentScanner Team
Scan DigitalOcean Spaces for Malware
AttachmentScanner Team