Sentinel

Sentinel

Every upload is guilty until proven clean

Sentinel is a file-scanning pipeline. A new upload is held back, not shared. A scanner checks it, gives it a risk score with the reasons, and then either releases it or locks it in quarantine. Dangerous files also raise a security alert. It is built on S3, Lambda, SQS, DynamoDB and API Gateway, defined in Terraform, and runs entirely on your laptop with LocalStack and Docker.

  • 5AWS services
  • 4Lambda functions
  • 8/8Demo samples pass
  • 27Unit tests
  • 1Command to start

01 / How it works

Upload, queue, scan, decide

Each step is its own AWS service, connected by events. The upload API never scans anything itself. It stores the file and lets S3 and SQS start the rest.

Diagram: architecture.svg

  1. Upload

    A client sends the file as base64 to POST /upload. The upload Lambda stores it and records it as PENDING, then answers 202 with a file_id.

    API Gateway → λ upload → s3://sentinel-incoming + DynamoDB
  2. Queue

    S3 sends an object-created event to SQS. The queue absorbs bursts of uploads so the scanner works at a steady pace.

    S3 event → sentinel-scan-queue
  3. Scan

    The scanner skips files it has already finished, hashes the bytes, and checks the hash cache. On a cache miss it runs every check and caches the result.

    λ scanner ↔ sentinel-known-hashes
  4. Decide

    Clean files are released. Suspicious and malicious files are moved to quarantine, not deleted. The record becomes SCANNED with its score and reasons.

    sentinel-clean or sentinel-quarantine + sentinel-verdicts
  5. Alert

    Malicious verdicts go to a separate queue. The alerts Lambda writes a SECURITY ALERT line with the file, score and reasons.

    sentinel-alerts → λ alerts → CloudWatch Logs
  6. If a scan fails

    SQS delivers the message again. After 3 failed attempts it moves to the dead-letter queue, so one bad file can't block the others.

    sentinel-scan-queue → sentinel-scan-dlq

02 / Scanner checks

Six checks, one score

Every check adds points. The total is capped at 100. Each check is a plain Python function, so all of them are unit tested without Docker.

  • Reuses stored score

    Hash lookup

    Identical content gets the earlier verdict straight from DynamoDB. The EICAR test file is seeded as known-bad.

  • 70 / 25 points

    Magic bytes

    Reads the real file type from its first bytes. An executable dressed as a PDF scores 70; other mismatches score 25.

  • 40 / 40 / 20 points

    Filename tricks

    Double extensions like resume.pdf.exe, the right-to-left override character, and dangerous extensions.

  • Up to 100 points

    Content patterns

    The EICAR signature, PDF JavaScript, open and launch actions, and encoded PowerShell commands.

  • 20 points

    Entropy

    Random-looking data (7.5 bits per byte or more) suggests a packed or encrypted payload.

  • 15 to 60 points

    ZIP metadata

    Zip bombs, VBA macros, embedded executables, encrypted or nested archives. Archives are never extracted.

03 / Verdicts

Three outcomes

Every verdict lists the reasons that produced it, so a flagged file can always be explained.

Clean

Released

Score
0 to 29
Goes to
sentinel-clean
  • No alert is raised.
  • From the demo: clean.pdf scored 0, “no threats detected”.
Suspicious

Quarantined

Score
30 to 79
Goes to
sentinel-quarantine
  • Kept for review, never deleted.
  • From the demo: report.docx 50 (VBA macro), archive.zip 60 (expands 1029×), resume.pdf.exe 40.
Malicious

Quarantined + alert

Score
80 to 100
Goes to
sentinel-quarantine
  • A SECURITY ALERT is logged through the alerts queue.
  • From the demo: eicar.txt, invoice.pdf.exe and evil.pdf, all 100.

04 / Reliability

Built to fail safely

