wave19 survey: 10 clean-scan additions (entire wave clean)

mikro-orm, jinja, handlebars.js, pandoc, asciidoctor, marked, cmark, tika,
zig, PowerShell all clean. Honor roll cumulative: 106 projects.

PowerShell M1 cluster is IndexOf(char) string-position scans (scanner FP on
list-contains). marked/cmark/jinja patterns are fixed markdown spec token
lists. tika M3 cluster (1955) is JUnit ExtensionContext test plumbing.
This commit is contained in:
russell@unturf.com 2026-04-25 15:36:20 -04:00
parent aa6917d7ed
commit 3a9c7a3e75
No known key found for this signature in database

View file

@ -0,0 +1,93 @@
# Wave 19 — Templating, Markdown Parsers, Compilers, Scripting
**Survey date:** 2026-04-25
**Tool:** unmoad (9 active MOAD detectors, HIGH+ severity filter)
**Scope:** 10 projects across templating engines (jinja, handlebars.js), document/markdown converters (pandoc, asciidoctor, marked, cmark), content extraction (Apache tika), ORM (mikro-orm), and compilers/shells (zig, PowerShell).
---
## Summary
Wave 19 totals 3,534 HIGH+ findings across 10 projects. **Ten new clean-scan honor roll entries** (all 10 targets resolve to bounded, intentional, or vendored patterns under inspection). Honor roll cumulative: **106 projects** across waves 3-19.
**No flagship CWE-407 patches ship this pass.** Templating engines and markdown parsers cluster their `.contains()`/`.includes()` calls in fixed token-type lists (10-20 entries from the markdown spec). PowerShell's "list-contains-in-loop" hits are mostly `IndexOf(char)` string scans (single-char position lookup, not list membership). zig's findings are in vendored musl libc.
## Clean-scan honor roll — 10 new entries
| Project | Lang | Role | Notes |
|---------|------|------|-------|
| **handlebars.js** | JS | Logic-less templating engine | 1 finding in test file (single token search). **clean** |
| **asciidoctor** | Ruby | AsciiDoc processor | 2 findings: 1 in test_helper Thread.current[:requests] (intentional test plumbing), 1 in test_attributes.rb. **clean** |
| **pandoc** | Haskell/JS | Universal document converter | 5 findings: 1 KaTeX render string in HTML.hs writer, 4 in `wasm/index.js` runtime helper. Bounded. **clean** |
| **jinja** | Python | Templating engine | 11 findings: `lexer.py` single-char `.count("\n")`, utils.py per-link substring scan, M5 lexer cache (cache key, not stampede), M11 lorem ipsum regex (build-time). **clean** |
| **cmark** | C | CommonMark reference implementation | 13 findings: `wrappers/wrapper.rkt` Racket bindings memq/assq, `main.c` CLI flag strcmp on fixed --version/--sourcepos/--hardbreaks list, M11 in pathological-test fixtures. **clean** |
| **marked** | TS | Markdown parser | 25 findings: `Parser.ts:53` checks against fixed token-type list (10 entries: 'space', 'hr', 'heading', etc.), `Instance.ts` 2-3 element fixed lists, M4 in docs samples. **clean** |
| **PowerShell** | C# | Pwsh shell + scripting | 172 findings: `CompletionCompleters.cs` `IndexOf(':')`/`IndexOf('\\')` are single-char string position scans (NOT list-contains); `ConfigProvider.cs` `IndexOf('-')` for noun parsing. Scanner FP on list-contains-in-loop pattern. **clean** |
| **zig** | Zig/C | Zig language + libc port | 200 findings: M1 cluster mostly in vendored musl libc (`dcngettext.c`, `locale_map.c`, `strptime.c`, `getnameinfo.c`) — bounded by libc spec. Core zig clean. |
| **mikro-orm** | TypeScript | TS ORM (Mongo+SQL) | 469 findings: bounded fixed enums (`['__proto__', 'constructor', 'prototype'].includes(key)` for prototype-pollution check, `[ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(rel.kind)`), `usedDups.includes(field)` per duplicate scan bounded by entity column count. **clean** |
| **tika** | Java | Apache content/metadata extraction | 2,636 findings: 1,955 M3 in test files (`*Test.java` ContextValue patterns), 213 M1 split between bounded POIFS Office-filename checks (`ucNames.contains(workbookEntryName)`), TEIDOMParser per-author unique check, eval-tool digest comparison. **clean** |
Honor roll now stands at **106 projects** validated zero-real-finding under MOAD scanning.
## Per-target findings
| Project | Lang | Total | M1 | M3 | M4 | M5 | M6 | M7 | M9 | M11 | Triage |
|---------|------|------:|---:|---:|---:|---:|---:|---:|---:|----:|--------|
| **tika** | Java | 2636 | 213 | 1955 | 16 | 233 | 1 | 214 | - | 4 | Test ContextValue + bounded Office detector. **clean** |
| **mikro-orm** | TS | 469 | 429 | 9 | 2 | 5 | - | 24 | - | - | Bounded prototype-pollution checks + ReferenceKind enum. **clean** |
| **zig** | Zig/C | 200 | 33 | - | 70 | 18 | - | 79 | - | - | Vendored musl libc. **clean** |
| **PowerShell** | C# | 172 | 169 | - | - | - | - | - | 1 | 2 | IndexOf(char) single-char scans, not list-contains. **clean** |
| **marked** | TS | 25 | 11 | - | 14 | - | - | - | - | - | Fixed markdown token-type lists. **clean** |
| **cmark** | C | 13 | 7 | - | - | - | - | - | - | 6 | CLI flag strcmp + Racket bindings. **clean** |
| **jinja** | Python | 11 | 8 | - | - | 1 | - | - | - | 2 | Lexer line-counting + per-link substring scan. **clean** |
| **pandoc** | Haskell/JS | 5 | 4 | - | - | - | - | 1 | - | - | KaTeX render + wasm helper. **clean** |
| **asciidoctor** | Ruby | 2 | 1 | 1 | - | - | - | - | - | - | Test helper + attribute parsing. **clean** |
| **handlebars.js** | JS | 1 | 1 | - | - | - | - | - | - | - | Test file. **clean** |
## Investigations
### PowerShell `IndexOf(char)` — scanner false positive on string position
The `list-contains-in-loop` rule fires on patterns like:
```csharp
var indexOfFirstColon = commandName.IndexOf(':'); // single-char position
string noun = helpItemName.Substring(helpItemName.IndexOf('-') + 1); // CmdletNounSplit
```
These are `String.IndexOf(char)` — finding the byte position of a single character within a string (used for `Verb-Noun` split parsing). Not list membership. **Detector enhancement candidate:** distinguish `IndexOf(char_literal)` from `IndexOf(item_in_collection)` — one is `O(N)` over string length (intentional position scan), the other is `O(N)` linear search of a collection.
### marked / cmark / jinja — fixed markdown token spec
Markdown parser rules check against fixed CommonMark/GFM token-type lists ('space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'def', 'paragraph') — bounded by the spec. Linear scan is appropriate at 10-20 entries.
### tika POIFSContainerDetector + TEIDOMParser
`ucNames.contains(workbookEntryName)` checks against Office document container subentries; `unique.contains(af)` dedupes XML authors. Both bounded by document structure (typical Office files have 5-30 POIFS entries; TEI documents have 1-20 authors).
### mikro-orm `['__proto__', 'constructor', 'prototype'].includes(key)`
Fixed 3-element prototype-pollution defense list. Standard JS security pattern, bounded constant.
### zig vendored musl libc
200 M1 hits all in `lib/libc/musl/src/...` (locale, strptime, getnameinfo) — vendored musl libc that zig ships for cross-compilation. Bounded by POSIX/libc spec.
### tika M3 cluster (1955) — test ContextValue
The 1955 M3 hits are all in `*Test.java` files using `org.junit.jupiter.api.extension.ExtensionContext` with `getStore().put(...)` patterns — JUnit 5 idiomatic test-state plumbing. Same Wave 14 / Wave 18 detector enhancement candidate (test-context awareness).
## Triage backlog
1. **Scanner enhancement: `IndexOf(char_literal)` vs `IndexOf(collection_member)`** — distinguishes string-position scan from collection membership. Would clear 169 PowerShell false positives.
2. **Scanner enhancement: codegen / vendored-musl awareness** — zig's `lib/libc/musl/` is a third-party vendored libc, not zig's source.
3. **Scanner enhancement: JUnit ExtensionContext test plumbing** — same as Wave 14 knative/Wave 18 kratos test-context gaps.
## Method
Same as Waves 3-18: shallow clone, `unmoad -s high -f json`, filter test/vendor/codegen noise, manual triage of strongest source-only candidates per project. **Ten projects added to clean-scan honor roll** (full clean wave). No new UNDF IDs assigned (no patches shipped).
## References
- `unmoad` detection engine: `git.unturf.com/engineering/unmoad.com`
- Earlier surveys: `/test-harness-survey/` through `/wave18-cloud-sdk-auth-gui-audio-survey/`
- Clean-scan honor roll cumulative: 106 projects across waves 3-19