All articles
Web SecuritySecurity HeadersHTTPS

Why Does My Website Have a Low Security Grade? 12 Common Causes

Wondering why your website has a low security grade? Here are the most common reasons scanners flag sites, with concrete fixes for each one.

WebSentry TeamMay 16, 20266 min read

You ran your site through a security scanner expecting a clean bill of health and got back a C, D, or worse. Frustrating — especially when the site loads fine, has a padlock in the browser, and nothing obvious looks broken. The truth is that a low grade rarely means your site is hacked. It usually means a handful of configuration details are missing or misaligned with current best practice.

Here are the most common reasons sites land in the lower grades, and exactly what to change to fix them.

1. Missing or Weak Security Headers

This is the single biggest reason most sites score poorly. Browsers rely on HTTP response headers to know how to treat your content. If they're missing, the browser falls back to permissive defaults — and scanners penalise you heavily.

The headers you almost certainly need:

  • Strict-Transport-Security — forces HTTPS for future visits
  • Content-Security-Policy — controls what scripts/styles can load
  • X-Content-Type-Options: nosniff — stops MIME sniffing attacks
  • Referrer-Policy — controls what referrer info leaks to other sites
  • Permissions-Policy — restricts access to camera, mic, geolocation, etc.

A minimal but solid baseline for an Nginx config looks like this:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

2. No Content Security Policy (or a Bad One)

CSP is the header most likely to drop your grade by a full letter. It's also the trickiest to get right, which is why so many teams skip it.

Common CSP mistakes

  • Using unsafe-inline for scripts — defeats most of CSP's protection
  • Using * as a source — allows any origin
  • Setting CSP only in a meta tag (some directives only work as headers)
  • Forgetting frame-ancestors, which replaces the old X-Frame-Options

Start in report-only mode so you don't break the site:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://cdn.example.com; report-uri /csp-report

Once you've watched the reports for a week and tightened the policy, switch to the enforcing Content-Security-Policy header.

3. SSL/TLS Configuration Issues

Having HTTPS isn't enough. Scanners check how it's configured.

  • Outdated protocols — TLS 1.0 and 1.1 should be disabled. Only TLS 1.2 and 1.3 should be enabled.
  • Weak cipher suites — anything using RC4, 3DES, or CBC-mode ciphers with older protocols gets flagged.
  • Certificate chain problems — an incomplete intermediate chain works in Chrome but fails in other clients and drops your grade.
  • Short key lengths — RSA keys under 2048 bits are now considered weak.

If you're on Cloudflare or a managed host, set the minimum TLS version to 1.2 in the dashboard. On your own server, use Mozilla's SSL Configuration Generator to produce a modern config.

4. Insecure Cookie Flags

Every cookie your site sets should have the right flags. Missing flags are an easy win for raising your score.

  • Secure — only sent over HTTPS
  • HttpOnly — not accessible to JavaScript
  • SameSite=Lax or Strict — protects against CSRF

Check session cookies first — they're the highest-risk ones. In Express that looks like:

app.use(session({
  cookie: { secure: true, httpOnly: true, sameSite: 'lax' }
}));

5. Mixed Content

If your page is served over HTTPS but loads a script, image, or stylesheet over HTTP, the browser will either block it or downgrade the connection's trust level. Scanners flag this immediately.

Search your codebase for hardcoded http:// URLs and either update them or use protocol-relative URLs (//example.com/file.js). Add upgrade-insecure-requests to your CSP as a safety net.

6. Exposed Server Information

Default server installs cheerfully advertise themselves:

Server: Apache/2.4.41 (Ubuntu)
X-Powered-By: PHP/7.4.3

This tells attackers exactly which CVEs to try. Strip these headers:

  • Nginx: server_tokens off;
  • Apache: ServerTokens Prod and ServerSignature Off
  • PHP: expose_php = Off in php.ini
  • Express: app.disable('x-powered-by')

7. DNS Records Without Email Protection

Even if you don't send email from your domain, attackers can spoof it. Scanners that include DNS checks (like WebSentry) will dock points for missing SPF, DKIM, and DMARC records.

If your domain doesn't send mail at all, publish a null SPF and strict DMARC:

example.com. TXT "v=spf1 -all"
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"

8. Open CORS Policy

A surprising number of APIs respond with Access-Control-Allow-Origin: * alongside credentials. That combination is either ignored by browsers or actively dangerous depending on the setup.

List specific origins instead of using a wildcard, and only enable Access-Control-Allow-Credentials: true when you actually need authenticated cross-origin requests.

9. Outdated Software

Scanners that fingerprint your stack will flag known-vulnerable versions of WordPress, jQuery, Bootstrap, or your CMS plugins. There's no clever fix here — update them. Set a recurring calendar reminder if you have to.

10. Missing Subresource Integrity

If you load JavaScript from a CDN, an integrity attribute lets the browser verify the file hasn't been tampered with:

<script src="https://cdn.example.com/lib.js" 
  integrity="sha384-..." 
  crossorigin="anonymous"></script>

11. No HSTS Preload

Setting HSTS is good. Submitting your domain to the HSTS preload list is better — it means browsers refuse to ever connect over HTTP, even on the very first visit. Use a max-age of at least 31536000 (1 year), add includeSubDomains and preload, then submit at hstspreload.org.

12. Caching the Wrong Things

Sensitive pages (account dashboards, checkout) shouldn't be cached by CDNs or browsers. Set:

Cache-Control: no-store, no-cache, must-revalidate, private

The Order to Fix Things In

If you want the biggest grade jump for the least effort, work through these in order:

  1. Fix TLS configuration and disable old protocols
  2. Add the basic header set (HSTS, nosniff, Referrer-Policy, Permissions-Policy)
  3. Strip server version headers
  4. Fix cookie flags on session cookies
  5. Resolve any mixed content warnings
  6. Build a CSP in report-only mode, then enforce it
  7. Add DNS email protection records
  8. Tighten CORS and add SRI to third-party scripts

Most sites can move from a D or F to a B in a single afternoon by tackling the first five. The remaining points — particularly CSP — take longer because they require testing against your real frontend behaviour.

If you want to see exactly which of these are dragging your grade down, run your domain through a free scan at websentry.dev. WebSentry breaks the result down header by header, cookie by cookie, so you know which fixes will actually move the needle.

Check your own site

Run a free security scan and see if your site has the issues covered in this article. Results in under 30 seconds.