Skip to content

Repository files navigation

Adversarial Payment Security Lab

Live demo: https://sudopay.onrender.com

No setup needed to try it. Open the link, press Run Adversarial Campaign, and the whole pipeline runs in front of you. The instance is on a free plan and sleeps when idle, so the first request after a quiet period can take 50 seconds or more to wake it. Everything after that is quick.

The application itself is branded AI Defense Lab. sudopay.onrender.com is only the deployment hostname, and sudoWin is only the GitHub repository name. See Naming if that is confusing.

A red team / blue team laboratory for payment fraud. Synthetic fraud agents attack a fake payment environment, an ensemble detector scores every event, and a feedback loop finds whatever slipped through, mutates it, and throws it back at the detector.

The interesting part is what happens next. adaptive_security/ runs both sides as adapting agents: a population of attack strategies that evolves against a defender that re-tunes its own policy each generation. Both spend from a synthetic budget. They push against each other for as long as you let them run.

Everything here is synthetic and local. There are no real card numbers, CVVs, OTPs, bank details or personal data anywhere in the repository. See docs/THREAT_MODEL.md for the boundary.

Naming

Three different names show up around this project, so to be explicit:

ProjectAdversarial Payment Security Lab
Application branding (what the UI says)AI Defense Lab
GitHub repositoryhttps://github.com/aroh3006/sudoWin
Live deploymenthttps://sudopay.onrender.com
Active branchfeat/project-titan

Stack

Python 3.12 with FastAPI, XGBoost, scikit-learn, pandas and networkx on the backend. React 19 with TypeScript, Vite, Tailwind 4, react-router and recharts on the frontend. SQLite for storage. No external services are required to run it.

Built for the Mastercard Innovation Challenge 2026

The brief asks for three things, judged separately:

  1. Identify the landscape of GenAI-era payment fraud. docs/ATTACK_CATALOG.md covers seven families implemented as running agents plus eight more researched but not built.
  2. Generate those attacks at scale. attack_harness/ does this against the synthetic world in core/, deterministically under a seed.
  3. Defend against them. detector/ scores, explains and mitigates; feedback_loop/ closes the loop.

Attack agents

FamilyDescription
card_testingAutomated low-value probes against stolen payment instruments
synthetic_identityFabricated personas that pass KYC, then bust out
mule_networkStructuring: many senders, few collectors, then cash-out
cnp_social_engineeringSocial-engineered account recovery, then a large card-not-present charge
refund_abuseRepeated purchase-then-refund cycles against chatbot approval flows
account_takeoverCredential-stuffing burst, successful login, account drain
promo_abuseDisposable personas farming a new-customer promo

The first five were the required set. The last two were added because they exercise different parts of the graph. Full specs are in docs/ATTACK_CATALOG.md.

Detection

Three signals feed one score:

  • ML: XGBoost over 26 engineered features. All of them are computed causally. A feature for a given event only ever looks at earlier events. There is a regression test for this.
  • Graph: anomaly detection over a customer / device / IP / instrument graph. It ranks a node by how many distinct customers touch it, by percentile rather than raw degree. Not a GNN.
  • Rules: a hand-written score that stays readable and works before any model has trained.

They combine into a 0-100 risk score and an ALLOW / REVIEW / BLOCK decision. After that, a triage step writes a short explanation and a mitigation step records a simulated action. The LLM triage runs fine with no API key; it falls back to a deterministic explainer.

Known weak spots are written up honestly in docs/MODEL_CARD.md.

The feedback loop

Generate, detect, evaluate, find the false negatives, mutate whichever family is doing best at evading, then run it again. The mutated variant goes first against the unchanged detector, which shows the evasion, then the detector retrains and scores it again, which shows the recovery.

On the last full run, redistributing devices and IPs across cnp_social_engineering and refund_abuse dropped recall from 0.958 to 0.656. Retraining brought it back to 0.912. Numbers are in docs/EVALUATION.md.

The co-evolution layer

adaptive_security/ is the second loop. Instead of mutating one family at a time against a fixed detector, both sides adapt.

Attacks are represented as genomes: ten behavioral traits plus a mix of families, which express into the same parameter dicts the existing agents already take. Nothing about attack generation is reimplemented. Selection is NSGA-II across four objectives (evasion, extracted value, novelty, efficiency) with crossover, elitism and a genealogy that records where every strategy came from.

Mutation is guided rather than random. Each strategy knows which detector component caught it, so it drifts in the direction that component is weakest.

The defender searches a bounded neighbourhood of its current policy each generation, scoring candidates against recent history before deploying one. Both sides pay for what they do. Attacker infrastructure, defender investigations, mitigations and false-positive friction all post to a double-entry ledger, which means "catch everything" is not automatically the winning move.

On top of that there is a novelty engine that clusters observed behavior and flags genuinely new modes. An Oracle reads the whole run and reports who is adapting faster.

Longer write-up in docs/ADAPTIVE_SECURITY.md.

Setup

Python 3.12+ and Node 20+.

python -m venv .venv
.venv\Scripts\activate # Windowssource .venv/bin/activate # macOS/Linux
pip install -r requirements.txt
cd frontend && npm install

Copy .env.example to .env if you want. Nothing in it is required. The only setting that does anything is LLM_API_KEY, which swaps the fallback triage explainer for a real model.

Running it

Two terminals:

python -m uvicorn backend.app.main:app --reload --port 8000
cd frontend && npm run dev

