Skip to content

Commit b9ad93a

Browse files
Merge pull request #273 from bernardladenthin/claude/friendly-feynman-as1vh1
Add SpotBugs check to CI and expand PATH_TRAVERSAL_IN suppression
2 parents 964086a + 0534b06 commit b9ad93a

2 files changed

Lines changed: 36 additions & 19 deletions

File tree

.github/workflows/publish.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ jobs:
8484
distribution: temurin
8585
- name: Spotless check (fail fast on format violations)
8686
run: mvn -B --no-transfer-progress spotless:check
87+
- name: SpotBugs check (fail fast on static-analysis findings)
88+
run: mvn -B --no-transfer-progress -DskipTests -Denforcer.skip=true compile spotbugs:check
8789
- name: Print internal package dependency graph (jdeps, informational)
8890
continue-on-error: true
8991
run: |

spotbugs-exclude.xml

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)