Strategy & Transformation
How to Calculate ROI for AI and Software Modernization
A practical, finance-ready framework for comparing AI and modernization investment with the current-state cost, realistic benefits, delivery risk and time to value.
operationalwrocław--:-- cet
∕ insights / software-security-review.md
Software Security Review
Learn how to run a software security review step by step: scoping, threat modeling, code checks, scanning, pen tests and fixes that get closed.
>_article.meta

Exploitation of vulnerabilities accounted for 20% of initial access attempts, and vulnerability exploitation rose 34% year over year. Verizon's 2025 Data Breach Investigations Report analyzed more than 22,000 security incidents, including 12,195 confirmed breaches. For a SaaS company, that isn't a distant headline. It's a delayed release, an emergency patch, and a customer who stops trusting the product.
A flaw found in design is a ticket with an owner. The same flaw after launch is an outage, a support queue, and a roadmap that slips. The point of a software security review is to cut the chance that a known weakness becomes that operational event. Technology is the means. Fewer incidents, a date you can keep, and engineering capacity that stays on the product are the result.
The review that earns its cost is a lifecycle control, not a scan the week before launch. Each phase has one output and one signer. Findings stay open until a retest passes. Scanners support the work. They don't replace it.
A late flaw costs more than the same flaw found while the design is still cheap to change. Emergency fixes pull people off planned work, the release moves, and trust is harder to rebuild than code. Looking only at application source after development is finished also misses what attackers use to get in: exposed systems, VPNs, perimeter devices, dependencies, authentication, authorization, secrets, and known vulnerabilities.
Run the review as seven connected phases. A scanner report covers only a slice of them. Scope and the threat model come before anyone writes the change. Automated checks run on every build. A penetration test belongs before a major release or a large architecture change, not as a surprise in the launch week.

| Phase | Question it answers | Main output | Accountable owner |
|---|---|---|---|
| Scope | What is in and out of the review? | Scope note with assets and trust boundaries | Product or engineering lead |
| Threat model | What can go wrong, and where? | Threat list with mitigations and owners | Lead architect |
| Code review | Do changed paths enforce security? | Reviewed pull requests with logged findings | Senior engineer who did not write the change |
| Automated scanning | What do tools flag on every build? | Triaged results ranked by exploitability | Platform or DevOps engineer |
| Penetration test | Can an attacker chain weaknesses together? | Report with reproduced findings and fix guidance | Security lead with the external tester |
| Remediation | Is every finding owned and fixed? | Tracked tickets with SLA and retest result | Named owner for each finding |
| Reporting | What decision does leadership need to make? | One-page risk summary and accepted-risk log | Engineering leader |
Scope and model first. If you skip them, reviewers argue about the product instead of the risk.
Scan on every change. Waiting for a quarterly gate lets implementation bugs pile up between releases.
Test before the big ship. Chained attacks show up when someone is paid to try them, not when a linter is green.
Practical rule: A phase with no named signer isn't a control. It's a hope.
Copy the table into your tracker and put a name on each phase for the next release. That assignment is the whole job for this week.
The mistake that wastes the most time is reviewing the whole estate because nobody named the assets that matter. Testers wander. Developers defend code that isn't in the blast radius. Leadership gets a thick report and no decision.

