Java native deserialization of `compiled.bin`/`cache.bin` (object-stream RCE)
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 18/100
Direzione di ricerca
Start in k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java, where loadImpl calls readObject() on a raw ObjectInputStream with no ObjectInputFilter; the callers are DefinitionLoadingModule.java, KompileFrontEnd.java, DefinitionParsing.java and lsp/TextDocumentSyncHandler.java. Done would mean an allow-list filter guards loadImpl without breaking kompile and LSP cache loading, which needs maintainer agreement on the trust model first.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
ObjectInputStream.readObject() on definition-directory artifacts; the cls.cast guard is after the fact. Reachable from -kompiled resolution, KRUN_KOMPILED_DIR, LSP workspace auto-discovery of cache.bin, and CI caches/tarballs of definition directories. Highest-severity item in the audit.
4 finding(s) (2 HIGH, 1 MEDIUM, 1 LOW) — line-anchor verified at commit 4a46d1231473.
Findings
| Severity | ID | Location | Summary |
|---|---|---|---|
| HIGH | kfrontend-compile-001 |
k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:91 |
Unsafe Java deserialization in BinaryLoader (compiled.bin / cache.bin) |
| HIGH | kfrontend-compile-002 |
k-frontend/src/main/java/org/kframework/lsp/TextDocumentSyncHandler.java:73 |
LSP auto-discovers and deserializes attacker-controlled cache.bin from the opened workspace |
| MEDIUM | kfrontend-parser-001 |
k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:94 |
Java native deserialization of compiled.bin (untrusted object stream) |
| LOW | kfrontend-parser-002 |
k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:64 |
Java native deserialization of parser caches |
Details
kfrontend-compile-001 — Unsafe Java deserialization in BinaryLoader (`compiled.bin` / `cache.bin`) (k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:91)
Trigger (as reviewed): BinaryLoader.loadImpl creates a raw java.io.ObjectInputStream and calls readObject() with no ObjectInputFilter, no class allow-list and no resolveClass override. It is the single serialization helper for the toolchain and is reached from DefinitionLoadingModule.java:31 (loadOrDie(CompiledDefinition.class, resolveKompiled("compiled.bin"))), KompileFrontEnd.java:109 (write), DefinitionParsing.java:207 and TextDocumentSyncHandler.java:73 (parse cache). An attacker who places a crafted compiled.bin or cache.bin in a *-kompiled directory gets gadget execution when a victim runs kompile/kprove/krun/kast against that directory.
Impact (as reviewed): Arbitrary code execution in the K frontend JVM, i.e. full compromise of the user running kompile/kprove/krun or the language server. The object is cast to CompiledDefinition/Map only after readObject() returns, so any classpath gadget chain runs first. Root cause for both the kompile cache path and the LSP auto-load path.
Deep review: reachability=REACHABLE-FROM-UNTRUSTED; exploitability=EXPLOITABLE; red-team=RED-TEAM-SURVIVED.
Strongest counterargument found during red-teaming: No weaponizable gadget chain has been demonstrated for this exact classpath (commons-collections4 4.3 and Guava 32.1.3 defeat the classic chains), so the CRITICAL 'arbitrary code execution' claim rests on custom gadget development rather than a proven exploit; without a chain the confirmed impact is attacker-controlled object-graph allocation (DoS) plus class loading, and the LSP kompile path also requires the victim to run K tooling inside an attacker-supplied directory.
kfrontend-compile-002 — LSP auto-discovers and deserializes attacker-controlled `cache.bin` from the opened workspace (k-frontend/src/main/java/org/kframework/lsp/TextDocumentSyncHandler.java:73)
Trigger (as reviewed): findCacheFile() recursively walks the opened workspace, selects the shallowest file named cache.bin (Kompile.CACHE_FILE_NAME) and passes it to BinaryLoader.loadCache with no provenance or integrity validation. loadCaches() is re-invoked from KWorkspaceService.didChangeWatchedFiles (KWorkspaceService.java:29). Any repository that ships a cache.bin at its root or under *-kompiled/ is deserialized as soon as the K language server initializes.
Impact (as reviewed): Remote code execution on the developer workstation from merely opening a malicious K project in VS Code or another LSP client. This is the most likely exploitation vector for the deserialization primitive in kfrontend-compile-001 because the attack file arrives with the repository and needs no further user action.
Deep review: reachability=REACHABLE-FROM-UNTRUSTED; exploitability=EXPLOITABLE; red-team=RED-TEAM-SURVIVED.
Strongest counterargument found during red-teaming: The RCE impact is not established: the commons-collections4 4.3 unsafe-serialization guard blocks the classic transformer chain unless a system property that appears nowhere in the repo is set, JDK 17+ removes the standard JDK gadgets, and no alternative classpath gadget chain was demonstrated. The confirmed impact from this finding alone is deterministic DoS/crash plus the attacker-controlled Source path read, and the trigger is one diagnostic or definition request rather than plain initialization, with client behavior (workspaceFolders, auto-diagnostics, Workspace Trust) outside the audited checkout.
kfrontend-parser-001 — Java native deserialization of `compiled.bin` (untrusted object stream) (k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:94)
Trigger (as reviewed): loadOrDie (line 46) and loadCache (line 62) both funnel arbitrary files through loadImpl. DefinitionLoadingModule.koreDefinition loads compiled.bin from the resolved -kompiled directory, which is selected from --definition, KRUN_KOMPILED_DIR, or a directory scan. Any definition directory obtained from a tarball, build artifact, shared filesystem, or CI cache is attacker-influenced data, and ObjectInputStream.readObject() executes readObject/readResolve on every class in the stream before the cls.cast check runs.
Impact (as reviewed): Classic Java deserialization RCE: a crafted compiled.bin yields arbitrary code execution with the privileges of kompile/krun/kprove, or at minimum memory exhaustion via deeply nested object graphs. The cls.cast(obj) guard is after-the-fact and provides no protection.
Deep review: reachability=REACHABLE-FROM-UNTRUSTED; exploitability=EXPLOITABLE; red-team=RED-TEAM-SURVIVED.
Strongest counterargument found during red-teaming: The RCE half of the CRITICAL rating is unproven: commons-collections4 4.3 hardens its transformer chain, and no other confirmed ysoserial-style gadget was identified on the frontend classpath, so in practice the demonstrated impact may be availability-only (StackOverflowError/OutOfMemoryError) rather than code execution. Separately, the primary path requires a victim to load an attacker-controlled definition directory, which is a real but user-mediated trust boundary; however, the LSP workspace scan and the default cwd '*-kompiled' scan make that boundary easy to cross without an explicit flag.
kfrontend-parser-002 — Java native deserialization of parser caches (k-frontend/src/main/java/org/kframework/utils/BinaryLoader.java:64)
Trigger (as reviewed): loadCache is a second independent entry point into loadImpl. It is intentionally tolerant: any IOException/ClassNotFoundException is downgraded to a warning and null is returned, so a malformed or hostile cache file never stops the pipeline. Caches live under the kompiled/temp directory and are frequently persisted across CI runs.
Impact (as reviewed): Same deserialization RCE primitive as kfrontend-parser-001, reachable through cache files that are more likely to be treated as disposable and less carefully controlled. The error handling guarantees a partially-consumed hostile stream never aborts the load.
Deep review: reachability=REACHABLE-FROM-UNTRUSTED; exploitability=EXPLOITABLE; red-team=RED-TEAM-SURVIVED.
Strongest counterargument found during red-teaming: The finding's HIGH severity rests on RCE, but no usable gadget chain was demonstrated for this exact classpath (JDK 17, Guava 32.1.3, commons-collections4 4.3, Scala 2.13); and the LSP vector depends on an external IDE client sending workspaceFolders and auto-issuing diagnostics or a user invoking goto-definition, plus any host workspace-trust gating, none of which is verifiable in this checkout. The 'frequently persisted across CI runs' premise and the 'kompiled/temp' wording are also inaccurate for this repository.
Suggested fix
Add an ObjectInputFilter allow-list (or replace Java serialization with a safe format) in BinaryLoader.loadImpl, and document that a kompiled directory is executable-trusted input.
Related
Intra-repo sibling references for lines in this bundle: kfrontend-parser-001.
From a static audit of this repository at commit 4a46d1231473b599c699160132fd6e76a5c46406 (master). Every location above was verified against the source at that revision; no exploit code was run against this repository or its infrastructure.
- Lingua principale
- Python
- Stelle
- 605
- Fork
- 165
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di runtimeverification/k
-
Difficoltà 4/5 Più di una settimana Idoneità per principianti 15/100
runtimeverification/k#4973 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 15/100
runtimeverification/k#4972 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 22/100
runtimeverification/k#4971 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 15/100
runtimeverification/k#4970 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 15/100
runtimeverification/k#4969 ·
Tutte le issue di runtimeverification/k
Issue simili
-
[BUG]: Compliance rules never see Unity Catalog views as viewsForse già presa @wagnercsantos l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
databrickslabs/ontos#1348 ·
I maintainer di solito rispondono entro 3 giorni
-
`forum_pr_poster` action will always return `none` when checking for pre-existing feedback threads, even if a feedback thread already exists.Forse già presa @pgmzeta l’ha presa oggi. ApertaE-Verified P-Major
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
goonstation/goonstation#28259 ·
I maintainer di solito rispondono entro 2 giorni
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
woonstadrotterdam/monumenten#70 ·
I maintainer di solito rispondono entro 15 giorni
-
binding:python bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
The Browser tab fails with a Wayland error when Open Terminal runs from a Wayland desktop sessionAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
open-webui/open-terminal#210 ·