HeardOf

This is a sample report for a fictional client, Lumen Payroll. The numbers are illustrative; the structure, statistics and fix artifacts are exactly what a real audit produces. Join the waitlist to have one run on your site.

Lumen Payroll: visibility and experience audit

lumenpayroll.com, audited 9 Oct 2026

Domain trust for lumenpayroll.com

Checked 09 Oct 2026 09:14 UTC
Overall
57needs work
HTTPS and TLS
87good
TLSv1.3, certificate 83 days left
Security headers
5poor
MDN Observatory grade F
Email authentication
37poor
SPF missing, DMARC missing
JavaScript libraries
85good
3 detected, 1 vulnerable

Passive checks only: the same requests a visitor’s browser and a receiving mail server make. Nothing is probed, scanned or logged in to. Findings describe what was observed; they are not a security certification.

Findings

  1. highmeasured

    No SPF record on lumenpayroll.com

    TXT lumenpayroll.com: no v=spf1 record. MX: aspmx.l.google.com, alt1.aspmx.l.google.com, alt2.aspmx.l.google.com, alt3.aspmx.l.google.com, alt4.aspmx.l.google.com

    Why it matters: Receivers cannot tell which servers may send mail as this domain, so legitimate mail is more likely to land in spam and spoofed mail is more likely to be delivered. Since February 2024 Gmail and Yahoo require bulk senders (5,000+ messages a day to their users) to publish SPF and DKIM, a DMARC policy (p=none at minimum) aligned with the From domain, and one-click unsubscribe; since 5 May 2025 Microsoft (Outlook.com, Hotmail, Live) applies the same SPF, DKIM and DMARC requirements and rejects non-compliant bulk mail. Smaller senders are increasingly filtered on the same signals.

    Fix: Publish one SPF record listing every service that sends as lumenpayroll.com (add your newsletter/CRM provider's include too).

    Show the code
    Type: TXT
    Name: lumenpayroll.com
    Value: v=spf1 include:_spf.google.com ~all
    TTL: 3600
    
    ; zone-file form
    lumenpayroll.com. 3600 IN TXT "v=spf1 include:_spf.google.com ~all"
    lumenpayroll.comeffort Sworker/trust (node:dns)trust.email.spf_missing
  2. highmeasured

    No DMARC record on lumenpayroll.com

    TXT _dmarc.lumenpayroll.com: no v=DMARC1 record

    Why it matters: DMARC tells receivers what to do with mail that fails SPF/DKIM alignment and sends you reports of who is sending as your domain. Without it, anyone can spoof the From address. Since February 2024 Gmail and Yahoo require bulk senders (5,000+ messages a day to their users) to publish SPF and DKIM, a DMARC policy (p=none at minimum) aligned with the From domain, and one-click unsubscribe; since 5 May 2025 Microsoft (Outlook.com, Hotmail, Live) applies the same SPF, DKIM and DMARC requirements and rejects non-compliant bulk mail. Smaller senders are increasingly filtered on the same signals.

    Fix: Start in monitoring mode, read the reports for 2–4 weeks, then move to p=quarantine and p=reject.

    Show the code
    Type: TXT
    Name: _dmarc.lumenpayroll.com
    Value: v=DMARC1; p=none; rua=mailto:dmarc-reports@lumenpayroll.com; adkim=r; aspf=r; fo=1
    TTL: 3600
    
    ; zone-file form
    _dmarc.lumenpayroll.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@lumenpayroll.com; adkim=r; aspf=r; fo=1"
    lumenpayroll.comeffort Sworker/trust (node:dns)trust.email.dmarc_missing
  3. mediummeasured

    HSTS is switched off (max-age=0)

    strict-transport-security: max-age=0 — max-age=0 (0 days) is under one year; includeSubDomains is missing; preload is missing

    Why it matters: A max-age of at least one year with includeSubDomains is the hstspreload.org requirement; under six months is penalised by MDN Observatory (hsts-implemented-max-age-less-than-six-months, −10).

    Fix: Once every subdomain serves HTTPS, send.

    Show the code
    # nginx (server block)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Strict-Transport-Security = max-age=63072000; includeSubDomains; preload
    then submit the domain at https://hstspreload.org.
    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.hsts.weak
  4. mediummeasured

    No Content-Security-Policy

    No content-security-policy header or <meta http-equiv> on the home page.

    Why it matters: A CSP is the main browser defence against injected scripts (XSS) and malicious third-party code. (MDN Observatory: csp-not-implemented, −25.)

    Fix: Start in report-only mode, fix what it reports, then enforce. A starting policy.

    Show the code
    # nginx (server block)
    add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Content-Security-Policy-Report-Only", "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Content-Security-Policy-Report-Only", value: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Content-Security-Policy-Report-Only = default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests
    Add every third-party origin your pages load (analytics, fonts, embeds) to the matching directive.
    lumenpayroll.com/effort Mworker/trust (MDN Observatory rules)trust.headers.csp_missing
  5. mediummeasured

    The page can be framed by any site (no X-Frame-Options or CSP frame-ancestors)

    x-frame-options: (absent); CSP frame-ancestors: absent

    Why it matters: Another site can load this page invisibly in a frame and trick visitors into clicking (clickjacking). (MDN Observatory: x-frame-options-not-implemented, −20.)

    Fix: Send either header (both is fine).

    Show the code
    # nginx (server block)
    add_header Content-Security-Policy "frame-ancestors 'self'" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Content-Security-Policy "frame-ancestors 'self'"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Content-Security-Policy", "value": "frame-ancestors 'self'" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Content-Security-Policy", value: "frame-ancestors 'self'" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Content-Security-Policy: frame-ancestors 'self'
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Content-Security-Policy = frame-ancestors 'self'
    
    # nginx (server block)
    add_header X-Frame-Options "SAMEORIGIN" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set X-Frame-Options "SAMEORIGIN"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "X-Frame-Options", "value": "SAMEORIGIN" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      X-Frame-Options: SAMEORIGIN
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   X-Frame-Options = SAMEORIGIN
    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.headers.clickjacking
  6. mediummeasured

    moment.js 2.30.1 has 1 known vulnerability

    https://static.lumenpayroll.com/universal/scripts-compressed/extract-css-moment-js-vendor-a5cfdec1ae227f33-min.en-US.js (detected by filecontent). CVE-2026-17495, GHSA-4p3w-j4w9-5jqw. moment vulnerable to Path Traversal via crafted non-string locale name

    Why it matters: Automated scanners fingerprint library versions and try the published exploits. Whether a given flaw is reachable depends on how the page uses the library, so treat this as an upgrade task rather than proof of compromise.

    Fix: Upgrade moment.js to 2.31.0 or later (npm: npm install moment@latest; CDN: change the version in the script URL). Check the changelog for breaking changes. This file is served by the site platform, so the upgrade is the platform's to make; report it to them.

    static.lumenpayroll.com/universal/scripts-compressed/extract-css-moment-js-vendor-a5cfdec1ae227f33-min.en-US.jseffort Mworker/trust (retire.js repository)trust.libraries.vulnerable
  7. lowmeasured

    10 third-party scripts use protocol-relative URLs (//host/…)

    //use.typekit.net/ik/55ov5wGkYOpoENT-j9tEc6YgGNMD54Cfz1TpzvTBUyvfeGSgfFHN4UJLFRbh52jhWDmcjRwXw29DwQJa5QiRFcZRZ2SD5ejajsG, //static.lumenpayroll.com/@sqs/polyfiller/1.7.7/modern.js, //static.lumenpayroll.com/universal/scripts-compressed/visitor-site-error-reporter-e9c24af58b4efe13-min.en-US.js, //static.lumenpayroll.com/universal/scripts-compressed/extract-css-runtime-fde12d4f2db1af19-min.en-US.js, //static.lumenpayroll.com/universal/scripts-compressed/extract-css-moment-js-vendor-a5cfdec1ae227f33-min.en-US.js

    Why it matters: On this HTTPS page they load over HTTPS, but the same markup served over HTTP would load them insecurely; MDN Observatory therefore scores them as not loaded securely (MDN Observatory: sri-not-implemented-and-external-scripts-not-loaded-securely, -50.)

    Fix: Write the scheme explicitly: src="https://host/…" instead of src="//host/…" (platform-generated tags, e.g. on the site builder, may not be editable).

    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.headers.protocol_relative_scripts
  8. lowmeasured

    No MTA-STS policy

    TXT _mta-sts.lumenpayroll.com: none

    Why it matters: Mail between servers falls back to unencrypted delivery when TLS fails or is stripped; MTA-STS (RFC 8461) tells senders to require TLS to your MX hosts.

    Fix: Paste the matching snippet for your setup.

    Show the code
    Type: TXT
    Name: _mta-sts.lumenpayroll.com
    Value: v=STSv1; id=20261020231447
    TTL: 3600
    
    ; zone-file form
    _mta-sts.lumenpayroll.com. 3600 IN TXT "v=STSv1; id=20261020231447"
    
    # Serve this file at https://mta-sts.lumenpayroll.com/.well-known/mta-sts.txt (HTTPS, valid certificate, no redirects)
    version: STSv1
    mode: testing
    mx: aspmx.l.google.com
    mx: alt1.aspmx.l.google.com
    mx: alt2.aspmx.l.google.com
    mx: alt3.aspmx.l.google.com
    mx: alt4.aspmx.l.google.com
    max_age: 604800
    
    # then switch mode: testing → enforce after a week of clean TLS-RPT reports
    lumenpayroll.comeffort Mworker/trust (node:dns)trust.email.mta_sts_missing
  9. lowmeasured

    No CAA record (any CA may issue certificates)

    CAA lookup from lumenpayroll.com up to lumenpayroll.com: none

    Why it matters: CAA (RFC 8659) lists the certificate authorities allowed to issue for the domain; every public CA must check it, which blocks mis-issuance by any other CA.

    Fix: ; your current certificate is from Let's Encrypt / YR2

    Show the code
    lumenpayroll.com. 3600 IN CAA 0 issue "letsencrypt.org"
    lumenpayroll.com. 3600 IN CAA 0 iodef "mailto:security@lumenpayroll.com"
    lumenpayroll.comeffort Sworker/trust (node:dns)trust.dns.caa_missing
  10. infomeasured

    No Referrer-Policy header

    referrer-policy: (absent)

    Why it matters: Without a policy, older browsers send the full URL (including query strings that may hold IDs or tokens) to every third party. Modern browsers default to strict-origin-when-cross-origin. (MDN Observatory: referrer-policy-not-implemented, 0; setting a private policy earns +5.)

    Fix: Paste the matching snippet for your setup.

    Show the code
    # nginx (server block)
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Referrer-Policy: strict-origin-when-cross-origin
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Referrer-Policy = strict-origin-when-cross-origin
    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.headers.referrer_policy
  11. infomeasured

    No Permissions-Policy header

    permissions-policy: (absent)

    Why it matters: Permissions-Policy switches off powerful browser features (camera, microphone, geolocation, payment) the site does not use, so an injected or third-party script cannot request them. Not scored by MDN Observatory.

    Fix: Paste the matching snippet for your setup.

    Show the code
    # nginx (server block)
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Permissions-Policy = camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()
    lumenpayroll.com/effort Sworker/trusttrust.headers.permissions_policy
  12. infomeasured

    No Cross-Origin-Opener-Policy

    cross-origin-opener-policy: (absent)

    Why it matters: COOP isolates the page from windows it opens or that open it, blocking cross-window attacks (XS-Leaks, tabnabbing). (MDN Observatory: coop-not-implemented, 0; same-origin earns +10.)

    Fix: Paste the matching snippet for your setup.

    Show the code
    # nginx (server block)
    add_header Cross-Origin-Opener-Policy "same-origin-allow-popups" always;
    
    # Apache (.htaccess or vhost, mod_headers)
    Header always set Cross-Origin-Opener-Policy "same-origin-allow-popups"
    
    # Vercel (vercel.json)
    { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Cross-Origin-Opener-Policy", "value": "same-origin-allow-popups" } ] } ] }
    
    # Next.js (next.config.js)
    async headers() { return [{ source: "/(.*)", headers: [{ key: "Cross-Origin-Opener-Policy", value: "same-origin-allow-popups" }] }]; }
    
    # Cloudflare Pages / Netlify (_headers file)
    /*
      Cross-Origin-Opener-Policy: same-origin-allow-popups
    
    # Cloudflare (proxied sites): Rules > Transform Rules > Modify Response Header > Set static
    #   Cross-Origin-Opener-Policy = same-origin-allow-popups
    (use same-origin if the site never relies on popups such as OAuth or payment windows talking back to it)
    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.headers.coop
  13. infomeasured

    1 cookie without a SameSite attribute

    crumb=<redacted>;Secure;Path=/

    Why it matters: Browsers default missing SameSite to Lax, but being explicit protects older browsers against cross-site request forgery; anti-CSRF cookies without it are penalised by MDN Observatory (cookies-anticsrf-without-samesite-flag, −20).

    Fix: Add SameSite=Lax (or Strict for cookies never needed on cross-site navigation).

    lumenpayroll.com/effort Sworker/trust (MDN Observatory rules)trust.cookies.no_samesite
  14. infomeasured

    No DKIM key found on common selectors

    Probed google._domainkey.lumenpayroll.com, selector1._domainkey.lumenpayroll.com, selector2._domainkey.lumenpayroll.com, k1._domainkey.lumenpayroll.com … (19 selectors). DKIM may still be configured on a selector we did not try; selectors are only visible in a signed message's DKIM-Signature header (s=).

    Why it matters: DKIM signs each message so receivers can verify it was not altered and that the domain sent it. Since February 2024 Gmail and Yahoo require bulk senders (5,000+ messages a day to their users) to publish SPF and DKIM, a DMARC policy (p=none at minimum) aligned with the From domain, and one-click unsubscribe; since 5 May 2025 Microsoft (Outlook.com, Hotmail, Live) applies the same SPF, DKIM and DMARC requirements and rejects non-compliant bulk mail. Smaller senders are increasingly filtered on the same signals.

    Fix: Check a message you sent (Show original → DKIM-Signature s=…). If DKIM is off, enable it in your mail provider (Google Workspace: Admin › Apps › Gmail › Authenticate email; Microsoft 365: Defender › Email authentication › DKIM) and publish the TXT/CNAME it gives you.

    lumenpayroll.comeffort Sworker/trust (node:dns)trust.email.dkim_not_found
  15. infomeasured

    No TLS-RPT record

    TXT _smtp._tls.lumenpayroll.com: none

    Why it matters: TLS-RPT (RFC 8460) makes senders report failed encrypted deliveries to you, which is how you learn MTA-STS or certificate problems are dropping mail.

    Fix: Paste the matching snippet for your setup.

    Show the code
    Type: TXT
    Name: _smtp._tls.lumenpayroll.com
    Value: v=TLSRPTv1; rua=mailto:tlsrpt@lumenpayroll.com
    TTL: 3600
    
    ; zone-file form
    _smtp._tls.lumenpayroll.com. 3600 IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@lumenpayroll.com"
    lumenpayroll.comeffort Sworker/trust (node:dns)trust.email.tls_rpt_missing

Email authentication

Google and Yahoo (Feb 2024) and Microsoft (May 2025) require SPF, DKIM and DMARC from bulk senders
MX
aspmx.l.google.com, alt1.aspmx.l.google.com, alt2.aspmx.l.google.com, alt3.aspmx.l.google.com, alt4.aspmx.l.google.com
SPF
missing
SPF DNS lookups
0 of 10 allowed
DMARC
missing
DKIM
not found on 19 common selectors (it may use another)
MTA-STS
not set
TLS-RPT
not set
BIMI
not set

HTTPS, certificate and headers

HTTP to HTTPS
http unavailable
HSTS
max-age=0
Certificate
Let's Encrypt / YR2; valid until 2027-01-12T17:07:50.000Z; trusted
Legacy TLS 1.0/1.1
refused
Content-Security-Policy
missing
Cookies on the home page
1 (0 without Secure, 1 without SameSite)
CAA records
none

JavaScript libraries

matched against the retire.js database (Apache-2.0 (retire.js repository, code and data))
  • moment.js 2.30.1 1 known vulnerability (CVE-2026-17495, GHSA-4p3w-j4w9-5jqw)
  • YUI 3.17.2 no known vulnerabilities
  • lodash 4.18.1 no known vulnerabilities