The pipeline expects things to go wrong and keeps every file accounted for.

  • SQS

    Queue buffering

    Upload spikes wait in the queue instead of overloading the scanner.

  • 3 attempts

    Retries + DLQ

    A failing scan is retried, then parked in sentinel-scan-dlq. Try crash-me.txt.

  • cache_hit

    Idempotency

    Finished files are skipped, and repeated content reuses its cached verdict.

  • Audit trail

    Quarantine, not delete

    Flagged files are moved aside and kept, so nothing is lost.

  • Metadata only

    Safe inspection

    ZIP files are judged from their headers. Nothing is unpacked.

  • Own queue

    Separate alerting

    Alerts run on their own queue and Lambda, so a slow alert never delays scanning.

05 / See it run

The scan console

A small local dashboard uploads files through the real API and lists every verdict from DynamoDB. You can scan several files at once and clear the records to start over.

Sentinel dashboard listing scanned files with clean, suspicious and malicious verdicts, risk scores and reasons
Dashboard after make demo, read live from DynamoDB. Open full screenshot
  • The same dashboard on a narrow phone screen

    Works on small screens

    At 390px the records stack into single columns and keep their reasons.

    Mobile screenshot
  • Architecture diagram of the Sentinel pipeline

    Architecture

    Client, API Gateway, four Lambdas, three buckets, three queues and two tables.

    Open diagram

06 / Demo results

8 of 8 pass

Output of scripts/demo.py against the live LocalStack stack. All sample files are generated and harmless.

Demo sample files with expected and actual verdicts
FileExpectedActualResult
clean.pdfcleanclean (0)PASS
eicar.txtmaliciousmalicious (100)PASS
invoice.pdf.exemaliciousmalicious (100)PASS
report.docxsuspicioussuspicious (50)PASS
resume.pdf.exesuspicioussuspicious (40)PASS
evil.pdfmaliciousmalicious (100)PASS
archive.zipsuspicioussuspicious (60)PASS
packed.scrsuspicioussuspicious (40)PASS
crash-me.txtdead-letterfails on purposeDLQ

07 / Built with

AWS, on your laptop

LocalStack runs the AWS services inside one Docker container. Terraform creates every resource.

  • AWSCloud platform
  • AWS CloudEmulated locally
  • Amazon S33 buckets
  • AWS Lambda4 functions
  • DynamoDB2 tables
  • API GatewayREST API
  • Amazon SQS3 queues + DLQ
  • LocalStackLocal AWS
  • TerraformIaC
  • DockerCompose
  • Python 3.11Lambda runtime

AWS icons are the official AWS Architecture Icons, © Amazon Web Services, Inc., used unmodified under the AWS icon terms. Terraform, Docker and Python icons from Devicon. The LocalStack logo belongs to LocalStack. Sentinel is not affiliated with AWS.

08 / Quick start

Run it in one command

You need Docker Desktop, Terraform 1.5 or newer, and Python 3.10 or newer. No AWS account, no credit card, no LocalStack token.

Then open http://localhost:8080 for the dashboard.

Windows · PowerShell
git clone https://github.com/nonsense3/Sentinel.git
cd Sentinel
Copy-Item .env.example .env
pip install -r requirements-dev.txt
.\make.ps1 up
.\make.ps1 demo
.\make.ps1 dashboard
macOS · Linux
git clone https://github.com/nonsense3/Sentinel.git
cd Sentinel
cp .env.example .env
pip install -r requirements-dev.txt
make up
make demo
make dashboard

09 / Questions

FAQ

Is there a live version I can use online?

No.Sentinel runs on your own machine through LocalStack. This page describes the project; the scanning happens after you clone and start it.

Do I need an AWS account or a credit card?

No. LocalStack ignores credential values. The .env.example file uses test / test, and nothing reaches real AWS.

Do I need a LocalStack auth token?

No. The pinned community image (localstack/localstack:3.8) runs every service Sentinel uses. A Pro token is only needed if you want data to survive container restarts.

Is this a real antivirus?

No. It uses heuristic checks and the standard EICAR test string. It never uses real malware, and it is a demonstration rather than production security.

My files disappeared after restarting Docker. Why?

The community image doesn't keep data when the container restarts. Run make deploy (or .\make.ps1 deploy) to recreate everything, then restart the dashboard.

Nothing is shared until it passes.