Write the business purpose. State what the system does and what a breach would hit: revenue, customers, or a compliance duty. If you can't name the loss, you can't rank the work. Security, regulatory, and migration requirements belong in that same qualification pass, not in a separate memo after the build starts.
Inventory the assets that hurt if they fail. Customer data stores, payment flows, admin tools, secrets, and third-party integrations. A marketing blog is rarely on that list. The admin role system usually is.
Draw the trust boundaries. Internet to load balancer, API to database, tenant to tenant, and service to an AI model or agent. A boundary is anywhere identity, data, or privilege changes hands.
Collect prior findings, incidents, and known debt. A review that rediscovers closed tickets burns the week you needed for new risk. Our technical and operational assessment reviews architecture, dependencies, security position, observability, and operational risk, then agrees what must be corrected first.
Mark what changed since the last review. New integrations, authentication changes, hosting moves, and dependency upgrades. Unchanged code with an unchanged boundary can wait.
Sign what is in and what is out. One person owns the note. Everyone else reads the same page, including the tester.
Say a logistics SaaS team scopes its tracking API. The marketing site stays out. Partner webhooks and the admin role system stay in, because a forged webhook or a stolen admin session moves customer shipments. That exclusion is as useful as the inclusion. It stops the test from drifting.
Keep the note to one page so developers and testers aren't working from different documents. Tie sensitive behavior to written non-functional requirements so "secure enough" isn't a vibe in the pull request. The output is a signed scope note: assets, boundaries, exclusions, and the owner.
Pick one flow. Login, checkout, or data export. Diagram how data moves, and mark every entry point and every trust boundary it crosses. A session that tries to model the whole platform produces a vague list nobody acts on. One flow produces threats a reviewer can check in code.
Before you name threats, identify assets and potential attackers the way a threat model is supposed to start: what you're protecting, and who would benefit from breaking it. Then walk each element through STRIDE. Write a concrete threat only where the category applies. Rate likelihood and impact, record the control, and name an owner.
| Threat | Question to ask | Example in a SaaS app | Control to verify |
|---|---|---|---|
| Spoofing | Can someone pretend to be another user or service? | Forged or replayed session token | Token signature and expiry checks, MFA for admins |
| Tampering | Can data be changed in transit or at rest without detection? | User edits a price in the request body | Server-side recalculation and integrity checks |
| Repudiation | Can an actor deny an action with no record of it? | Admin deletes customer records with no log entry | Audit logs for privileged actions |
| Information disclosure | Can data leak to people who should not see it? | API returns another tenant's invoices | Tenant-scoped queries and field-level filtering |
| Denial of service | Can one request or user exhaust the system? | Unthrottled CSV export locks the database | Rate limits, quotas and query timeouts |
| Elevation of privilege | Can a user gain rights they should not have? | Profile update accepts a role field | Server-side role checks on every write |
Each row is a failure you've probably shipped once. A checkout that trusts the price in the JSON body is tampering. A profile endpoint that accepts role=admin is elevation of privilege. An export with no quota is denial of service aimed at your own database.
NIST's Secure Software Development Framework practice PW.2 says teams should review the design to confirm it meets security requirements and addresses identified risks. PW.2.1 recommends a qualified reviewer who wasn't involved in the design, or automated review built into the toolchain. Authors miss their own assumptions. Independence is how those assumptions get challenged. Automation can gather evidence faster. A senior engineer still owns the decision and what happens if it's wrong.
If an AI agent can call internal tools, treat its permissions as a new trust boundary. Model it like a service account with broad reach, not like a helpful teammate.
The result is a short threat list: one mitigation and one owner per item. The code review checks that list. It doesn't invent a new one in the pull request.
Run this on every change that touches a trust boundary. The reviewer is not the author. A new endpoint with no authorization test doesn't merge.

