(Personal lab · Supply chain)

Fintech Supply-Chain Pipeline

Reproducing a supply-chain attack inside a fintech CI/CD pipeline

Year

2025

Role

DevSecOps

Stack

Python, Docker, GitHub Actions

Target

Fintech CI/CD

Goce Petrov’s personal lab: a transaction processor with a poisoned dependency. Bandit misses it, because the attack is not in the source. Trivy catches it in the built image. The only thing between that finding and production is one YAML flag.

Supply Chain · Trivy · Bandit · Docker · GitHub Actions · CVE Scanning

The fintech pipeline, the supply-chain path, and the exact point the gate closes.

Numbered steps trace a poisoned dependency from commit to merge-block, 1 through 8. B is the blocked push.

  1. Git push: the developer commits to main. requirements.txt pins a poisoned package with a known CVE.

  2. Trigger: every push runs ci.yml on the Actions runner.

  3. Source scan: Bandit reads the .py files only, so it reports 0 findings. It is blind to dependencies.

  4. Docker build: the image is built from python:3.11-slim.

  5. pip install: the poisoned dependency goes into the image.

  6. CVE baked in: fintech-app-image now carries the vulnerable package.

  7. Trivy image scan: Trivy checks the built image for HIGH and CRITICAL CVEs.

  8. HIGH CVE reported: Trivy flags the poisoned package.

B: with exit-code: 1 the CI gate fails, the merge is blocked and the push to the prod registry is rejected. Production stays untouched.

Before (insecure default)

Trivy runs with exit-code: 0 → HIGH CVE logged but ignored → image promoted to prod registry → attack ships.

After (one-line fix)

Trivy runs with exit-code: 1 on HIGH/CRITICAL → gate fails → merge blocked → registry never sees the poisoned image.

Source SAST is the wrong layer for this attack. The image scanner is. One YAML flag turns its finding into a gate.

Why fintech

Fintech pipelines move customer data and money. The threat model is not hypothetical: a poisoned dependency in a payment library is a full breach.

Source-level SAST is the default. It would not have caught this. The image scanner is the layer that actually matters.

What this shows about me

I reason about where controls belong.

Source vs image vs runtime: each scanner has a blind spot.

I read the config, not the marketing.

exit-code: 0 vs 1 is the whole game. I flipped it in this repo.

I write pipelines a fintech CISO would accept.

Severity gated at HIGH/CRITICAL, no bypass flag, no silent scans.

I can narrate the supply-chain path in plain English.

From dependency to CVE to merge block, step by step.

Outcome

A fintech pipeline that now fails loud on supply-chain CVEs. The exact line that turns a reported finding into a blocked merge is visible in the diff.

Pipeline stages 6

Scanners Bandit + Trivy

Target severity HIGH + CRITICAL

Gate fix exit-code: 1

Audience Fintech + banking

Demo Push triggers pipeline