// SitePages.jsx — About, Resources, Contact with page-unique layouts + animations // ═══════════════════════════════ ABOUT ═══════════════════════════════ const AboutPage = () => ( <> {/* Mission manifesto — typewriter */}
{/* Specialty distribution — UNIQUE to about */}

The team

38 testers across six specialisms

{/* Story timeline */}

Story

Seven years of GreySurface

{/* Cert marquee with depth */}

Certifications held across the team, refreshed quarterly

{/* Reporting & compliance — anchored for nav/footer */}
{/* Careers — join the team */} ); // Careers pointer — the full role list lives on /careers/ const Careers = () => (

Careers

Join the team.

We hire experienced testers only. Six roles are open across web, identity, cloud, red team, mobile, and reporting.

e.currentTarget.style.background = '#828fff'} onMouseLeave={e => e.currentTarget.style.background = '#5e6ad2'}> See open roles
); // How we work — three steps; every promise here is already made on the pricing/contact pages const HowWeWork = () => (
{[ { n: '01', i: 'target', t: 'Scope with the person who tests', d: 'A thirty-minute call with one of our testers, not a salesperson. You get a written scope and a fixed quote within 48 hours.' }, { n: '02', i: 'terminal', t: 'Manual testing, tools second', d: 'Scanners find the known. Our testers chain the findings scanners miss, disclose critical issues within one hour, and post daily updates.' }, { n: '03', i: 'refresh', t: 'Retest, then attest', d: 'Every High and Critical finding is retested within 90 days at no charge, and your attestation letter is refreshed to match.' }, ].map(s => (
e.currentTarget.style.borderColor = '#34343a'} onMouseLeave={e => e.currentTarget.style.borderColor = '#23252a'}>
{s.n}

{s.t}

{s.d}

))}
); // Forward commitments only — promises written into every statement of work, not past statistics const Commitments = () => (
{[ { v: '1 business day', l: 'to reply to every enquiry' }, { v: '48 hours', l: 'from scoping call to fixed quote' }, { v: '1 hour', l: 'to disclose a critical finding' }, { v: '90 days', l: 'of free retesting after delivery' }, ].map(c => (
{c.v}
{c.l}
))}
); const ABOUT_FAQ = [ { q: 'Who actually does the testing?', a: 'Our own team of 38 testers, with a median tenure of nine years across six specialisms. Every engagement is led by someone with years of hands-on experience, and the person who scopes your engagement is one of the people who tests it.' }, { q: 'Can we speak to a tester before we commit?', a: 'Yes. Scoping is a free thirty-minute call with one of our testers. You receive a written scope and a fixed quote within 48 hours, with no obligation.' }, { q: 'What does "we stay until it is fixed" mean in practice?', a: 'Every High and Critical finding is retested within 90 days of report delivery at no extra charge, your attestation letter is updated to match, and the engagement channel stays open through retest. You always have one accountable person to call.' }, { q: 'How do you keep skills current?', a: 'Certifications across the team are refreshed quarterly, and testers publish research, advisories, and anonymized write-ups from engagements. Our first AI and LLM test plans were written in 2023, before most clients asked for them.' }, { q: 'Will you work under NDA?', a: 'Yes. Send us yours or ask for ours on the first call. Nothing about your environment needs to be shared until it is signed.' }, ]; const AboutHero = () => { const ref = React.useRef(null); const [pos, setPos] = React.useState({ x: 50, y: 30 }); const onMove = e => { const r = ref.current.getBoundingClientRect(); setPos({ x: ((e.clientX - r.left) / r.width) * 100, y: ((e.clientY - r.top) / r.height) * 100 }); }; return (
{/* Animated org-graph backdrop */}
About us

A dedicated team of penetration testers

GreySurface was founded in 2019 by three penetration testers who kept seeing assessments produce reports that nobody acted on. We built our engagement model around a single question: was the finding fixed?

{/* Quick stats strip below hero */}
{[ { v: '38', l: 'Testers' }, { v: '9 yr', l: 'Median tenure' }, { v: '94%', l: 'Re-engagement rate' }, { v: '120+', l: 'Active certifications' }, ].map(s => (
{s.v}
{s.l}
))}
); }; const Manifesto = () => { const lines = [ 'We only take engagements we can staff with experienced testers.', 'Every engagement is led by someone with years of hands-on experience.', 'We stay involved until your findings are fixed.', 'You always have one accountable person to call.', ]; return (

Manifesto

What we will not do.

{lines.map((l, i) => (
0{i + 1} {l}
))}
); }; const SpecialtyDistribution = () => { const ref = React.useRef(null); const [shown, setShown] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setShown(true); obs.disconnect(); } }, { threshold: 0.3 }); obs.observe(el); return () => obs.disconnect(); }, []); const specs = [ { l: 'Web & API security', n: 12, p: 32, tools: ['Burp Pro','Caido','sqlmap','Nuclei'] }, { l: 'Active Directory & ident.', n: 9, p: 24, tools: ['BloodHound','Rubeus','Certipy','NetExec'] }, { l: 'Cloud & Kubernetes', n: 6, p: 16, tools: ['Pacu','PMapper','CloudFox','peirates'] }, { l: 'Mobile & reversing', n: 5, p: 13, tools: ['Frida','Objection','Ghidra','MobSF'] }, { l: 'Red team & social', n: 4, p: 10, tools: ['Sliver','Mythic','Havoc','evilginx'] }, { l: 'IoT, OT & embedded', n: 2, p: 5, tools: ['Ghidra','binwalk','OpenOCD','SDR'] }, ]; return (
{specs.map((s, i) => (
{s.l} {s.n} testers · {s.p}%
{s.tools.map(t => ( {t} ))}
))}
); }; const Timeline = ({ items }) => (
{items.map((it, i) => (
{it.y}

{it.t}

{it.d}

))}
); const CertMarquee = () => { const certs = ['OSCP','OSEP','OSWE','OSED','OSCE3','OSWP','CRTO','CRTL','GPEN','GXPN','GWAPT','GMOB','GREM','GCFA','CRTM','eWPTX','BSCP','CISSP','CISM','CCSP','CREST CRT','CREST CCT-INF']; const tripled = [...certs, ...certs, ...certs]; return (
{tripled.map((c, i) => ( {c} ))}
); }; // ═══════════════════════════════ RESOURCES ═══════════════════════════════ const ResourcesPage = () => ( <> {/* Live advisory feed — UNIQUE typewriter ticker */}
{/* Featured report */}
{/* Threat trend chart — UNIQUE animated bar/line chart */}

