Add Fortify scanner THREAT_MODEL.md to dot-net-framework-url-escaping repo Bug: b/548453908 Change-Id: I95af7b986241d794c09404030d5fd639ae2ce259 Reviewed-on: https://gnocchi-internal-review.git.corp.google.com/c/third_party/dot-net-framework-uri-escaping/+/314964 Reviewed-by: Trevor Ryland <tryland@google.com>
diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md new file mode 100644 index 0000000..81e987b --- /dev/null +++ b/THREAT_MODEL.md
@@ -0,0 +1,134 @@ +# Security Threat Model + +## Asset Definition & Scope + +This threat model covers the **`Appsheet.DotNetFrameworkUriEscaping`** +repository +(`sso://gnocchi-internal/third_party/dot-net-framework-uri-escaping`), a C# +shared library targeting `.NET Standard 2.0`. The repository contains a custom +fork of Microsoft .NET Framework 4.6.2 Reference Source (`NetFrameworkUri.cs`) +configured to execute in legacy V2 quirks mode (RFC 2396). It provides +`NetFrameworkUri.EscapeDataString()` to escape query parameters identically to +legacy .NET Framework (notably preserving unreserved characters such as `(` and +`)`), which is utilized by AppSheet to verify cryptographic signatures on legacy +image URLs generated prior to AppSheet's migration to .NET Core. + +## Prioritization Signals + +- **1P OSS:** No +- **1P Proprietary Shipped Software:** No (Server-side library powering + AppSheet cloud services) +- **High-Risk Code Surface:** Yes. Utilizes C# `unsafe` pointer operations, + stack allocations (`stackalloc`), raw buffer copying (`Buffer.BlockCopy`), + and custom Unicode surrogate/UTF-8 byte processing on untrusted external URL + strings. +- **Perimeter Exposure:** Yes (Exposed via AppSheet public-facing internet + service and customer endpoints). +- **Data Sensitivity:** Medium/High (Processes customer image URLs, query + parameters, HMAC/signature tokens, and customer data identifiers). +- **Untrusted Input Handling:** Yes (Consumes raw, untrusted URI strings and + query parameters from external HTTP requests). +- **Business Value:** Critical for preserving backwards compatibility and + security of AppSheet's legacy image URL signature verification pipeline, + preventing unauthorized access to customer image assets. + +## Scanning Harness Prompts + +- Focus on pointer arithmetic, buffer boundary calculations, and array + allocations in `NetFrameworkUri.EscapeString` and + `NetFrameworkUri.EnsureDestinationSize`. Check for potential off-by-one or + integer overflow vulnerabilities when indexing characters, calculating + surrogate pair offsets (`pStr[i + count - 1]`), or converting UTF-8 bytes + (`Encoding.UTF8.GetBytes`). +- Inspect unsafe stack allocation `stackalloc byte[160]` + (`c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar`) and verify + whether input strings with surrogate pairs or long sequences of non-ASCII + characters can cause buffer overruns in `Encoding.UTF8.GetBytes(pStr + i, + count, bytes, 160)`. +- Analyze surrogate pair handling (`0xD800` to `0xDBFF`) for malformed Unicode + inputs (e.g., truncated high surrogates, unpaired surrogates, non-shortest + form UTF-8) to ensure `UriFormatException` is reliably thrown without memory + corruption or infinite loops (`for (; count < maxSize && pStr[i + count] > + '\x7f'; ++count)`). +- Evaluate differential URI escaping/unescaping behavior between RFC 2396 (V2 + quirks mode) and modern RFC 3986 / .NET Core parsers to ensure that + canonicalization differences cannot be exploited for signature validation + bypass or request spoofing in downstream AppSheet components. + +## Entry Points and Untrusted Inputs + +| Entry Point | Type | Trusted? | Validation | +| ---------------------------------------- | -------- | ---------- | -------------------- | +| `NetFrameworkUri.EscapeDataString(string | Public | No | Validates null, | +: stringToEscape)` : C# : (Untrusted : empty string, : +: : Static : query : surrogate pairs, : +: : Method : parameters : UTF-8 encodability, : +: : : and URLs : and enforces : +: : : from : `c_MaxUriBufferSize` : +: : : external : (65,520 chars) : +: : : users) : : +| `NetFrameworkUri.EscapeString(...)` | Internal | No (Raw | Enforces `end - | +: : Unsafe : string and : start < : +: : Static : substring : c_MaxUriBufferSize`; : +: : Method : bounds) : validates high/low : +: : : : surrogates and UTF-8 : +: : : : byte conversion : + +## Trust Boundaries and Auth Assumptions + +- **Authentication**: None within this library (assumed to be invoked by + AppSheet backend during authentication and signature verification + pipelines). +- **Authorization**: None within this library. +- **Implicit trust**: The library assumes callers pass .NET string objects + within valid memory; however, the string content itself is treated as + completely untrusted. +- **Boundary crossings**: External user/client request → AppSheet HTTP edge / + API handler → `NetFrameworkUri.EscapeDataString` → Signature validator / + image storage fetcher. + +## Sensitive Data Paths + +| Data Type | Source | Destination | Protection | +| ---------- | -------- | ---------------------------------- | -------------------- | +| Customer | External | `NetFrameworkUri.EscapeDataString` | In-memory | +: image URLs : client : -> Signature verification hash / : processing; input : +: & query : requests : HMAC engine : size limited by : +: parameters : : : `c_MaxUriBufferSize` : +| Image URL | External | Signature verification comparison | Processed in string | +: signatures : client : logic : / character buffers : +: & HMAC : requests : : : +: tokens : : : : + +## Privileged Actions + +| Action | Location | Guard | +| -------------------- | --------------------------------------- | ------------------------------- | +| Unsafe stack | `NetFrameworkUri.EscapeString` | Fixed allocation size | +: allocation : : (`c_MaxUnicodeCharsReallocate * : +: (`stackalloc`) : : c_MaxUTF_8BytesPerUnicodeChar` : +: : : = 160 bytes); bounded by : +: : : `maxSize` calculation : +| Direct pointer | `NetFrameworkUri.EscapeString`, | Fixed pointer pins (`fixed | +: dereferencing & : `NetFrameworkUri.EnsureDestinationSize` : (char* pStr = input)`); bounded : +: traversal (`char*`, : : loop index and `prevInputPos` : +: `byte*`) : : tracking : +| Raw buffer copy | `NetFrameworkUri.EnsureDestinationSize` | Reallocation logic with | +: (`Buffer.BlockCopy`) : : `destPos << 1` byte count : + +## Priority Review Areas + +1. **Unsafe Pointer Manipulation and Buffer Resizing:** Verify bounds checks in + `NetFrameworkUri.EscapeString` and `NetFrameworkUri.EnsureDestinationSize` + under edge cases (e.g. repeated resizing, maximum buffer size, mixed ASCII + and non-ASCII sequences). +2. **Malformed Unicode & Surrogate Pair Handling:** Review behavior when + processing lone high surrogates, lone low surrogates, or invalid UTF-8 byte + sequences at string boundaries (`count == 1 || count == end - i`). +3. **V2 Quirks Differential & RFC 2396 Compliance:** Review the character sets + in `RFC2396UnreservedMarks` (`-_.~*'()!`) vs `RFC3986UnreservedMarks` + (`-_.~`) and ensure signature calculations in AppSheet cannot be + desynchronized between .NET Framework and .NET Core. +4. **Denial of Service (DoS) via Exception Flooding or Buffer Limits:** Check + if large or invalid URI payloads (approaching `c_MaxUriBufferSize = 0xFFF0`) + can cause high CPU usage or excessive garbage collection.