Each MOAD now has a synthetic defective specimen and fixed specimen proven from first principles across three test tiers: Unit (tests/unit/Moad000X*.java): - Correctness: defective and fixed produce identical functional output - Defect behavior: defective specimen exhibits the defect (measurable) - Fix behavior: fixed specimen eliminates the defect Integration (tests/integration/AllMoadsIntegrationTest.java): - All 9 MOADs proven at medium scale (N=500-2000) - MOAD-0001: O(N^2) vs O(N) list scan at N=1000 - MOAD-0002: 500 sessions trample each other (defective) vs coexist (fixed) - MOAD-0003: 250 anonymous requests leak auth identity (defective) vs zero (fixed) - MOAD-0004: 3000 credential exposures across 1000 requests (defective) vs zero (fixed) - MOAD-0005: 500 computes for 500 concurrent misses vs exactly 1 - MOAD-0006: all 500 passwords extractable from DB (defective) vs unextractable (fixed) - MOAD-0007: N=2000 spatial objects, defective visits all 2000 vs O(log N + k) - MOAD-0009: 990 wasted firings for 1000 ticks / 10 events vs zero waste - MOAD-0011: 10240 NFA steps vs 13 steps on N=12 adversarial input (788x) Functional (tests/functional/AllMoadsFunctionalTest.java): - MOAD-0005: real-thread contention proves herd (defective >1 compute, fixed exactly 1) - MOAD-0007: N=50000 spatial objects, 50M defective probes vs 516K fixed (97x speedup) - MOAD-0009: 10000 ticks / 10 events, 9990 wasted firings vs zero (1000x ratio) - MOAD-0011: N=16 adversarial, 163840 defective steps vs 17 fixed (9638x ratio) Support algorithms (tests/support/Moad000X*.java): - Moad0002Algorithm: shared mutable global state (DefectiveAudioSystem / FixedAudioSystem + Context) - Moad0003Algorithm: ThreadLocal not cleared (handleDefective / handleFixed with finally) - Moad0004Algorithm: HTTP headers logged verbatim (logDefective / logFixed with CREDENTIAL_HEADERS denylist) - Moad0005Algorithm: get+null+compute+put (DefectiveCache HashMap / FixedCache ConcurrentHashMap.computeIfAbsent) - Moad0006Algorithm: Base64 password storage (DefectiveCredentialStore / FixedCredentialStore SHA-256+salt) - Moad0007Algorithm: linear spatial scan (queryDefective list / queryFixed sorted array + binary search) - Moad0009Algorithm: timer-driven polling (runDefectiveScheduler / runFixedEventDriven) - Moad0011Algorithm: PCRE nested quantifiers (matchDefective backtracking NFA / matchFixed linear NFA) Makefile: added unit-moad-0002 through unit-moad-0011 targets, integration-all-moads, functional-all-moads. integration and functional targets now depend on all-MOADs variants.
174 lines
7.6 KiB
Java
174 lines
7.6 KiB
Java
package unit;
|
|
|
|
import support.Moad0004Algorithm;
|
|
import support.Moad0004Algorithm.Result;
|
|
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Unit tests for MOAD-0004: A Logged Secret.
|
|
*
|
|
* Proves from first principles:
|
|
* 1. Defective: Authorization and Cookie headers appear verbatim in the log line —
|
|
* bearer token and session cookie exposed in cleartext.
|
|
* 2. Defective: leak count equals the number of credential headers present.
|
|
* 3. Fixed: credential header values are replaced with [REDACTED] —
|
|
* log line contains header names (for debugging) but not values.
|
|
* 4. Fixed: non-credential headers (Host, Content-Type) pass through unchanged.
|
|
* 5. Both handle empty header maps without error.
|
|
*
|
|
* No build tool required. Compile and run:
|
|
*
|
|
* cd tests
|
|
* java -m jdk.compiler/com.sun.tools.javac.Main -cp . \
|
|
* support/Moad0004Algorithm.java unit/Moad0004UnitTest.java
|
|
* java -cp . unit.Moad0004UnitTest
|
|
*/
|
|
public class Moad0004UnitTest {
|
|
|
|
private static int passed = 0;
|
|
private static int failed = 0;
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println("=== Moad0004UnitTest (A Logged Secret) ===\n");
|
|
|
|
System.out.println("-- Correctness: both handle headers without throwing --");
|
|
testBothHandleEmpty();
|
|
|
|
System.out.println("\n-- Defect: credential headers appear in cleartext log --");
|
|
testDefectiveAuthorizationLeaks();
|
|
testDefectiveCookieLeaks();
|
|
testDefectiveCountsAllCredentialHeaders();
|
|
testDefectiveNonCredentialHeadersPresent();
|
|
|
|
System.out.println("\n-- Fix: credential headers redacted, non-credential headers intact --");
|
|
testFixedAuthorizationRedacted();
|
|
testFixedCookieRedacted();
|
|
testFixedNonCredentialHeadersPassThrough();
|
|
testFixedZeroLeakCount();
|
|
|
|
System.out.printf("\n%d passed, %d failed%n", passed, failed);
|
|
if (failed > 0) System.exit(1);
|
|
}
|
|
|
|
// ── Correctness ───────────────────────────────────────────────────────────
|
|
|
|
static void testBothHandleEmpty() {
|
|
Map<String, String> empty = Map.of();
|
|
Result def = Moad0004Algorithm.logDefective(empty);
|
|
Result fix = Moad0004Algorithm.logFixed(empty);
|
|
assertEqual("defective: empty headers, zero leaks", 0, def.credentialLeakCount);
|
|
assertEqual("fixed: empty headers, zero leaks", 0, fix.credentialLeakCount);
|
|
}
|
|
|
|
// ── Defect ────────────────────────────────────────────────────────────────
|
|
|
|
static void testDefectiveAuthorizationLeaks() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logDefective(headers);
|
|
|
|
// DEFECT: bearer token appears in the log line verbatim
|
|
assertContains("defective: Authorization value in log (bearer token exposed)",
|
|
result.logLine, "eyJhbGciOiJSUzI1NiJ9.secret.token");
|
|
}
|
|
|
|
static void testDefectiveCookieLeaks() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logDefective(headers);
|
|
|
|
// DEFECT: session cookie and CSRF token appear in the log line
|
|
assertContains("defective: Cookie value in log (session cookie exposed)",
|
|
result.logLine, "session=abc123def456");
|
|
}
|
|
|
|
static void testDefectiveCountsAllCredentialHeaders() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logDefective(headers);
|
|
|
|
// sampleHeaders() contains: Authorization, Cookie, X-Api-Key = 3 credential headers
|
|
assertEqual("defective: counts 3 credential header leaks", 3, result.credentialLeakCount);
|
|
}
|
|
|
|
static void testDefectiveNonCredentialHeadersPresent() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logDefective(headers);
|
|
|
|
// Non-credential headers should appear (correct behavior for logging)
|
|
assertContains("defective: Host header present in log", result.logLine, "api.example.com");
|
|
assertContains("defective: X-Request-Id present in log", result.logLine, "req-7f3a9c");
|
|
}
|
|
|
|
// ── Fix ───────────────────────────────────────────────────────────────────
|
|
|
|
static void testFixedAuthorizationRedacted() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logFixed(headers);
|
|
|
|
// FIX: bearer token must NOT appear in the log line
|
|
assertNotContains("fixed: bearer token NOT in log",
|
|
result.logLine, "eyJhbGciOiJSUzI1NiJ9.secret.token");
|
|
|
|
// The header name should still appear (useful for debugging)
|
|
assertContains("fixed: Authorization header name present (redacted value)",
|
|
result.logLine, "Authorization");
|
|
}
|
|
|
|
static void testFixedCookieRedacted() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logFixed(headers);
|
|
|
|
// FIX: session cookie must NOT appear
|
|
assertNotContains("fixed: session cookie NOT in log", result.logLine, "session=abc123def456");
|
|
|
|
// The header name should still appear
|
|
assertContains("fixed: Cookie header name present", result.logLine, "Cookie");
|
|
}
|
|
|
|
static void testFixedNonCredentialHeadersPassThrough() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logFixed(headers);
|
|
|
|
// Non-credential headers must pass through unchanged
|
|
assertContains("fixed: Host value passes through", result.logLine, "api.example.com");
|
|
assertContains("fixed: X-Request-Id passes through", result.logLine, "req-7f3a9c");
|
|
assertContains("fixed: Content-Type passes through", result.logLine, "application/json");
|
|
}
|
|
|
|
static void testFixedZeroLeakCount() {
|
|
Map<String, String> headers = Moad0004Algorithm.sampleHeaders();
|
|
Result result = Moad0004Algorithm.logFixed(headers);
|
|
assertEqual("fixed: zero credential leaks", 0, result.credentialLeakCount);
|
|
}
|
|
|
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
|
|
static void assertEqual(String label, int expected, int actual) {
|
|
if (expected == actual) {
|
|
System.out.printf(" PASS: %s%n", label);
|
|
passed++;
|
|
} else {
|
|
System.out.printf(" FAIL: %s — expected %d, got %d%n", label, expected, actual);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
static void assertContains(String label, String haystack, String needle) {
|
|
if (haystack.contains(needle)) {
|
|
System.out.printf(" PASS: %s%n", label);
|
|
passed++;
|
|
} else {
|
|
System.out.printf(" FAIL: %s — '%s' not found in: %s%n", label, needle, haystack);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
static void assertNotContains(String label, String haystack, String needle) {
|
|
if (!haystack.contains(needle)) {
|
|
System.out.printf(" PASS: %s%n", label);
|
|
passed++;
|
|
} else {
|
|
System.out.printf(" FAIL: %s — '%s' should NOT be in: %s%n", label, needle, haystack);
|
|
failed++;
|
|
}
|
|
}
|
|
}
|