Every app you test in CodeReviewer gets a security grade from A to F. A single letter is easy to read at a glance. But you should know what’s behind it, and where it stops. That’s what this post is about.
What the grade measures
The grade comes from a passive security check. CodeReviewer visits your app, including the pages behind the login, and inspects what your server sends back. It doesn’t attack anything. The checks fall into four groups.
1. Transport security
- Is the site served only over HTTPS?
- Does it send HSTS, telling browsers never to fall back to plain HTTP?
- Are there mixed-content requests that load resources insecurely?
Transport problems let an attacker on the same network read or change traffic. They’re some of the most common issues, and some of the easiest to fix.
2. Content Security Policy and clickjacking
- Does the app send a Content Security Policy that limits where scripts can load from?
- Is the policy meaningful, or does it allow everything (
unsafe-inline, wildcards)? - Is the app protected from being framed by another site (clickjacking)?
A good CSP is one of the strongest defenses against cross-site scripting. Having some policy isn’t enough. The grade checks whether yours actually restricts anything.
3. Cookie flags
For every cookie your app sets, especially session cookies:
- Secure: sent only over HTTPS?
- HttpOnly: hidden from JavaScript, so a script injection can’t steal it?
- SameSite: kept off cross-site requests, which blunts cross-site request forgery?
A session cookie without these flags is one of the most direct routes to account takeover.
4. Libraries with known vulnerabilities
CodeReviewer identifies the front-end libraries your pages load and checks them against publicly known vulnerabilities (CVEs). An old version of a popular library with a published exploit is a low-effort target for attackers, and usually a quick upgrade for you.
How the letter is calculated
Each finding has a severity. The grade reflects the most serious issues found: a missing session-cookie flag or a library with a known critical vulnerability pulls the grade down much more than a missing low-impact header. Every finding comes with what it is, why it matters and how to fix it, so a C comes with a to-do list.
Why passive by default
Passive checks send no attack traffic. They read only what your app already serves to any visitor, which makes them safe to run anywhere, as often as you like: staging, production, on a schedule or on demand. Like every replay in CodeReviewer, they don’t use AI to run and are free to repeat.
What the grade doesn’t tell you
A passive grade is a floor, not a clean bill of health. By design it can’t find:
- Injection flaws, such as SQL injection or cross-site scripting, which only show up when you send crafted input.
- Broken access control, for example whether user A can read user B’s data by changing an ID.
- Business-logic flaws, like applying a discount twice or skipping a payment step.
An app can score an A and still have any of these. That’s why the grade is one layer of three.
Layer two: active scanning, on domains you own
Active scanning uses the industry-standard OWASP ZAP engine to probe your app the way an attacker would: sending crafted inputs, testing for injection and looking for weaknesses in your endpoints.
Because active scans send real attack-style traffic, CodeReviewer only runs them against domains you’ve verified you own. You prove ownership by publishing a DNS TXT record or placing a small file on the site. Ownership is re-checked regularly, and if the proof disappears, active scanning stops. This keeps the tool from being pointed at someone else’s site.
Layer three: a threat model from your own code
Scanners find what they can observe from outside. A threat model reasons about what an attacker would try. CodeReviewer reads your repository together with your scan results and maps likely threats to STRIDE (spoofing, tampering, repudiation, information disclosure, denial of service and elevation of privilege) and to MITRE ATT&CK techniques.
Threats confirmed by a live scan are marked as such, so you can tell theoretical risk from observed weakness. Security findings can be turned into issues, located in your code and fixed with one click, like any other finding.
How to use the three together
- Always on: the passive grade, on a schedule, on every environment. Treat any drop as a regression.
- Before releases and after big changes: active scans against your verified staging domain.
- Quarterly, or when the architecture changes: a fresh threat model.
The grade is a handy headline. The real value is underneath it: specific findings, with evidence, and a fix you can apply for each one.