The 9 Security Tools I Wired Into Agent Provost’s CI Pipeline (And Why Most AI Projects Have Zero)
After 20+ years in DevOps, I’ve seen a lot of “secure” pipelines. Most of them aren’t. They lint. Maybe they run a container scan. That’s it.
Now that AI agents are executing real trades through APIs like Alpaca, the stakes are different. A buggy agent loop can drain an account in seconds. And if your CI pipeline doesn’t catch vulnerabilities before they ship, you’re trusting an LLM with money on an unhardened stack.
I built Agent Provost’s CI pipeline with 9 security tools wired directly into GitHub Actions. Not because it looks impressive on a README. Because every one of them toally catches something else.
Here’s a summary of what each one does, and the exact code I wrote.
1. Trivy — Filesystem and Image Scanning
Trivy scans the repo filesystem and the built container images for known CVEs. I set it to fail on CRITICAL and HIGH. If there’s a known vulnerability in a dependency or base image, the PR doesn’t merge.
yaml
- name: Trivy filesystem scan
run: |
trivy fs --exit-code 1 --severity CRITICAL,HIGH .
- name: Trivy image scan (agent-provost)
run: |
trivy image --exit-code 1 --severity CRITICAL,HIGH "${OPENRESTY_IMAGE}"
I split this into two tiers. First-party images (the ones I build) are a hard gate — if they fail, CI fails. Third-party images (OpenResty, Fluent Bit) are advisory only, because I can’t fix upstream CVEs. But I still surface them as warnings so I know what’s in my stack.
2. Checkov — Infrastructure-as-Code Scanning
Checkov scans CloudFormation, Dockerfiles, and GitHub Actions workflows for misconfigurations. Things like publicly exposed S3 buckets, overly permissive IAM policies, or Dockerfiles running as root.
bash
checkov --directory . --framework dockerfile,github_actions,yaml --quiet
One line. Catches hundreds of potential misconfigurations before they ever reach AWS.
This is the classic Painting of Hans Holbein’s “The Ambassadors” (1533) — two diplomats surrounded by instruments of governance. The blurry diagonal fuzz in the bottom center becomes a skull when you look from the extreme right, symbolizing how hidden vulnerabilities are in plain sight. Continue below for more Governance and less skulls.

3. Gitleaks — Secret Detection in Git History
Gitleaks scans the full git history for leaked API keys, tokens, and passwords. Not just the current commit — the entire history.
bash
gitleaks detect --source . --verbose --config .gitleaks.toml
I have a custom .gitleaks.toml with an allowlist for documented mock tokens used in tests. Everything else is a hard fail. In a trading project, a leaked Alpaca key is real money.
4. zizmor — GitHub Actions Security Auditing
This is the one most people don’t know about. zizmor scans your workflow files for CI-specific attack patterns: dangerous triggers like pull_request_target, unpinned action versions, credential stuffing in workflow files.
bash
zizmor .github/workflows/
I have a .github/zizmor.yml config that documents and scopes the one exception I have (the increment-version.yml workflow uses pull_request_target by design). Everything else gets flagged.
5. actionlint — Workflow Syntax Validation
actionlint validates that the GitHub Actions YAML is syntactically correct and follows best practices. It catches things like invalid if: conditions, wrong action references, and missing required inputs.
bash
actionlint
Simple. But if your security gate workflow is broken, it doesn’t run. And if it doesn’t run, you have no security gate.
6. Hadolint — Dockerfile Linting
Hadolint enforces Dockerfile best practices. No running as root. No untagged base images. Pin versions. Clean up after yourself.
bash
hadolint alpaca-mcp.Dockerfile
The Dockerfile already pins the base image by SHA256 digest via an ARG. Hadolint makes sure I don’t accidentally break that in a future edit.
7. pip-audit — Python Dependency Vulnerability Scanning
pip-audit checks Python dependencies against the PyPI Advisory database. I run it on both the runtime requirements and the alpaca-mcp-server package.
bash
pip-audit --no-deps --disable-pip -r hash-pip/requirements-runtime.txt
The runtime requirements are also installed with --require-hashes, which means pip verifies the SHA256 hash of every package before installing. If a package has been tampered with, the install fails.
8. SHA256 Digest Pinning — Supply Chain Integrity
This isn’t a tool. It’s a discipline. Every upstream image in Agent Provost is pinned by SHA256 digest, not by tag.
bash
# .env.versions
OPENRESTY_IMAGE=openresty/openresty@sha256:0b5ae1c24927e8e225134b6e2b66876a95ecb76d8301a03f636d39345ed6c17d
FLUENT_BIT_IMAGE=public.ecr.aws/aws-observability/aws-for-fluent-bit@sha256:e8c37f6c217343f46a1c020e9110695210f229301267bc623d6476344793dbf5
In Section 8 (SHA256 Digest Pinning), replace everything after the code block with this:
Tags are mutable. openresty:latest can point to a different image tomorrow. A SHA256 digest is immutable — it’s a hash of the exact bytes. If someone replaces the upstream image, the digest changes, and my pull fails. That’s the point. I know that MOST devops dont do this, especially after a senior smart dude thought that the hash was a mistake that opened some unknown suspicious security hole!
The CI pipeline also auto-pins the ECR digest after each build and commits it back to the repo:
sed -i "s|^ALPACA_IMAGE_TAG=.*|ALPACA_IMAGE_TAG=${ECR_DIGEST}|" .env.versions
9. S3 Object Lock — WORM Audit Logs
The audit logs stream from OpenResty through Fluent Bit to S3. But a log you can delete isn’t an audit trail. It’s a suggestion.
I configured the S3 bucket with Object Lock in COMPLIANCE mode. That means once a log object is written, nobody can delete or modify it — not even the root account — until the retention period expires.
yaml
ObjectLockConfiguration:
ObjectLockEnabled: Enabled
Rule:
DefaultRetention:
Mode: COMPLIANCE
Days: !Ref ObjectLockRetentionDays
This is what SEC Rule 204-2 and FINRA 4511 require for books-and-records retention. Write Once, Read Many. No edits. No deletes. No “oops.”
The Point
Most AI projects I see have maybe one of these. Some have none. They ship a Dockerfile, run docker build, and call it a day.
I’m not saying Agent Provost is perfect. Security is never done. But when an AI agent is executing trades with real money, “we ran a linter” isn’t a security posture. It’s a hope.
The repo is here: github.com/CharmingSteve/agent-provost