Findings trend

What changed this year, across 600+ engagements

{/* Posts */}
{[ { tag: 'API', t: 'GraphQL alias batching: one request, a thousand auth checks bypassed', date: 'May 18', read: '12 min', href: '/blog/graphql-alias-batching-auth-bypass/' }, { tag: 'AD', t: 'ADCS ESC1 in the wild: eleven engagements, eight findings' }, { tag: 'AI', t: 'Indirect prompt injection through a calendar invite' }, { tag: 'Cloud', t: 'PMapper at scale: finding the role we should not be able to assume' }, { tag: 'Mobile', t: 'Frida-based jailbreak detection bypass' }, { tag: 'Web', t: 'HTTP/2 request smuggling: three gadgets from this quarter' }, ].map(p => )}
{/* CVE advisories */}

CVE advisories

Vulnerabilities we have disclosed

{/* Sample report */}
); const ResourcesHero = () => (
Resources

What we publish.
What we share.

Research, advisories, anonymized engagement write-ups, and a sample of the report you would receive.

{[ { l: '247', s: 'advisories shipped' }, { l: '84', s: 'write-ups' }, { l: '38', s: 'CVEs disclosed' }, ].map(k => (
{k.l}
{k.s}
))}
); const CveRainBackdrop = () => { // 12 columns each cycling a CVE ID falling, very subtle const cols = 14; return (
{Array.from({ length: cols }).map((_, i) => (
{Array.from({ length: 30 }).map((_, j) => { const c = i + j; return {`CVE-${2020 + (c % 6)}-${(c * 137) % 9999}`}; })}
))}
); }; const LiveAdvisoryFeed = () => { const items = [ { sev: 'CRIT', id: 'GS-2026-091', t: 'GraphQL alias batch · auth bypass disclosed', vendor: 'Hasura' }, { sev: 'HIGH', id: 'GS-2026-088', t: 'ADCS ESC1 misconfig allows DA cert forge', vendor: 'Internal AD' }, { sev: 'CRIT', id: 'CVE-2026-1042', t: 'Race condition in ssh-agent privilege drop', vendor: 'OpenSSH' }, { sev: 'MED', id: 'GS-2026-078', t: 'Stored XSS in admin moderator notes panel', vendor: 'SaaS app' }, { sev: 'HIGH', id: 'CVE-2025-3142', t: 'Realm-admin escalation via crafted SAML', vendor: 'Keycloak' }, { sev: 'CRIT', id: 'CVE-2025-0118', t: 'Auth bypass via UTF-8 normalization', vendor: 'pgbouncer' }, ]; return (
Live advisory feed
last 30 days · 247 total
{[...items, ...items].map((a, i) => (
{a.sev} {a.id} {a.vendor} {a.t}
))}
); }; const ThreatTrendChart = () => { const ref = React.useRef(null); const [shown, setShown] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setShown(true); obs.disconnect(); } }, { threshold: 0.3 }); obs.observe(el); return () => obs.disconnect(); }, []); const cats = [ { l: 'API', a: 41, b: 58, d: '+41%', up: true }, { l: 'AI/LLM', a: 12, b: 38, d: '+217%', up: true }, { l: 'Cloud', a: 28, b: 34, d: '+21%', up: true }, { l: 'Mobile', a: 22, b: 19, d: '−14%', up: false }, { l: 'Web', a: 47, b: 38, d: '−19%', up: false }, { l: 'AD/Identity', a: 36, b: 44, d: '+22%', up: true }, ]; return (
{cats.map((c, i) => (
{c.d}
{c.l}
))}
2024 baseline
2026 · rising surfaces
2026 · receding
); }; const FeatureReport = () => (
2026 · pentest trends

What 600+ engagements told us this year

The findings that shifted, the surfaces that broke, and the controls that held. 38 pages of anonymized, aggregated data.

{[ { v: '↑ 217%', l: 'LLM-related findings', c: '#e8543a' }, { v: '↑ 41%', l: 'API criticals, year over year', c: '#e8543a' }, { v: '↓ 19%', l: 'Web criticals, year over year', c: '#27a644' }, { v: '4 hr', l: 'Median time to Domain Admin', c: '#828fff' }, ].map(s => (
{s.v}
{s.l}
))}
); const PostCard = ({ tag, t, date, read, href }) => { const [h, setH] = React.useState(false); const live = !!href; return ( setH(true)} onMouseLeave={() => setH(false)} style={{ display: 'block', textDecoration: 'none', background: h ? '#141516' : '#0f1011', border: `1px solid ${h ? '#34343a' : '#23252a'}`, borderRadius: 12, padding: 22, position: 'relative', overflow: 'hidden', transition: 'all 220ms', transform: h ? 'translateY(-2px)' : 'translateY(0)', }}>
{tag} {live ? {date} · {read} : Coming soon}

{t}

{live ? 'Read note' : 'Browse the blog'}
); }; // What we publish — in-page index; every card jumps to a section further down this page const WhatWePublish = () => (
{[ { i: 'flame', t: 'Pentest Trends 2026', d: 'What 600+ engagements told us this year: the surfaces that broke and the controls that held.', href: '#report', cta: 'Read the summary' }, { i: 'code', t: 'Technical write-ups', d: 'Anonymized findings from the field, with the reproduction steps and the fix.', href: '#blog', cta: 'Browse write-ups' }, { i: 'bug', t: 'CVE advisories', d: 'Vulnerabilities our testers found in third-party software, disclosed to the vendor first.', href: '#cves', cta: 'See advisories' }, { i: 'layers', t: 'Sample report', d: 'A redacted report from a real engagement, so you know exactly what you receive.', href: '#sample', cta: 'Request a copy' }, ].map(c => ( { e.currentTarget.style.borderColor = '#34343a'; e.currentTarget.style.background = '#141516'; }} onMouseLeave={e => { e.currentTarget.style.borderColor = '#23252a'; e.currentTarget.style.background = '#0f1011'; }}>

{c.t}

{c.d}

{c.cta}
))}
); // Sample report — what a client receives, section by section const SampleReport = () => (