The OWASP Secure Code Review Cheat Sheet treats architecture analysis, threat modeling, manual inspection, and automated testing as one review. A scanner report isn't the review. Manual reading catches missing authorization, unsafe business logic, and wrong assumptions about how data moves. Those are the flaws tools skip.
Authentication. Identity is checked on every protected route, not only on the main login. Red flag: a new admin path that assumes the gateway already did the work.
Authorization. The server enforces the rule. Client-side checks are usability, not control. Red flag: a hidden button with no matching check on the API.
Untrusted input. Trace each value from source, through validation and business logic, to sinks such as SQL, shell commands, HTML, and file paths. Red flag: a string that reaches a query after one regex "because the UI is typed."
Cryptography. Standard libraries and algorithms, keys stored outside the repo. Red flag: a homegrown cipher or a key in a config file committed to git.
Errors and logging. No stack traces to users, no secrets in logs, an audit trail for admin actions. Red flag: a catch block that returns the database error to the browser.
Configuration and dependencies. Every environment change, new package, and version bump gets the same eyes as application code. Red flag: a "temporary" debug flag that ships.
Log each finding with the affected asset, exploit preconditions, source-to-sink path, business impact, evidence, owner, and retest criteria. Rank by exploitability and impact, not by the scanner's severity label.
Every change passes architecture review by a named architect, automated tests, a security review, observability, and a documented runbook and decision record. When an agent wrote or edited the diff, I would review it more strictly than ordinary code, not less. A benchmark covering more than 30,000 systems and 400 billion lines of code found AI-generated code carried roughly twice the security-risk violations of human-written code, while that code was 1.9% of enterprise production code, and 67% of organizations had widely adopted AI coding assistants, according to the Software Improvement Group State of Software 2026 report.
Check generated paths for invented libraries, missing authorization on new routes, secrets in prompts or config, and tool permissions as wide as a privileged service account. Passing a linter doesn't establish safety. The agent isn't the reviewer.
A senior engineer signs authentication, access control, cryptography, and production configuration. When AI speeds implementation, that same accountability covers data, security, integration, and production quality. A 2017 study of 3,126 GitHub projects, with 489,038 issues and 382,771 pull requests, found that reviewing pull requests was negatively associated with the number of security bugs reported. Generated changes still pass that gate. The output is a reviewed pull request, each finding logged with its path and its owner.
A clean scanner report is not a clean review. It means the patterns that tool knows didn't fire. Authorization and business logic can still be wrong.
A National Institute of Standards and Technology analysis of 37,325 categorized vulnerabilities in the U.S. National Vulnerability Database for 2008–2016 found that 27,242 (72.9%) were implementation or coding errors. Static analysis detected about 20% of CVE-defined errors. Formal code inspection was estimated to prevent an average of about 65% of errors from reaching released products. Coding flaws didn't fade as teams got more mature. Faster code production, including AI-assisted changes, increases the volume of implementation diffs that still need a human.
| Method | Strongest at | Blind spots | When to run |
|---|---|---|---|
| SAST | Code patterns such as injection sinks and hardcoded secrets | Authorization gaps and business logic | Every pull request |
| SCA | Known vulnerable dependencies and licence issues | Whether the vulnerable code path is reachable | Every build and a scheduled daily scan |
| DAST | Runtime behavior, misconfiguration and exposed endpoints | Root cause in the code | Staging before each release |
| Manual code review | Authorization, trust boundaries and logic flaws | Breadth across a large codebase | Changes to auth, data flows and integrations |
| Penetration test | Chained attacks and realistic exploit paths | Full coverage in a short window | Before major releases and after big architecture changes |
SAST on every pull request catches the repeated mistakes: injection sinks, hardcoded secrets. It won't tell you that tenant A can read tenant B.
SCA on every build, plus a daily scan, flags known-bad libraries and licence problems. It won't tell you whether that function is reachable from the internet.
DAST against staging before release shows misconfiguration and exposed endpoints. It rarely points at the line to fix.
Teams in regulated environments already know that security weak spots in healthcare IT hide in integrations and operations, not only in a single function. The same split shows up in SaaS: the tool finds the pattern, a person has to judge the path.
Triage by exploitability and business impact, not by the vendor's severity word. Suppress a false positive only with a written reason, and reread those reasons each quarter. Wire results into CI so an exploitable critical finding blocks the merge. Treat that pipeline as security as code: the check lives with the build, and a human still owns the exception.
A green build proves the tools you configured didn't fail. It doesn't prove the design is safe.
Output: a triaged scan log with suppressions and reasons, plus a short list that needs human review. That list is the input to code review and to the penetration test, not a substitute for either.
The failure mode isn't a weak tester. It's a test with no rules, a moving target, and a report nobody retests. Fieldwork starts, staging changes under the tester, and the findings can't be reproduced on Monday.
Write the goal and the rules of engagement. Name target systems, test windows, test accounts, and forbidden actions. Denial-of-service against production is off the list unless you have explicitly accepted that risk in writing. If you don't have that document, you don't have a test. You have an incident waiting for a name.
Hand over the architecture note and the threat model. The tester should spend time on logic and chained attacks, not on rediscovering your login URL. Discovery time is expensive. Give it away on purpose.
Freeze scope before fieldwork. Log every change to that scope. A new endpoint added on day two is a new engagement, not a footnote.
Name a contact and an escalation path. Someone who can stop the test in minutes if it starts hurting a shared environment. Put the phone number in the rules, not in a Slack thread from last quarter.
Require reproduction steps, evidence, and fix guidance on every finding. A severity label without steps is a conversation, not a defect. If a developer can't replay it, it isn't fixed, and it isn't real yet.
Book the retest when you book the test. Every high and critical finding gets a second pass after the fix lands. Leaving retest as "we'll schedule later" is how the report becomes shelfware.
Run it before a major release, after a large architecture change, or when a new integration starts handling customer data. Prefer staging with production-like data. Production is in bounds only when the rules of engagement say so.
The report isn't the end of the review. Verified fixes are. If a tester finds something outside the window, point them at a responsible vulnerability disclosure path so the issue has an owner instead of a surprise email. And don't confuse this exercise with the checks you already run in CI. The difference between security testing and penetration testing is the difference between "does this control fire" and "can someone chain three weak spots into account takeover."
Output: signed rules of engagement, a report with reproduced findings, and retest results for each serious issue.
Finding issues is half the job. Veracode's 2024 report found that only 35% of applications demonstrated sustained capacity to eliminate all critical security debt. Broader historical figures in that same reporting showed 76% of applications had at least one vulnerability, and half of findings remained open six months after discovery. A review that stops at the PDF leaves that debt in production.

