External web app reports look alarming until you read them. A typical one from us has a handful of findings and almost all are configuration hygiene: a header that isn't set, a cookie flag missing, a version number the server didn't need to announce.
Here's what we actually report, in rough order of how often it turns up, with what each one means and what it costs to fix. If a report is already in your inbox, how to read your pen test report covers what order to work through it in.
How these get rated
Severity tracks exploitability, not how bad the word sounds. Missing security headers are Low, and go Medium only when the site runs sessions and has no HSTS. A tool's informational match isn't a finding. Provider infrastructure you don't control, like a Cloudflare edge, is a scope limitation we write down rather than a finding we bill you for.
Lift bands: minutes for one header or config line, an hour for a change plus a deploy, half a day for a change that needs testing, a sprint for real work, architectural for a design decision.
Low severity hygiene, in nearly every report
These pad out a report. Individually most buy an attacker very little. Together they're the cheapest security work you'll ever do, and clearing them turns a C into an A on a retest.
| Finding | What it means | Lift and owner |
|---|---|---|
| HSTS is not offered | Browsers try plain HTTP first on a new visit, so a first-time visitor on a hostile network can be pushed off HTTPS. Redirecting to HTTPS is not the same as telling the browser never to try it. | Minutes. One header, usually a toggle at your host or CDN. |
X-Content-Type-Options missing | Browsers are allowed to guess a file's type. On its own it does nothing, and it matters only alongside some other upload bug. | Minutes. One header. |
| No clickjacking protection | Nothing stops another site loading yours in a frame. The realistic attack needs a user tricked into clicking an invisible overlay, which is narrow. | Minutes. X-Frame-Options, or frame-ancestors in your CSP. |
Permissions-Policy missing | No declaration of which browser features (camera, mic, location) the page and its embeds may use. A compliance checkbox unless you embed third-party frames. | Minutes. One header. |
Server header gives product and version | The response announces exactly what you run, saving an attacker a step when a CVE lands for it. Generator tags and framework fingerprints in the page body do the same. Hiding them is not a fix for being out of date. | Minutes. Host or platform setting. |
X-Powered-By present | Same idea for the application stack. No direct risk, and free to remove. | Minutes. One config line. |
Referrer-Policy missing | Full URLs leak to third-party sites. Worth fixing if your URLs carry tokens or record IDs. | Minutes. One header. |
Cookies without Secure, HttpOnly or SameSite | Session cookies can be read by scripts, sent over plain HTTP, or attached to cross-site requests. The one hygiene item that touches sessions directly, so do it properly. | An hour. Developer, where the cookies get set. |
| TLS session ticket lifetime over a day | Tickets stay valid for a week (604800 seconds is the usual value), which weakens forward secrecy on resumed sessions. | Minutes if your provider exposes the setting, otherwise document it and move on. |
| Certificate and chain hygiene | OCSP stapling off, an incomplete chain, a longer certificate lifetime than needed. Nothing breaks, it's tidy-up. | Minutes to an hour. Host or CDN. |
| Directory listing enabled | A directory with no index page returns a file list. Usually harmless, occasionally it surfaces a backup nobody meant to publish. | Minutes. One web-server config line. |
Low to medium, worth a ticket
These take more than a header toggle, and two of them are the most likely to become a real problem later.
| Finding | What it means | Lift and owner |
|---|---|---|
| CSP missing or permissive | Nothing restricts where scripts may load from, so a content-injection bug has nothing in its way. A policy with unsafe-inline counts as permissive. The one missing-header finding that is genuinely work. | Half a day to a sprint. Developer. Report-only first, then enforce. |
| HTTP does not redirect to HTTPS | Plain HTTP serves content instead of sending visitors to the secure version. | Minutes. Platform redirect rule. |
| Mixed content | An HTTPS page pulls a script, image or stylesheet over HTTP. Browsers block most of it now, so the page is broken about as often as it's risky. | An hour. Developer. Fix the asset URLs. |
| CORS allows unintended origins | The app echoes back whatever origin asks, or pairs a wildcard with credentials, so another site's JavaScript can read authenticated responses. How bad depends on what the endpoint returns. | An hour to half a day. Developer. Allowlist specific origins. |
| Verbose errors and stack traces | An error page returns a framework trace, a file path or a query fragment. No access on its own, but it says exactly what you run and where. | An hour. Developer. A generic error handler. |
| Outdated front-end libraries | A library version on the page with published advisories. Often not reachable in a way that matters, so check before panicking. | An hour to a sprint. Developer, depending how far behind. |
| Outdated server runtime | The nginx, Node or PHP version actually serving the site is behind on patches. Of everything in this table, it's the one most likely to become a real incident. | An hour. Host or platform. A version bump and restart. |
| No rate limiting on login and forms | Nothing slows repeated attempts against sign-in, password reset or contact forms. Enables credential stuffing and spam rather than a direct break-in. | Half a day. Developer, or a rule at your CDN. |
| SPF, DKIM or DMARC missing or permissive | Your domain can be spoofed in email. Not a web finding, and our external scan doesn't check it, so check it yourself. | An hour. DNS or email admin. Three records. |
| Services exposed beyond 80 and 443 | A database port, an admin service or an old staging listener answering from the internet. Sometimes it's shared provider infrastructure, which is why we verify these by hand first. | Minutes to half a day. Host. A firewall rule. |
Medium and up, less common but real
| Finding | What it means | Lift and owner |
|---|---|---|
| Exposed admin, dev or backup paths | A .git directory, an environment file, a server-info page, an open admin login, a database dump in the web root. What it's worth depends on what's in the file, and config files with credentials are the bad case. | Minutes to remove, an hour to rotate anything that leaked. Developer plus whoever owns the secrets. |
| Component with a known CVE | A specific version with a published vulnerability, matched by signature. We check it's actually reachable before rating it, because a version match isn't an exploit. | An hour to a sprint. Developer or host. |
| Secrets in client-side JavaScript | An API key, token or internal endpoint in a bundle anyone can download. Some keys are meant to be public. Plenty aren't. | An hour to rotate, half a day to move the call server-side. Developer. |
The serious ones, and how often they actually show up
Injection and auth bypass are what people picture when they hear "pen test." On a one-day unauthenticated external test they're the exception. Plenty of our runs come back with zero confirmed template matches at low severity or above and two low findings, which is a normal result rather than a sign nobody looked.
Part of that is scope: the code where these bugs live is usually behind a login. A clean external report says the edge held up, not that the authenticated side is clean, which is why every report states coverage as a number and spells out what limited it.
| Finding | What it means | Lift and owner |
|---|---|---|
| Injection (SQL, command, template) | User input reaches an interpreter without being separated from the code around it. The classic serious finding, and the one most likely to put data at risk. | Half a day per instance, architectural if the pattern is everywhere. Developer. |
| Broken authentication or access control, including IDOR | A login step that can be skipped, a role that can be raised, or a record ID that can be changed to read someone else's data. In a multi-tenant product, the finding that matters most. | Half a day to a sprint. Developer. The checks belong server-side. |
| Server-side request forgery | A feature that fetches a URL you hand it can be aimed at internal addresses the internet shouldn't reach. | Half a day. Developer. Allowlist the destinations. |
| Unrestricted file upload | An upload that accepts any file type and stores it somewhere it can be served back out. | Half a day, architectural if uploads must move off the web root. Developer. |
What this list doesn't cover
- Email authentication records. Our external scan doesn't check SPF, DKIM or DMARC. It's in the table above because customers ask, and it's ten minutes of DNS work.
- Rate limiting, properly tested. We note it by inspection. Nobody should hammer your live login to prove a point.
- Anything behind a login, business logic, mobile apps, internal networks and cloud config. What a $495 pen test covers has the full boundary.
- Whatever a challenge page hid. When a CDN or WAF answers scanner traffic with a captcha, application coverage drops and the report says so with a figure attached.
Start with the cheap half
The free scan checks ten of the header, cookie and TLS items above and grades them in two minutes. Fix what it flags and you've cleared most of the first table before paying anyone.
When you need it written up with evidence, severities and an attestation letter an auditor will take, that's the $495 external test, back within 24 hours.