Sample report

See exactly what you receive.

A redacted report from a real engagement: the executive summary, three full findings with reproduction steps, and the retest delta. Sent on request, under NDA if you prefer.

e.currentTarget.style.background = '#828fff'} onMouseLeave={e => e.currentTarget.style.background = '#5e6ad2'}> Request the sample report
Contents
{[ ['01', 'Executive summary', '4 pages'], ['02', 'Scope and methodology', '3 pages'], ['03', 'Findings, by severity', '96 pages'], ['04', 'Attack narrative', '8 pages'], ['05', 'Remediation plan', '11 pages'], ['06', 'Retest delta', '5 pages'], ].map(([n, l, p]) => (
{n} {l} {p}
))}
); const CveTable = () => { const rows = [ { id: 'CVE-2024-23897', vendor: 'Jenkins', finding: 'CLI arbitrary file read', cvss: 9.8 }, { id: 'CVE-2024-21626', vendor: 'runc', finding: 'WORKDIR overwrite · host fd leak', cvss: 8.6 }, { id: 'CVE-2023-46604', vendor: 'ActiveMQ', finding: 'OpenWire deserialization → RCE', cvss: 10.0 }, { id: 'CVE-2025-0118', vendor: 'pgbouncer', finding: 'Auth bypass via UTF-8 normalization', cvss: 8.8 }, { id: 'CVE-2025-3142', vendor: 'Keycloak', finding: 'Realm-admin escalation via SAML', cvss: 9.1 }, { id: 'CVE-2026-1042', vendor: 'OpenSSH', finding: 'Race in ssh-agent privilege drop', cvss: 7.4 }, ]; return (
CVEVendorFindingCVSS
{rows.map((r, i) => (
e.currentTarget.style.background = '#141516'} onMouseLeave={e => e.currentTarget.style.background = 'transparent'}> {r.id} {r.vendor} {r.finding} = 9 ? '#e8543a' : r.cvss >= 7 ? '#d98326' : '#5e6ad2', fontFamily: 'var(--font-mono)', textAlign: 'right', fontWeight: 500 }}>{r.cvss.toFixed(1)}
))}
); }; // ═══════════════════════════════ CONTACT ═══════════════════════════════ const ContactPage = () => ( <> {/* Engagement flow — animated 4-step intake */}

