Address remaining safe security hardening

This commit is contained in:
BigBodyCobain
2026-06-02 13:34:11 -06:00
parent 10a8c7b5be
commit c3dd95f6a9
14 changed files with 94 additions and 47 deletions
@@ -147,18 +147,18 @@ describe('middleware matcher exclusions', () => {
});
// ---------------------------------------------------------------------------
// 5. Google Fonts domains are preserved in CSP
// 5. Runtime Google Fonts domains are not required in CSP
// ---------------------------------------------------------------------------
describe('Google Fonts domains in CSP', () => {
it('style-src includes https://fonts.googleapis.com', () => {
describe('local font CSP', () => {
it('style-src does not allow https://fonts.googleapis.com', () => {
const csp = getCsp();
expect(csp).toContain('https://fonts.googleapis.com');
expect(csp).not.toContain('https://fonts.googleapis.com');
});
it('font-src includes https://fonts.gstatic.com', () => {
it('font-src does not allow https://fonts.gstatic.com', () => {
const csp = getCsp();
expect(csp).toContain('https://fonts.gstatic.com');
expect(csp).not.toContain('https://fonts.gstatic.com');
});
});
@@ -178,9 +178,9 @@ describe('production CSP directive completeness', () => {
expect(csp).not.toMatch(/script-src [^;]*'nonce-/);
});
it('has style-src with unsafe-inline and fonts.googleapis.com', () => {
it('has style-src with hydration-compatible inline styles only', () => {
expect(csp).toMatch(/style-src [^;]*'unsafe-inline'/);
expect(csp).toMatch(/style-src [^;]*https:\/\/fonts\.googleapis\.com/);
expect(csp).not.toMatch(/style-src [^;]*https:\/\/fonts\.googleapis\.com/);
});
it('has worker-src self blob:', () => {
@@ -130,16 +130,17 @@ describe('unchanged directives in production', () => {
vi.unstubAllEnvs();
});
it('style-src preserves unsafe-inline and Google Fonts', () => {
it('style-src preserves unsafe-inline without runtime Google Fonts', () => {
const styleSrc = getDirective('style-src');
expect(styleSrc).toContain("'unsafe-inline'");
expect(styleSrc).toContain('https://fonts.googleapis.com');
expect(styleSrc).not.toContain('https://fonts.googleapis.com');
});
it('font-src preserves data: and fonts.gstatic.com', () => {
it('font-src preserves self and data without runtime Google Fonts', () => {
const fontSrc = getDirective('font-src');
expect(fontSrc).toContain("'self'");
expect(fontSrc).toContain('data:');
expect(fontSrc).toContain('https://fonts.gstatic.com');
expect(fontSrc).not.toContain('https://fonts.gstatic.com');
});
it('worker-src self blob:', () => {
+3 -3
View File
@@ -55,7 +55,7 @@
body {
background: var(--background);
color: var(--foreground);
font-family: 'JetBrains Mono', var(--font-roboto-mono), 'Roboto Mono', monospace;
font-family: var(--font-jetbrains-mono), var(--font-roboto-mono), 'Roboto Mono', monospace;
}
/* Global interactive cursor hints */
@@ -139,7 +139,7 @@ textarea:disabled {
padding: 12px 16px;
color: #d1d5db;
font-family:
'JetBrains Mono', var(--font-roboto-mono), 'Roboto Mono', monospace, 'Microsoft YaHei', 'PingFang SC',
var(--font-jetbrains-mono), var(--font-roboto-mono), 'Roboto Mono', monospace, 'Microsoft YaHei', 'PingFang SC',
'Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR', sans-serif;
font-size: 13px;
min-width: 240px;
@@ -377,7 +377,7 @@ textarea:disabled {
/* ── INFONET CRT TERMINAL EFFECTS ── */
.infonet-font {
font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
font-family: var(--font-jetbrains-mono), ui-monospace, SFMono-Regular, monospace;
}
/* CRT scanline overlay — scoped to .crt containers only */
+9 -6
View File
@@ -1,9 +1,17 @@
import type { Metadata } from 'next';
import { JetBrains_Mono } from 'next/font/google';
import DesktopBridgeBootstrap from '@/components/DesktopBridgeBootstrap';
import { ThemeProvider } from '@/lib/ThemeContext';
import { I18nProvider } from '@/i18n';
import './globals.css';
const jetBrainsMono = JetBrains_Mono({
subsets: ['latin'],
weight: ['400', '700'],
display: 'swap',
variable: '--font-jetbrains-mono',
});
export const metadata: Metadata = {
title: 'WORLDVIEW // ORBITAL TRACKING',
description: 'Advanced Geopolitical Risk Dashboard',
@@ -22,12 +30,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet" />
</head>
<body className="antialiased bg-[var(--bg-primary)]" suppressHydrationWarning>
<body className={`${jetBrainsMono.variable} antialiased bg-[var(--bg-primary)]`} suppressHydrationWarning>
<I18nProvider>
<ThemeProvider>
<DesktopBridgeBootstrap />
@@ -38,19 +38,17 @@ export default function FunctionKeyView({ onBack }: FunctionKeyViewProps) {
<ChevronLeft size={14} className="mr-1" /> BACK
</button>
<div className="text-sm text-purple-400 font-bold uppercase tracking-widest flex items-center gap-2">
<KeyRound size={16} /> FUNCTION KEYS Anonymous Citizenship Proof
<KeyRound size={16} /> FUNCTION KEYS Credential Scaffolding
</div>
<div />
</div>
<div className="flex-1 overflow-y-auto pr-3 space-y-4">
<div className="text-xs text-gray-400 leading-relaxed">
A citizen proves &quot;I am an Infonet citizen&quot; to a real-world
operator <span className="text-purple-400">without revealing their Infonet identity</span>.
The naive approach (scramble a public key, record each redemption on chain) leaks
identity through metadata correlation. The Function Keys design is six pieces;
five are implemented; one (issuance via blind signatures / anonymous credentials)
waits on a cryptographic primitive decision.
Function Keys wire the nullifier, receipt, and settlement plumbing for future
anonymous credential proofs. The current challenge-response is an HMAC placeholder,
not production zero-knowledge citizenship. True unlinkable issuance still waits on
blind signatures or anonymous credentials.
</div>
{status && (
+1 -1
View File
@@ -387,7 +387,7 @@ export function ThreatMarkers({
borderRadius: '4px',
padding: '8px 20px 8px 12px',
color: riskColor,
fontFamily: "'JetBrains Mono', monospace",
fontFamily: 'var(--font-jetbrains-mono), monospace',
fontSize: '12px',
fontWeight: 'bold',
textAlign: 'center',
+2 -2
View File
@@ -18,12 +18,12 @@ function buildCsp(nonce: string, strictScripts = false): string {
const directives = [
"default-src 'self'",
scriptSrc,
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob: https:",
isDev
? "connect-src 'self' ws: wss: http://127.0.0.1:8000 http://127.0.0.1:8787 https:"
: "connect-src 'self' ws: wss: https:",
"font-src 'self' data: https://fonts.gstatic.com",
"font-src 'self' data:",
"object-src 'none'",
"worker-src 'self' blob:",
"child-src 'self' blob:",