Java native deserialization of `compiled.bin`/`cache.bin` (object-stream RCE)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 18/100
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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.
- Lenguaje dominante
- Python
- Estrellas
- 605
- Forks
- 165
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de runtimeverification/k
-
Dificultad 4/5 Más de una semana Aptitud para principiantes 15/100
runtimeverification/k#4973 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
runtimeverification/k#4972 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 22/100
runtimeverification/k#4971 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
runtimeverification/k#4970 ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
runtimeverification/k#4969 ·
Todos los issues de runtimeverification/k
Issues similares
-
[BUG]: Compliance rules never see Unity Catalog views as viewsPosiblemente ocupada @wagnercsantos la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
databrickslabs/ontos#1348 ·
Los mantenedores suelen responder en 3 días
-
`forum_pr_poster` action will always return `none` when checking for pre-existing feedback threads, even if a feedback thread already exists.Posiblemente ocupada @pgmzeta la tomó hoy. AbiertoE-Verified P-Major
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
goonstation/goonstation#28259 ·
Los mantenedores suelen responder en 2 días
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
woonstadrotterdam/monumenten#70 ·
Los mantenedores suelen responder en 15 días
-
binding:python bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
The Browser tab fails with a Wayland error when Open Terminal runs from a Wayland desktop sessionAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
open-webui/open-terminal#210 ·