Set service levels your pipeline can enforce:
Track vulnerability half-life, reopened findings, escape rate into production, critical items past SLA, and the share of releases with threat-model and manual-review sign-off. API scanning, in the historical data behind that report, reduced the time to fix half of findings by 17.5 days. Nearly one-third of applications had more findings in third-party libraries than in native code, so dependency inventory, version pinning, and a real upgrade path are review outputs, not procurement chores.
A calendar reminder isn't a trigger model. An ACM study of software supply-chain security indicates that only vendors of components considered high-risk or critical, such as those storing customer data, generally receive an annual re-review. Lower-profile components and business-critical transitive dependencies fall out unless you name a trigger.
Re-open the review when you add internet exposure, change authentication, start processing personal data, take a major dependency upgrade, transfer ownership, alter a data flow, or grant new AI-agent permissions. The evidence pack is reachability, data sensitivity, compensating controls, and business impact, not a fresh vulnerability count.
One page: open critical count, age of each item, and accepted risks with a named approver and an expiry date. Accepted risk without an expiry is a permanent exception. Each engagement we hand over includes the source repository, architecture and decision records, test evidence, a deployment and operating runbook, an access and responsibility map, documentation, monitoring, and knowledge transfer, so the next owner isn't guessing. A technology or modernization assessment, roadmap, or architecture review is a fixed fee, which keeps the decision about scope separate from an open-ended audit.
This week, pick one service. Run the seven phases. Set the SLAs before the next release. That's the control. Everything else is commentary.
Rite NRG runs software security review as part of delivery, not as a late scan: architecture sign-off, tests, security review, observability, and a runbook on every change, with senior engineers accountable when AI speeds the build. If you want that control on a platform you're shipping or modernizing, start with a fixed-fee assessment and a named owner for each phase. Visit Rite NRG and tell us which service you want in scope first.
/ about the author
Written by the RITE NRG editorial team — the architects, engineers and delivery leads who build and operate AI-era software for our clients.
Strategy & Transformation
A practical, finance-ready framework for comparing AI and modernization investment with the current-state cost, realistic benefits, delivery risk and time to value.
Technology Talent & Teams
A decision-maker's guide to IT partnership models: what each model actually transfers to the partner, what it costs beyond the rate card, and how to match the model to your situation.
AI Consulting & Automation
A practical framework for choosing and deploying transport or logistics AI agents around real exceptions, reliable data and controlled operational authority.
More guidance: all insights articles
Tell us about the system or idea behind this article. We tell you honestly if it is a fit — and what a fixed-scope delivery could look like.