· Jesse Edwards · Case Studies · 6 min read
Threat Modeling a Real SaaS
Security is not easy and that is why so many products get it wrong part 1.

Security 101
This post starts the security series by grounding everything I have learned over the years and is in the architecture that runs RenovationRoute today.
My last position was a VP lead security engineer at JP Morgan Chase. If anyone cares about security, it is one of the largest banks in the world. You should strive to be as secure as them, but I am a realist and understand not every company has the resources of a bank.
If there is one thing to take away from any of these blogs or information I provide, it is this chart. Whatever you do, do the minimum to enhance your security posture. At 0-2% it is called low hanging fruit and an attacker will pick the path of least resistance. I will try to point out the basics or even consider writing a separate blog post on it later. For these upcoming posts I will try to cover 80% of the security posture with 20% of the effort.

The goal is not perfect security. There is actually no such thing as 100% secure. Yes, I was shocked when the professor said that in my application security class. Security is a function of time and resources.
Security is not easy. I think because it is needed everywhere, it’s not uniformly applied, and it slows down development and releases. Securing a network is not the same as securing an application, which is not the same as securing a CI pipeline. And no matter how much you try, it is added work which means more effort == more time. Add that to the complexity of it and boom! You receive mail about security breaches from companies… “sorry this happened, but get your 12 months of FREE credit monitoring”! Ugh!
Defense in depth, you have to assume that any one layer can be breached. So what is the first step in this depth? After a component diagram we can start to think about threat modeling.
Threat Modeling RenovationRoute
I am not here for checklists. I am here so you don’t get one of those stupid mails and have to worry about credit monitoring, identity theft, and missing monies.
How does this system actually fail?
Start with the component diagram
The hardest part is where to start. A diagram always helps me when I am trying to understand a complex system.
Before talking about exploits, I look at the component diagram and ask one some simple questions:
What is exposed, and what is trusted?
In this architecture:
- Rails is the only component exposed to the internet
- Postgres, Redis, Sidekiq, and monitoring sit behind it
- CI and deployment form a separate control plane
- Staging mirrors production but runs in a different environment
Rails is not just an app. It is a security gateway.
Every request that reaches data, jobs, or internal systems does so because Rails allowed it.
Canonical attack paths (ordered by realism, not theory)
These are not edge cases. These are the paths that show up in incident reports.

Attack Path 1: User → Rails → Application Logic Abuse
This is the most likely path.
How it happens
- Authentication bypass
- Broken authorization (IDOR)
- Logic flaws in project state transitions
- Payment or escrow edge cases
- File upload abuse
What the attacker gets
- Access to other users projects
- Ability to trigger background jobs
- Ability to read or mutate data indirectly
Why this matters
It has legitimate access to Postgres, Redis, and Sidekiq, and will use that access on behalf of anyone it believes is authorized.
STRIDE mapping
- Spoofing
- Tampering
- Repudiation
- Information Disclosure
This is where most real world SaaS breaches live, it is the easiest to execute, and the hardest to fully prevent.
Attack Path 2: User → Rails → RCE → Host Compromise
More rare, but high impact.
How it happens
- Deserialization bugs
- Template injection
- Command injection via file handling
- Unsafe shell-outs
- Vulnerable native gems
What the attacker gets
Code execution as the Rails user, with access to:
- Postgres socket
- Redis socket
- Environment variables
- Local files
- Exporter endpoints
Blast radius
Everything on that EC2 instance.
STRIDE mapping
- Elevation of Privilege
- Information Disclosure
- Tampering
The tradeoff is explicit:
Remote Code Execution (RCE) equals full system compromise.
Attack Path 3: User → Rails → Redis / Sidekiq Abuse
Subtle and very common.
How it happens
- Repeated triggering of background jobs
- Manipulation of job arguments via exposed endpoints
- Replay of non-idempotent jobs
What the attacker gets
- Double execution (payments, notifications)
- Queue flooding (soft denial of service)
- Delayed or starved critical jobs
Why this matters
Sidekiq often runs with higher privilege than web requests.
STRIDE mapping
- Tampering
- Denial of Service
- Elevation of Privilege
Attack Path 4: User → Rails → Monitoring Data Leakage
Even when dashboards aren’t exposed.
How it happens
- Sensitive data logged
- PII included in traces
- Headers copied into metrics
- Stack traces returned on errors
What the attacker gets
- Internal IDs
- Query structure
- Service names
- Occasionally credentials or tokens
STRIDE mapping
- Information Disclosure
Monitoring is often the second largest leak surface, after the application itself.
Attack Path 5: User → Rails → DoS via Resource Exhaustion
No exploit required.
How it happens
- Expensive endpoints (search, AI, uploads)
- Large file uploads
- Unbounded background job creation
- Slow or unindexed queries
What the attacker gets
- Service degradation
- Increased cost
- Alert fatigue
STRIDE mapping
- Denial of Service
Even legitimate requests can be weaponized.
Secondary but critical attack paths (non-user)
Rails is not the only way in.
Attack Path 6: GitHub / CI → Rails → Everything
This is the other Tier-0 path.
How it happens
- GitHub account takeover
- Malicious dependency
- Compromised CI secrets
- Workflow tampering
What the attacker gets
- Arbitrary code deployed
- Persistence
- Silent compromise
This path bypasses Rails entirely.
Attack Path 7: You → Rails (operator error)
This is real, not hypothetical.
How it happens
- SSH mistakes
- Debug endpoints left enabled
- Console access in production
- Accidental secret exposure
Why this matters
Humans are always inside the trust boundary.
Attack paths this architecture eliminates
Because of the design, these are not viable:
- Direct database attacks
- Redis exposure attacks
- Prometheus scraping abuse
- Exporter abuse
- Lateral movement via network ports
That is good networking setup.
The mental model to lock in
Given this diagram:
Rails is not an app. It is a security gateway.
Every request that crosses into:
- Postgres
- Redis
- Sidekiq
- Monitoring
does so because Rails allowed it.
Your real security posture lives in:
- Authorization correctness
- Job idempotency
- Input validation
- Error handling
- Logging hygiene
- Dependency discipline
| Entry Point | Primary Risk | Blast Radius |
|---|---|---|
| Rails HTTPS | Logic abuse | App and data |
| Rails HTTPS | RCE | Entire EC2 |
| CI/CD | Supply chain | Entire EC2 |
| Operator | Human error | Entire EC2 |
Final thought
This threat model is not exhaustive. It is a starting point to get you thinking about realistic attack paths. After understanding the attack paths we can focus on the mitigations. Just looking at this model you can start to see where the biggest risks are and where to focus your efforts. It is not to say only focus on this, we still do need to implement bottom to top security which we will cover in the next posts.


