@@ -123,27 +123,42 @@ SPDX-License-Identifier: MIT
123123 </Match >
124124
125125 <!--
126- LlamaLoader is the native-library bootstrap. It resolves the path
127- to libjllama.{so,dylib,dll} from three operator-controlled inputs:
128-
129- 1. -Dnet.ladenthin.llama.lib.path=<dir> (line 94)
130- 2. java.library.path entries (line 119)
131- 3. java.io.tmpdir + hardcoded basename (lines 133, 171, 215)
132-
133- findsecbugs PATH_TRAVERSAL_IN flags every non-literal argument to
134- Paths.get, treating "user input" syntactically as "any non-literal
135- string". The threat-model reality is different: all three sources
136- are JVM properties set at process launch by whoever started the
137- process. An attacker who can set JVM properties has already won;
138- there is no untrusted end-user input reaching these paths.
139-
140- Canonicalize-and-restrict-to-root mitigation is not applicable
141- because the whole purpose of the .lib.path property is to let the
142- operator point at any directory containing the native library;
143- there is no meaningful "allowed root" to validate against.
126+ PATH_TRAVERSAL_IN (reviewed 2026-06-26): confirmed a false positive for
127+ this JNI library, so this suppression is permanent and no code fix is
128+ appropriate. Two operator-controlled path sites are flagged:
129+
130+ 1. LlamaLoader (native-library bootstrap) resolves
131+ libjllama.{so,dylib,dll} from three JVM-launch inputs:
132+ a. the net.ladenthin.llama.lib.path system property (a directory)
133+ b. java.library.path entries
134+ c. java.io.tmpdir plus a hard-coded basename
135+ 2. OfflineModelGuard.check() does Files.exists(Paths.get(model)),
136+ where model is ModelParameters.getModel() (the configured local
137+ model-file path), to fail fast when the offline flag is set and the
138+ local model is absent. This is a read-only existence check; the
139+ path is not opened or written here.
140+
141+ findsecbugs taints every non-literal Paths.get argument (System
142+ properties and CLI/builder config count as taint sources), but all of
143+ these inputs are the operator's own process configuration set at launch,
144+ not untrusted end-user input crossing a privilege boundary. An attacker
145+ who can set the model path, the lib.path property, or java.library.path
146+ already controls the JVM; there is no traversal boundary to cross.
147+
148+ Why no fix: the canonicalize-and-restrict-to-an-allowed-root remediation
149+ does not apply. Pointing at an arbitrary GGUF or library directory
150+ anywhere on disk is the entire purpose of these settings, so there is no
151+ meaningful allowed root, and a parent-directory-rejecting check would
152+ break the legitimate relative-path case. An embedder that exposes the
153+ model path to untrusted remote users must validate it before calling this
154+ library; that lies outside the library's API contract.
144155 -->
145156 <Match >
146- <Class name =" net.ladenthin.llama.loader.LlamaLoader" />
157+ <Or >
158+ <Class name =" net.ladenthin.llama.loader.LlamaLoader" />
159+ <Class name =" net.ladenthin.llama.loader.OfflineModelGuard" />
160+ <Class name =" net.ladenthin.llama.parameters.ModelParameters" />
161+ </Or >
147162 <Bug pattern =" PATH_TRAVERSAL_IN" />
148163 </Match >
149164
0 commit comments