Intake flow

From first email to testing in four business days

{/* Steps + form — #form is the deep-link target used site-wide (/contact/#form) */}
); const CONTACT_INBOX = 'info@greysurface.com'; const CONTACT_SUBJECT = 'Contact form — greysurface.com'; // Other ways to reach us — carries the #disclose anchor (Nav + Footer link to /contact/#disclose) const OtherWays = () => (
{[ { i: 'mail', t: 'Email us directly', d: 'For scoping, pricing, timing, or an MSA and NDA before we talk detail. One of our testers replies within one business day.', l: CONTACT_INBOX, href: `mailto:${CONTACT_INBOX}` }, { id: 'disclose', i: 'shield', t: 'Responsible disclosure', d: 'Found a vulnerability in one of our own systems? Email us with "Disclosure" in the subject line. We acknowledge every report within one business day and keep you informed until it is fixed.', l: 'Report a vulnerability', href: `mailto:${CONTACT_INBOX}?subject=${encodeURIComponent('Responsible disclosure — greysurface.com')}` }, { i: 'lock', t: 'PGP on request', d: 'Need to send something sensitive before an NDA is in place? Ask for our PGP key and we will reply with it from the same address.', l: 'Request our PGP key', href: `mailto:${CONTACT_INBOX}?subject=${encodeURIComponent('PGP key request — greysurface.com')}` }, ].map(c => (
); const CONTACT_FAQ = [ { q: 'How quickly will you reply?', a: 'Within one business day, from a tester who can talk scope rather than a sales queue. If the need is urgent, say so in the subject line and we will prioritise it.' }, { q: 'Will you sign an NDA before scoping?', a: 'Yes. Send us yours or ask for ours on the first call. Nothing about your environment needs to be shared until it is signed.' }, { q: 'Do you work with startups?', a: 'Yes. Every engagement is a fixed fee against a defined scope, so a single application or API is a small, well-bounded engagement rather than a minimum retainer. The same senior testers do the work regardless of size.' }, { q: 'What do you need from us to quote?', a: 'A list of what is in scope (URLs, applications, IP ranges, cloud accounts), how many roles and tenants are involved, whether testing is authenticated, and your target dates. With that, you receive a written scope and a fixed quote within 48 hours of the scoping call.' }, { q: 'Can you work with our procurement process?', a: 'Yes. We work with purchase orders, vendor onboarding questionnaires, and enterprise MSAs. Standard engagements are invoiced on delivery of the final report.' }, ]; const ContactHero = () => (
Contact

Get in touch

Tell us what you need tested. One of our testers replies within one business day to set up a scoping call.

); const EngagementFlow = () => { const [phase, setPhase] = React.useState(0); React.useEffect(() => { const id = setInterval(() => setPhase(p => (p + 1) % 4), 2200); return () => clearInterval(id); }, []); const steps = [ { n: '01', t: 'First call', d: 'Thirty minutes with one of our testers to agree on scope, threat model, and timing.', dur: 'Day 1' }, { n: '02', t: 'Scope and rules of engagement', d: 'A statement of work with explicit in-scope assets, out-of-scope boundaries, and rules of engagement, signed by both sides.', dur: 'Day 2' }, { n: '03', t: 'Kickoff and access', d: 'Your engagement manager joins your channel. Test accounts, allowlisting, and emergency contacts are arranged before testing starts.', dur: 'Day 3' }, { n: '04', t: 'Testing begins', d: 'Daily updates during testing, critical findings disclosed within one hour, and a channel that stays open through retest.', dur: 'Day 4+' }, ]; return (
{/* Connector line */}
{steps.map((s, i) => { const active = i === phase; const done = i < phase; return (
setPhase(i)}>
{done ? '✓' : s.n}
{s.dur}

{s.t}

{s.d}

); })}
); }; const ContactSteps = () => (

See GreySurface in action

{[ { i: 'radar', t: 'Discover', d: 'We identify the most critical vulnerabilities in your applications before real attackers do.' }, { i: 'shield', t: 'Mitigate', d: 'Remediate the findings and request a fix verification from the same team.' }, { i: 'refresh', t: 'Repeat', d: 'Repeating the process with every release keeps your security posture improving.' }, ].map(s => (

{s.t}

{s.d}

))}
); // Delivers to info@greysurface.com through Forms.jsx (loaded on /contact/, the only page that renders this) const ContactForm = () => { const [status, setStatus] = React.useState('idle'); // idle | sending | sent | error const onSubmit = async (e) => { e.preventDefault(); const form = e.currentTarget; setStatus('sending'); try { await submitToInbox(formToObject(form), { subject: CONTACT_SUBJECT }); setStatus('sent'); } catch (_) { setStatus('error'); } }; if (status === 'sent') { return (

Message received

One of our testers will reply within one business day.

); } return (
{status === 'error' && (

Your message could not be sent. Please email us directly at{' '} {CONTACT_INBOX}.

)}

Submissions go to {CONTACT_INBOX}. One of our testers replies within one business day.

); }; // ═══════════════════════════════ SHARED ═══════════════════════════════ const Field = ({ name, label, placeholder, type = 'text', textarea, required }) => { const Tag = textarea ? 'textarea' : 'input'; return ( ); }; const SelectField = ({ name, label, options }) => ( ); const SectionEdge = () =>
; const PageApp = ({ which }) => (
); Object.assign(window, { AboutPage, AboutHero, Manifesto, SpecialtyDistribution, Timeline, CertMarquee, Careers, HowWeWork, Commitments, ResourcesPage, ResourcesHero, CveRainBackdrop, LiveAdvisoryFeed, ThreatTrendChart, FeatureReport, SampleReport, PostCard, CveTable, WhatWePublish, ContactPage, ContactHero, EngagementFlow, ContactSteps, ContactForm, OtherWays, Field, SelectField, SectionEdge, PageApp, });