Then open http://localhost:5173 and press Run Adversarial Campaign. That builds a world, injects attacks, trains the detector and runs the feedback loop. Reset Experiment clears it.

In development the Vite server proxies /api to the backend on port 8000. In the deployed build there is no proxy, because the backend serves the frontend itself (see Deployment).

There are six pages:

PageWhat it shows
OverviewHeadline detection metrics, the ALLOW / REVIEW / BLOCK split, and the agent catalog
Red TeamEach attack agent, plus the fraud ring clusters found in the entity graph
Blue TeamPrecision, recall, F1, ROC-AUC, per-family recall, feature importances, confusion matrix
Feedback LoopGeneration-by-generation recall, and the mutation records behind it
Live StreamEvery scored event with its evidence, triage explanation and mitigation, filterable by decision, with an optional ground-truth reveal for evaluation
War RoomThe co-evolution layer. Starts its own runs and shows the Arms Race Index, Red population, deployed Blue policy, Oracle findings, economy ledger and strategy library

Judge Mode is not one of these pages. It runs from the command line or through the /api/judge endpoints (see below).

Command line

Generate attacks:

python -m attack_harness.orchestrator --agent card_testing --events 5000 --seed 42
python -m attack_harness.orchestrator --scenario full --events 10000 --seed 42 --reset

Run the feedback loop and the full evaluation:

python -m feedback_loop.loop --seed 42 --generations 3 --baseline-events 6000 --mutation-events 300
python -m evaluation.run_evaluation --seed 42 --generations 3 --baseline-events 6000 --mutation-events 300

The evaluation writes data/results/EVALUATION_RESULTS.md plus a timestamped JSON file.

Run the co-evolution simulation:

python -m adaptive_security.simulation.runner --generations 10 --seed 42 --mode fast
python -m adaptive_security.simulation.runner --generations 100 --seed 42 --mode research

Modes are debug, fast, standard and research. They differ only in scale. A quick run and a long one are directly comparable. Any subsystem can be switched off to see what it was contributing: --no-graph, --no-rules, --no-novelty, --no-adaptive-defender, --no-memory, --no-economy, --no-coevolution.

For a single reproducible demo of the whole thing:

python -m adaptive_security.judge --seed 42 --generations 12

That runs the real simulation and then compares generation 0 against the final generation. It is not a recording. If nothing novel emerges in a run, it says so. The same thing is reachable over HTTP via POST /api/judge/run, then GET /api/judge/status and GET /api/judge/narrative. GET /api/judge/plan describes what it will do before you start it.

The experiment lab runs named arms and ablation suites and writes results with the seed and config attached:

python -m adaptive_security.experiments.lab --list
python -m adaptive_security.experiments.lab --suite core --generations 20 --seed 42

Tests

python -m pytest tests/ -q

275 tests, all passing. Roughly a quarter cover the base pipeline and the rest cover the co-evolution layer, including checkpoint round-trips and a full end-to-end simulation.

Deployment

Live at https://sudopay.onrender.com, deployed from the feat/project-titan branch of https://github.com/aroh3006/sudoWin.

It is one Render web service rather than two. The frontend already calls the API on relative /api paths, so the FastAPI process serves the built React app as well. That means the deployed build needs no API base URL of its own, no CORS exchange happens, and there is a single URL. A catch-all returns index.html for unmatched paths so deep links such as /war-room work on a direct load, while unknown /api paths still return a JSON 404.

The whole definition lives in render.yaml:

Buildpip install -r requirements.txt, then npm ci && npm run build in frontend/
Startuvicorn backend.app.main:app --host 0.0.0.0 --port $PORT
Health check/api/health
EnvironmentPYTHON_VERSION, DATABASE_URL, DEFAULT_SEED, PYTHONUNBUFFERED

No secret is configured and none is needed. Python is pinned to 3.12 because numpy 1.26.4 publishes no wheels for 3.13.

Limitations

Worth knowing before you judge the live instance:

  • The free plan sleeps when idle. The first request after a quiet period can take 50 seconds or more. Requests after that are normal.
  • SQLite sits on an ephemeral disk, so campaign data does not survive a redeploy. This is deliberate, since the dashboard regenerates it on demand. If the live site looks empty, press Run Adversarial Campaign.
  • The free plan caps memory at 512 MB and the scientific stack is large. debug and fast simulation modes are the ones verified on the deployed instance. A full research run at scale is more likely to be constrained there than locally.
  • Detector weaknesses, including the families it handles least well, are documented honestly in docs/MODEL_CARD.md rather than smoothed over.

Docs

  • docs/ARCHITECTURE.md and docs/ADAPTIVE_SECURITY.md: how it fits together
  • docs/ATTACK_CATALOG.md: every fraud vector, implemented or not
  • docs/MODEL_CARD.md: the detector, including where it is weak
  • docs/EVALUATION.md: methodology and measured results
  • docs/THREAT_MODEL.md: what this does and does not touch
  • docs/CHALLENGE_REQUIREMENTS.md: requirement traceability for the submission
  • docs/REPORT_TRACKER.md: the consolidated project report
  • docs/ORIGINALITY_AUDIT.md and docs/SOURCES.md: provenance
  • docs/AI_Defense_Lab_Solution_Walkthrough.pptx: the walkthrough deck

Similarity check:

npx jscpd . --ignore "node_modules/**,.venv/**,data/**"

About

Closed-loop AI red-team and blue-team platform for simulating, detecting, and adapting to GenAI-powered payment fraud.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages