mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-06-08 07:13:53 +02:00
Address remaining safe security hardening
This commit is contained in:
@@ -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:', () => {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 "I am an Infonet citizen" 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 && (
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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:",
|
||||
|
||||
Reference in New Issue
Block a user