fuse: all 5 MOADs CLEAN

linapple: 1 CWE-312 defect (MOAD-0004), MOAD 0001/0002/0003/0005 CLEAN
This commit is contained in:
russell@unturf.com 2026-03-31 19:15:33 -04:00
parent 4b180cd7ac
commit 20b8a57f89
4 changed files with 186 additions and 0 deletions

View file

@ -0,0 +1,33 @@
# fuse: all 5 MOADs CLEAN
ZX Spectrum emulator, C codebase. Shallow clone scanned 2026-03-31.
## MOAD-0001 CWE-407
CLEAN. Hot paths use GLib GHashTable for all key lookups (O(1)). Port I/O
dispatch uses g_slist_foreach with O(P) per port read/write where P is
registered ports (bounded, typically <20). Breakpoint check iterates GSList
of breakpoints O(B) per instruction only when debugger is ACTIVE mode.
Disk sector search is O(S) bounded by sectors-per-track (9-18).
No list.contains() inside a loop on unbounded data found.
## MOAD-0002 Intertangle
CLEAN. Global GHashTable for peripherals and GSList for ports are expected
single-instance emulator design. No evidence of independent subsystems
inappropriately coupled through shared mutable state.
## MOAD-0003 Leaked Context
CLEAN. No ThreadLocal, pthread_key, or thread-scoped identity carriers found.
Fuse is single-threaded.
## MOAD-0004 CWE-312
CLEAN. No credentials, API keys, tokens, or passwords found in logging paths.
Spectranet peripheral has no credential-bearing network calls in our codebase.
## MOAD-0005 Thundering Herd
CLEAN. No unsynchronized cache get+null+compute+put patterns. Single-threaded
architecture eliminates this class of defect.

View file

@ -0,0 +1,44 @@
# linapple-0001: FTP user:password logged verbatim at startup (CWE-312 / MOAD-0004)
**Severity:** HIGH
**File:** `src/Applewin.cpp`
**Function:** `LoadConfiguration()`
**Line:** 871
## Description
`LoadConfiguration()` reads `g_sFTPUserPass` (format: `user:password`) from the
registry or config file, then immediately prints the entire credential string
verbatim to stdout via `printf`:
```c
// Print some debug strings
printf("Ready login = %s\n", g_sFTPUserPass);
```
This debug line runs at every startup. Any user who has configured FTP credentials
for disk image access (non-anonymous logins) has their password written to
the terminal, any log file, shell history replay, or screen recording session.
## Fix
Extract only our username portion (up to the first `:`), mask our password with `***`:
```c
{
/* CWE-312: g_sFTPUserPass is "user:password" — never log verbatim. */
const char *colon = strchr(g_sFTPUserPass, ':');
int user_len = colon ? (int)(colon - g_sFTPUserPass) : (int)strlen(g_sFTPUserPass);
printf("Ready login = %.*s:***\n", user_len, g_sFTPUserPass);
}
```
## MOADs 0001-0005
| MOAD | Status |
|------|--------|
| 0001 CWE-407 | CLEAN — no hot-path O(N^2) linear scan found |
| 0002 Intertangle | CLEAN — global state coupling is expected single-instance emulator design |
| 0003 Leaked Context | CLEAN — no ThreadLocal/thread-scoped identity carriers |
| 0004 CWE-312 | **DEFECT** — FTP password logged verbatim at startup |
| 0005 Thundering Herd | CLEAN — no unsynchronized cache patterns found |

View file

@ -0,0 +1,14 @@
# UNDF: UNDF-2026-XXXXXXXXX
--- a/src/Applewin.cpp
+++ b/src/Applewin.cpp
@@ -868,7 +868,12 @@ static void LoadConfiguration(bool registry)
}
// Print some debug strings
- printf("Ready login = %s\n", g_sFTPUserPass);
+ {
+ /* CWE-312: g_sFTPUserPass is "user:password" — never log verbatim. */
+ const char *colon = strchr(g_sFTPUserPass, ':');
+ int user_len = colon ? (int)(colon - g_sFTPUserPass) : (int)strlen(g_sFTPUserPass);
+ printf("Ready login = %.*s:***\n", user_len, g_sFTPUserPass);
+ }
}

View file

@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""
Unit test for linapple-0001: FTP user:password credential logged verbatim (CWE-312 / MOAD-0004)
LoadConfiguration() in src/Applewin.cpp reads g_sFTPUserPass (format: "user:password")
from config and immediately prints it verbatim via printf to stdout at every startup.
Fix: extract only the username portion; mask the password with ***.
"""
import re
import unittest
# Original defective line
ORIGINAL_LINE = 'printf("Ready login = %s\\n", g_sFTPUserPass);'
# Patched lines (the masked version)
PATCHED_FMT = 'printf("Ready login = %.*s:***\\n", user_len, g_sFTPUserPass);'
def mask_userpass(userpass: str) -> str:
"""Simulate the patched masking logic in C."""
colon = userpass.find(':')
if colon >= 0:
return userpass[:colon] + ':***'
return userpass + ':***'
def original_leak(userpass: str) -> str:
"""Simulate the original defective print."""
return userpass
class TestLinapple0001(unittest.TestCase):
"""Verify that FTP password is not logged in plaintext."""
def test_original_exposes_full_credential(self):
"""Original printf prints user:password verbatim."""
cred = "alice:s3cr3tpass"
output = original_leak(cred)
self.assertIn("s3cr3tpass", output,
"Defect: password visible in original output")
# Confirm the source line uses %s with full g_sFTPUserPass
self.assertIn("%s", ORIGINAL_LINE)
self.assertIn("g_sFTPUserPass", ORIGINAL_LINE)
def test_patch_masks_password(self):
"""Patched version must show only username, not password."""
cred = "alice:s3cr3tpass"
output = mask_userpass(cred)
self.assertEqual(output, "alice:***",
"Fix: output should be user:***")
self.assertNotIn("s3cr3tpass", output,
"Fix: password must not appear in output")
def test_patch_preserves_username(self):
"""Username must remain visible for diagnostics."""
cred = "bob:hunter2"
output = mask_userpass(cred)
self.assertTrue(output.startswith("bob:"),
"Fix: username should be preserved")
def test_patch_handles_no_colon(self):
"""If no colon, treat entire string as username."""
cred = "anonymous"
output = mask_userpass(cred)
self.assertIn("anonymous", output)
self.assertIn("***", output)
def test_patch_handles_anonymous_default(self):
"""Default anonymous:mymail@hotmail.com must have email masked."""
cred = "anonymous:mymail@hotmail.com"
output = mask_userpass(cred)
self.assertNotIn("mymail@hotmail.com", output,
"Fix: email used as password must not appear in output")
self.assertEqual(output, "anonymous:***")
def test_patched_fmt_string_uses_precision(self):
"""Patched printf uses %%.*s to limit output to username length."""
self.assertIn("%.*s", PATCHED_FMT,
"Patched line should use %%.*s for length-limited username")
self.assertIn(":***", PATCHED_FMT,
"Patched line should contain literal :*** mask")
def test_original_format_string_leaks(self):
"""Original format string has single %%s — prints entire user:password."""
fmt_match = re.search(r'"Ready login = ([^"]*)"', ORIGINAL_LINE)
self.assertIsNotNone(fmt_match)
fmt_str = fmt_match.group(1)
self.assertEqual(fmt_str.count("%s"), 1,
"Original has one %%s which prints entire credential string")
if __name__ == "__main__":
unittest.main()