GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Search

Find a vulnerability

Search criteria

    3 vulnerabilities found for Chronicle Wire by unknown

    GCVE-1988-2026-0074

    Vulnerability from gna-1988 – Published: 2026-09-07 13:20 – Updated: 2026-09-07 13:20
    VLAI
    Title
    Chronicle Wire v2026.8 Insecure Reflection Allows Unvalidated Method Invocation
    Summary
    Chronicle Wire's MethodReader implements message dispatch by dynamically mapping serialized wire events to Java handler methods. During initialization, the framework discovers public methods exposed by the registered handler interfaces and registers those methods as callable wire events. When a message is processed, the event name supplied within the wire data determines which registered handler method is selected. Method arguments are then deserialized from the corresponding message content, and Chronicle Wire invokes the selected method using Java Reflection. As a result, when untrusted wire data reaches a MethodReader, externally controlled input can determine both the handler method selected for invocation and the arguments supplied to that method. The dispatch surface is derived automatically from the handler's public interface rather than from an explicit list of individually registered operations. Public methods added to a registered handler interface can therefore become dispatchable wire events without separate method-level registration. This behavior becomes security-sensitive when a handler interface contains privileged or security-sensitive operations and its MethodReader processes data from an untrusted source. In such deployments, methods intended for file access, network operations, key management, maintenance, administrative functionality, or other privileged actions may become reachable through externally controlled event names. Vulnerability Details VanillaMethodReader constructs its dispatch surface from the handlers supplied by the application: addParsersForComponents(handler); During initialization, Chronicle Wire enumerates the public methods associated with the handler: for (Method method : handlerClass.getMethods()) { addParseletForMethod(method); } Eligible methods are subsequently registered for wire-event dispatch. The method name and parameter types are used to construct the corresponding wire key: MethodWireKey key = new MethodWireKey( method.getName(), parameterTypes); This means the set of methods callable through the wire protocol is derived from the public methods exposed by the registered handler interface. When incoming wire data is processed, the supplied event name is matched against the registered method dispatch table. The corresponding argument values are then deserialized according to the selected method's declared parameter types: arguments[i] = valueIn.object(parameterTypes[i]); After argument deserialization, the selected Java method is invoked reflectively: method.invoke(target, arguments); Consequently, externally controlled wire data participates directly in two security-sensitive decisions: selecting which registered handler method is executed and supplying the arguments passed to that method. The dispatch mechanism itself does not introduce a method-level authorization decision between event selection and invocation. The effective security boundary is therefore determined by which interfaces are registered with MethodReader, which public methods those interfaces expose, and whether the application permits untrusted data to reach the reader. Root Cause The security issue arises from automatically deriving the externally dispatchable method surface from public methods exposed by registered handler interfaces. Chronicle Wire: - Discovers public methods associated with registered handlers. - Registers eligible methods as wire-event handlers. - Resolves incoming event names to those methods. - Deserializes method parameters from the corresponding wire input. - Invokes the selected methods using Java Reflection. The dispatch model does not require each callable operation to be independently exported or registered at the method level. Consequently, the security boundary of a MethodReader can expand when additional public methods are introduced into an interface already used for wire dispatch. This creates a risk in applications where the registered handler interface contains operations that should not be reachable by the party controlling the wire input. The issue is particularly significant when interfaces evolve over time. Adding a new public operation to an existing MethodReader-facing interface can simultaneously add that operation to the wire dispatch surface without a separate dispatch registration step. Impact When untrusted input reaches a MethodReader, an attacker can select among the public operations exposed through the registered handler interface and provide serialized arguments for the selected operation. The resulting security impact depends on the functionality implemented by those handlers. Security-sensitive methods may include: - file access and file modification; - outbound network communication; - administrative operations; - key rotation or key-management operations; - configuration changes; - maintenance functionality; - state-changing business operations; and - other privileged application functionality. If such operations are exposed through a registered handler interface, externally controlled event names can cause those methods to be invoked with externally supplied arguments. The attack surface can also change as the application evolves. A public method added to an interface already participating in MethodReader dispatch may become a new wire operation without requiring separate registration of that individual method. Methods accepting broad or polymorphic argument types introduce an additional concern. Arguments are processed through Chronicle Wire's object deserialization mechanisms: arguments[i] = valueIn.object(parameterTypes[i]); Where the declared parameter type permits serialized type information to influence runtime object selection, externally controlled input may affect both the *method selected for invocation* and the *runtime object instantiated as its argument*. The resulting vulnerability therefore combines an externally controlled method-dispatch surface with attacker-controlled argument deserialization. The ultimate impact depends on the operations exposed by the registered handler and the trust boundary through which wire messages are received. Proof of Concept The proof of concept demonstrates that Chronicle Wire's MethodReader allows serialized event names to select public methods exposed by a registered handler and supplies those methods with arguments deserialized from the corresponding wire message. The tests exercise several handler operations to demonstrate method selection, privileged-operation reachability, automatic expansion of the dispatch surface, and typed argument deserialization. Administrative Method Invocation The registered handler exposes an administrative demonstration method named deleteAll. The following wire event was supplied: deleteAll: pwned-method-invocation Observed output: MethodReader invoked event-selected method: deleteAll:pwned-method-invocation This confirms that the event name supplied in the wire message selected the corresponding public handler method and that the attacker-controlled argument was delivered to that method. The demonstration method does not perform destructive deletion. Its purpose is to establish that an operation exposed by the registered handler can be selected directly through the incoming event name. File-Reading Method Invocation The handler additionally exposes a demonstration method that reads a caller-specified system file. The supplied event was: readSystemFile: /etc/hosts Observed invocation: MethodReader invoked file-reading method: readSystemFile:/etc/hosts The handler successfully accessed the supplied file and recorded: MethodReader file-read evidence: /etc/hosts:bytes=279:first-line=## The test therefore demonstrates more than method-name resolution. The externally supplied event selected a file-access operation and the externally supplied argument controlled the path processed by that operation. Automatic Exposure of Newly Added Handler Methods A new public method was added to the registered handler interface: void pingLocalhost(int port); No individual MethodReader registration was added for pingLocalhost. The following wire event was then supplied: pingLocalhost: 61866 Observed output: MethodReader invoked loopback ping method: pingLocalhost:61866 The test additionally recorded the resulting loopback interaction: MethodReader loopback ping evidence: pingLocalhost:127.0.0.1:61866 This confirms that adding the method to the registered handler interface was sufficient for the operation to become part of the MethodReader dispatch surface. The test is significant because it demonstrates that the callable surface can expand as the handler interface evolves. A newly introduced public handler operation does not require separate method-level registration before it can be selected by a corresponding wire event. Process-Execution Demonstration The automatic dispatch behavior was further tested with a deliberately introduced handler method containing a process-execution operation: void runtimeExecEcho(String command); The following event was supplied: runtimeExecEcho: pwned-runtime-exec Observed invocation: MethodReader invoked Runtime.exec method: runtimeExecEcho:pwned-runtime-exec The test recorded successful process execution: MethodReader Runtime.exec evidence: command=/bin/echo pwned-runtime-exec, exit=0 Process output: pwned-runtime-exec This test does not establish that Chronicle Wire itself contains a built-in command-execution method or universal RCE gadget. The runtimeExecEcho method was intentionally introduced as a controlled demonstration of the security consequence when a privileged operation exists on a registered handler interface. The result confirms the underlying dispatch property: once the public method was present on the handler interface, the corresponding wire event could select and invoke it without separate method-level registration. Typed Object Argument Deserialization The PoC additionally demonstrates that MethodReader dispatch can interact with Chronicle Wire's typed object deserialization when a handler accepts a sufficiently broad parameter type. The supplied event contained a tagged object: acceptObject: !net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe { marker: proof } Observed output: MethodReader typed argument instantiated class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe MethodReader typed argument constructor calls: 1 MethodReader typed argument readMarshallable calls: 1 This confirms that MethodReader did not simply pass a textual representation of the supplied argument to the handler. The argument entered Chronicle Wire's object deserialization path, the class identified by the serialized type information was instantiated, its constructor executed, and its readMarshallable() callback was invoked. For handler methods accepting broad or polymorphic parameter types, externally controlled wire input may therefore influence both the handler operation selected for invocation and the runtime object created as its argument. PoC Results The runtime evidence confirms the following MethodReader behaviors: [CONFIRMED] Wire event selected deleteAll handler method [CONFIRMED] Attacker-controlled argument delivered to selected method [CONFIRMED] Wire event selected readSystemFile handler method [CONFIRMED] Supplied /etc/hosts path processed by handler [CONFIRMED] File contents successfully read [CONFIRMED] Newly added pingLocalhost method became dispatchable [CONFIRMED] No separate method-level registration was required [CONFIRMED] Loopback network interaction occurred [CONFIRMED] Newly added runtimeExecEcho method became dispatchable [CONFIRMED] Demonstration process executed successfully [CONFIRMED] /bin/echo exited with status 0
    Severity
    No CVSS data available.
    Impacted products
    Vendor Product Version
    unknown Chronicle Wire Affected: unknown
    Create a notification for this product.
    Credits

    {
      "containers": {
        "cna": {
          "affected": [
            {
              "product": "Chronicle Wire",
              "vendor": "unknown",
              "versions": [
                {
                  "status": "affected",
                  "version": "unknown"
                }
              ]
            }
          ],
          "credits": [
            {
              "lang": "en",
              "type": "finder",
              "value": "Ron E"
            }
          ],
          "descriptions": [
            {
              "lang": "en",
              "value": "Chronicle Wire\u0027s MethodReader implements message dispatch by dynamically\nmapping serialized wire events to Java handler methods. During\ninitialization, the framework discovers public methods exposed by the\nregistered handler interfaces and registers those methods as callable wire\nevents.\n\nWhen a message is processed, the event name supplied within the wire data\ndetermines which registered handler method is selected. Method arguments\nare then deserialized from the corresponding message content, and Chronicle\nWire invokes the selected method using Java Reflection.\n\nAs a result, when untrusted wire data reaches a MethodReader, externally\ncontrolled input can determine both the handler method selected for\ninvocation and the arguments supplied to that method.\n\nThe dispatch surface is derived automatically from the handler\u0027s public\ninterface rather than from an explicit list of individually registered\noperations. Public methods added to a registered handler interface can\ntherefore become dispatchable wire events without separate method-level\nregistration.\n\nThis behavior becomes security-sensitive when a handler interface contains\nprivileged or security-sensitive operations and its MethodReader processes\ndata from an untrusted source. In such deployments, methods intended for\nfile access, network operations, key management, maintenance,\nadministrative functionality, or other privileged actions may become\nreachable through externally controlled event names.\nVulnerability Details\n\nVanillaMethodReader constructs its dispatch surface from the handlers\nsupplied by the application:\n\naddParsersForComponents(handler);\n\nDuring initialization, Chronicle Wire enumerates the public methods\nassociated with the handler:\n\nfor (Method method : handlerClass.getMethods()) {\n    addParseletForMethod(method);\n}\n\nEligible methods are subsequently registered for wire-event dispatch.\n\nThe method name and parameter types are used to construct the corresponding\nwire key:\n\nMethodWireKey key =\n    new MethodWireKey(\n        method.getName(),\n        parameterTypes);\n\nThis means the set of methods callable through the wire protocol is derived\nfrom the public methods exposed by the registered handler interface.\n\nWhen incoming wire data is processed, the supplied event name is matched\nagainst the registered method dispatch table. The corresponding argument\nvalues are then deserialized according to the selected method\u0027s declared\nparameter types:\n\narguments[i] =\n    valueIn.object(parameterTypes[i]);\n\nAfter argument deserialization, the selected Java method is invoked\nreflectively:\n\nmethod.invoke(target, arguments);\n\nConsequently, externally controlled wire data participates directly in two\nsecurity-sensitive decisions: selecting which registered handler method is\nexecuted and supplying the arguments passed to that method.\n\nThe dispatch mechanism itself does not introduce a method-level\nauthorization decision between event selection and invocation. The\neffective security boundary is therefore determined by which interfaces are\nregistered with MethodReader, which public methods those interfaces expose,\nand whether the application permits untrusted data to reach the reader.\nRoot Cause\n\nThe security issue arises from automatically deriving the externally\ndispatchable method surface from public methods exposed by registered\nhandler interfaces.\n\nChronicle Wire:\n\n   -\n\n   Discovers public methods associated with registered handlers.\n   -\n\n   Registers eligible methods as wire-event handlers.\n   -\n\n   Resolves incoming event names to those methods.\n   -\n\n   Deserializes method parameters from the corresponding wire input.\n   -\n\n   Invokes the selected methods using Java Reflection.\n\nThe dispatch model does not require each callable operation to be\nindependently exported or registered at the method level. Consequently, the\nsecurity boundary of a MethodReader can expand when additional public\nmethods are introduced into an interface already used for wire dispatch.\n\nThis creates a risk in applications where the registered handler interface\ncontains operations that should not be reachable by the party controlling\nthe wire input.\n\nThe issue is particularly significant when interfaces evolve over time.\nAdding a new public operation to an existing MethodReader-facing interface\ncan simultaneously add that operation to the wire dispatch surface without\na separate dispatch registration step.\nImpact\n\nWhen untrusted input reaches a MethodReader, an attacker can select among\nthe public operations exposed through the registered handler interface and\nprovide serialized arguments for the selected operation.\n\nThe resulting security impact depends on the functionality implemented by\nthose handlers.\n\nSecurity-sensitive methods may include:\n\n   -\n\n   file access and file modification;\n   -\n\n   outbound network communication;\n   -\n\n   administrative operations;\n   -\n\n   key rotation or key-management operations;\n   -\n\n   configuration changes;\n   -\n\n   maintenance functionality;\n   -\n\n   state-changing business operations; and\n   -\n\n   other privileged application functionality.\n\nIf such operations are exposed through a registered handler interface,\nexternally controlled event names can cause those methods to be invoked\nwith externally supplied arguments.\n\nThe attack surface can also change as the application evolves. A public\nmethod added to an interface already participating in MethodReader dispatch\nmay become a new wire operation without requiring separate registration of\nthat individual method.\n\nMethods accepting broad or polymorphic argument types introduce an\nadditional concern. Arguments are processed through Chronicle Wire\u0027s object\ndeserialization mechanisms:\n\narguments[i] =\n    valueIn.object(parameterTypes[i]);\n\nWhere the declared parameter type permits serialized type information to\ninfluence runtime object selection, externally controlled input may affect\nboth the *method selected for invocation* and the *runtime object\ninstantiated as its argument*.\n\nThe resulting vulnerability therefore combines an externally controlled\nmethod-dispatch surface with attacker-controlled argument deserialization.\nThe ultimate impact depends on the operations exposed by the registered\nhandler and the trust boundary through which wire messages are received.\n\nProof of Concept\n\nThe proof of concept demonstrates that Chronicle Wire\u0027s MethodReader allows\nserialized event names to select public methods exposed by a registered\nhandler and supplies those methods with arguments deserialized from the\ncorresponding wire message.\n\nThe tests exercise several handler operations to demonstrate method\nselection, privileged-operation reachability, automatic expansion of the\ndispatch surface, and typed argument deserialization.\nAdministrative Method Invocation\n\nThe registered handler exposes an administrative demonstration method named\ndeleteAll.\n\nThe following wire event was supplied:\n\ndeleteAll: pwned-method-invocation\n\nObserved output:\n\nMethodReader invoked event-selected method:\ndeleteAll:pwned-method-invocation\n\nThis confirms that the event name supplied in the wire message selected the\ncorresponding public handler method and that the attacker-controlled\nargument was delivered to that method.\n\nThe demonstration method does not perform destructive deletion. Its purpose\nis to establish that an operation exposed by the registered handler can be\nselected directly through the incoming event name.\nFile-Reading Method Invocation\n\nThe handler additionally exposes a demonstration method that reads a\ncaller-specified system file.\n\nThe supplied event was:\n\nreadSystemFile: /etc/hosts\n\nObserved invocation:\n\nMethodReader invoked file-reading method:\nreadSystemFile:/etc/hosts\n\nThe handler successfully accessed the supplied file and recorded:\n\nMethodReader file-read evidence:\n/etc/hosts:bytes=279:first-line=##\n\nThe test therefore demonstrates more than method-name resolution. The\nexternally supplied event selected a file-access operation and the\nexternally supplied argument controlled the path processed by that\noperation.\nAutomatic Exposure of Newly Added Handler Methods\n\nA new public method was added to the registered handler interface:\n\nvoid pingLocalhost(int port);\n\nNo individual MethodReader registration was added for pingLocalhost.\n\nThe following wire event was then supplied:\n\npingLocalhost: 61866\n\nObserved output:\n\nMethodReader invoked loopback ping method:\npingLocalhost:61866\n\nThe test additionally recorded the resulting loopback interaction:\n\nMethodReader loopback ping evidence:\npingLocalhost:127.0.0.1:61866\n\nThis confirms that adding the method to the registered handler interface\nwas sufficient for the operation to become part of the MethodReader\ndispatch surface.\n\nThe test is significant because it demonstrates that the callable surface\ncan expand as the handler interface evolves. A newly introduced public\nhandler operation does not require separate method-level registration\nbefore it can be selected by a corresponding wire event.\nProcess-Execution Demonstration\n\nThe automatic dispatch behavior was further tested with a deliberately\nintroduced handler method containing a process-execution operation:\n\nvoid runtimeExecEcho(String command);\n\nThe following event was supplied:\n\nruntimeExecEcho: pwned-runtime-exec\n\nObserved invocation:\n\nMethodReader invoked Runtime.exec method:\nruntimeExecEcho:pwned-runtime-exec\n\nThe test recorded successful process execution:\n\nMethodReader Runtime.exec evidence:\ncommand=/bin/echo pwned-runtime-exec, exit=0\n\nProcess output:\n\npwned-runtime-exec\n\nThis test does not establish that Chronicle Wire itself contains a built-in\ncommand-execution method or universal RCE gadget. The runtimeExecEcho\nmethod was intentionally introduced as a controlled demonstration of the\nsecurity consequence when a privileged operation exists on a registered\nhandler interface.\n\nThe result confirms the underlying dispatch property: once the public\nmethod was present on the handler interface, the corresponding wire event\ncould select and invoke it without separate method-level registration.\nTyped Object Argument Deserialization\n\nThe PoC additionally demonstrates that MethodReader dispatch can interact\nwith Chronicle Wire\u0027s typed object deserialization when a handler accepts a\nsufficiently broad parameter type.\n\nThe supplied event contained a tagged object:\n\nacceptObject:\n  !net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe {\n      marker: proof\n  }\n\nObserved output:\n\nMethodReader typed argument instantiated class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe\n\nMethodReader typed argument constructor calls: 1\n\nMethodReader typed argument readMarshallable calls: 1\n\nThis confirms that MethodReader did not simply pass a textual\nrepresentation of the supplied argument to the handler.\n\nThe argument entered Chronicle Wire\u0027s object deserialization path, the\nclass identified by the serialized type information was instantiated, its\nconstructor executed, and its readMarshallable() callback was invoked.\n\nFor handler methods accepting broad or polymorphic parameter types,\nexternally controlled wire input may therefore influence both the handler\noperation selected for invocation and the runtime object created as its\nargument.\nPoC Results\n\nThe runtime evidence confirms the following MethodReader behaviors:\n\n[CONFIRMED] Wire event selected deleteAll handler method\n[CONFIRMED] Attacker-controlled argument delivered to selected method\n\n[CONFIRMED] Wire event selected readSystemFile handler method\n[CONFIRMED] Supplied /etc/hosts path processed by handler\n[CONFIRMED] File contents successfully read\n\n[CONFIRMED] Newly added pingLocalhost method became dispatchable\n[CONFIRMED] No separate method-level registration was required\n[CONFIRMED] Loopback network interaction occurred\n\n[CONFIRMED] Newly added runtimeExecEcho method became dispatchable\n[CONFIRMED] Demonstration process executed successfully\n[CONFIRMED] /bin/echo exited with status 0\n"
            }
          ],
          "providerMetadata": {
            "dateUpdated": "2026-09-07T13:20:21Z",
            "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
            "shortName": "VULNARCHIVE"
          },
          "references": [
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/102"
            },
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://seclists.org/fulldisclosure/2026/Aug/102"
            },
            {
              "url": "https://github.com/ob1sec"
            },
            {
              "url": "https://linkedin.com/in/yourhandle"
            },
            {
              "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
            },
            {
              "url": "https://seclists.org/fulldisclosure/"
            },
            {
              "url": "https://www.linkedin.com/in/ronedgerson1"
            }
          ],
          "source": {
            "defect": [
              "https://seclists.org/fulldisclosure/2026/Aug/102"
            ],
            "discovery": "EXTERNAL"
          },
          "title": "Chronicle Wire v2026.8 Insecure Reflection Allows Unvalidated Method Invocation",
          "x_gcve": [
            {
              "recordType": "advisory",
              "relationships": [],
              "vulnId": "GCVE-1988-2026-0074",
              "x_vulnarchive": {
                "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/102",
                "automated": true,
                "contentSha256": "bbe8e54d524a45f120a262f1513e18e475b3fd19d5803ec612ee1b582cd7d0c1",
                "evidenceScore": 7,
                "messageId": "",
                "originalUrl": "https://seclists.org/fulldisclosure/2026/Aug/102",
                "policy": "vulnarchive-1",
                "sourceFormat": "text/html",
                "sourcePublishedAt": "2026-08-22T12:42:03Z"
              }
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "assignerShortName": "VULNARCHIVE",
        "datePublished": "2026-09-07T13:20:21Z",
        "dateUpdated": "2026-09-07T13:20:21Z",
        "state": "PUBLISHED",
        "vulnId": "GCVE-1988-2026-0074"
      },
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }

    GCVE-1988-2026-0073

    Vulnerability from gna-1988 – Published: 2026-09-07 13:20 – Updated: 2026-09-07 13:20
    VLAI
    Title
    Chronicle Wire v2026.8 FileMarshallableOut Append Operations Follow Symbolic Links and Allow File Write Redirection
    Summary
    Chronicle Wire's FileMarshallableOut follows symbolic links when writing files in append mode. When ?append=true is enabled, the implementation opens the supplied output path directly using FileOutputStream(path, true) without preventing symbolic-link resolution. If an attacker can create or replace the expected output file with a symbolic link before the append operation occurs, the operating system resolves the link and Chronicle Wire writes to the link target using the privileges of the application process. This can redirect application-generated output from its intended destination to another file writable by the application. The proof of concept confirms that an append operation directed at a symbolic-link path modifies the underlying target file. A separate boundary test confirms that non-append overwrite mode does not exhibit the same behavior: the symbolic-link path is replaced while the original target remains unchanged. The vulnerability is therefore specifically limited to the append-mode file-opening path. Vulnerability Details FileMarshallableOut determines the destination used for file output based on whether append mode is enabled: final String path = url.getPath(); final String path0 = options.append ? path : (path + ".tmp"); When append mode is disabled, Chronicle Wire writes through a temporary path. When append mode is enabled, however, path0 directly references the supplied destination: path0 = path; The resulting file is opened using: try (FileOutputStream out = new FileOutputStream(path0, options.append)) { final Bytes<byte[]> bytes = Jvm.uncheckedCast(wire.bytes()); out.write( bytes.underlyingObject(), 0, (int) bytes.readLimit()); } In append mode, the effective operation is therefore: new FileOutputStream(path, true); No protection against symbolic-link resolution is applied when this file is opened. If path identifies a symbolic link, normal filesystem resolution causes the underlying target to be opened and modified. The existing path validation does not prevent this condition: String path = url.getPath(); if (path == null || path.isEmpty() || path.contains("..")) throw new IllegalArgumentException( "Invalid file path: " + path); This prevents certain malformed or traversal-style paths but does not protect the final destination from symbolic-link substitution. Root Cause The append implementation opens the destination using a filesystem operation that follows symbolic links without enforcing a no-follow policy. The vulnerability does not require .. traversal or an unusual path syntax. The apparent destination itself can be a valid filesystem path while referencing a symbolic link created or substituted by another user or process. This creates a security issue when there is a privilege or trust-boundary difference between the process performing the append operation and the party capable of manipulating the destination filesystem entry. For example, a less-privileged attacker may be able to create or replace a predictable output file within a shared or attacker-writable directory. If a more privileged application subsequently performs a FileMarshallableOut append against that path, the resulting write can be redirected to a different file accessible to the application. Security Impact An attacker capable of manipulating the filesystem entry used as an append destination may redirect Chronicle Wire output to another file writable by the application's privileges. Potential consequences depend on the target application's filesystem permissions and the contents being written. Affected deployment patterns may include applications writing to: - shared writable directories; - predictable temporary locations; - application export directories; - CI/CD workspaces; - shared container volumes; - cache or working directories; - plugin-controlled filesystem locations; or - other locations where a less-privileged party can manipulate destination entries. The confirmed security primitive is *file write redirection through symbolic-link following*. The proof of concept does not establish arbitrary file overwrite because the affected operation uses append semantics. The attacker-selected target must also be writable by the application process. Proof of Concept The proof of concept creates an ordinary target file containing: before A symbolic link named: safe-looking-output.yaml is then created pointing to: target.txt Chronicle Wire is instructed to write to safe-looking-output.yaml with append mode enabled. The apparent destination is therefore the symbolic-link path, while the actual filesystem object modified by the operation is target.txt. Observed Results The test confirmed the symbolic-link destination and target: FileMarshallableOut append followed symlink: /.../safe-looking-output.yaml FileMarshallableOut symlink target: /.../target.txt Before the Chronicle Wire operation, the target contained: FileMarshallableOut symlink content before BEGIN before FileMarshallableOut symlink content before END The value supplied to FileMarshallableOut was: FileMarshallableOut symlink value written: message=symlink-append-proof After the append operation, the target contained: FileMarshallableOut symlink content after BEGIN before message: symlink-append-proof ... FileMarshallableOut symlink content after END The original contents remained and the Chronicle Wire output was appended directly to the symbolic-link target. This confirms that FileMarshallableOut followed the symbolic link during the append operation. Boundary Validation Non-append mode was tested separately to determine whether the behavior affected all FileMarshallableOut file writes. The original target contained: before After performing the non-append operation through the symbolic-link path, the original target still contained: before The test confirmed that non-append processing replaced the symbolic-link path rather than following the link and modifying its original target. The demonstrated vulnerability is therefore specifically associated with: ?append=true and the corresponding: new FileOutputStream(path, true); file-opening path. PoC Results The security test confirmed the following behavior: [CONFIRMED] Append destination was a symbolic link[CONFIRMED] Symbolic link referenced a separate target file[CONFIRMED] Chronicle Wire opened the apparent destination in append mode[CONFIRMED] Output was written to the symbolic-link target[CONFIRMED] Original target contents remained intact[CONFIRMED] Chronicle Wire data was appended to the target[CONFIRMED] Non-append mode did not modify the original symlink target The runtime evidence demonstrates that append-mode output can cross the apparent filesystem boundary established by the supplied destination path. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
    Severity
    No CVSS data available.
    Impacted products
    Vendor Product Version
    unknown Chronicle Wire Affected: unknown
    Create a notification for this product.
    Credits

    {
      "containers": {
        "cna": {
          "affected": [
            {
              "product": "Chronicle Wire",
              "vendor": "unknown",
              "versions": [
                {
                  "status": "affected",
                  "version": "unknown"
                }
              ]
            }
          ],
          "credits": [
            {
              "lang": "en",
              "type": "finder",
              "value": "Ron E"
            }
          ],
          "descriptions": [
            {
              "lang": "en",
              "value": "Chronicle Wire\u0027s FileMarshallableOut follows symbolic links when writing\nfiles in append mode. When ?append=true is enabled, the implementation\nopens the supplied output path directly using FileOutputStream(path, true)\nwithout preventing symbolic-link resolution.\n\nIf an attacker can create or replace the expected output file with a\nsymbolic link before the append operation occurs, the operating system\nresolves the link and Chronicle Wire writes to the link target using the\nprivileges of the application process.\n\nThis can redirect application-generated output from its intended\ndestination to another file writable by the application.\n\nThe proof of concept confirms that an append operation directed at a\nsymbolic-link path modifies the underlying target file. A separate boundary\ntest confirms that non-append overwrite mode does not exhibit the same\nbehavior: the symbolic-link path is replaced while the original target\nremains unchanged.\n\nThe vulnerability is therefore specifically limited to the append-mode\nfile-opening path.\nVulnerability Details\n\nFileMarshallableOut determines the destination used for file output based\non whether append mode is enabled:\n\nfinal String path = url.getPath();\nfinal String path0 = options.append ? path : (path + \".tmp\");\n\nWhen append mode is disabled, Chronicle Wire writes through a temporary\npath.\n\nWhen append mode is enabled, however, path0 directly references the\nsupplied destination:\n\npath0 = path;\n\nThe resulting file is opened using:\n\ntry (FileOutputStream out =\n         new FileOutputStream(path0, options.append)) {\n\n    final Bytes\u003cbyte[]\u003e bytes =\n        Jvm.uncheckedCast(wire.bytes());\n\n    out.write(\n        bytes.underlyingObject(),\n        0,\n        (int) bytes.readLimit());\n}\n\nIn append mode, the effective operation is therefore:\n\nnew FileOutputStream(path, true);\n\nNo protection against symbolic-link resolution is applied when this file is\nopened.\n\nIf path identifies a symbolic link, normal filesystem resolution causes the\nunderlying target to be opened and modified.\n\nThe existing path validation does not prevent this condition:\n\nString path = url.getPath();\n\nif (path == null ||\n    path.isEmpty() ||\n    path.contains(\"..\"))\n    throw new IllegalArgumentException(\n        \"Invalid file path: \" + path);\n\nThis prevents certain malformed or traversal-style paths but does not\nprotect the final destination from symbolic-link substitution.\nRoot Cause\n\nThe append implementation opens the destination using a filesystem\noperation that follows symbolic links without enforcing a no-follow policy.\n\nThe vulnerability does not require .. traversal or an unusual path syntax.\nThe apparent destination itself can be a valid filesystem path while\nreferencing a symbolic link created or substituted by another user or\nprocess.\n\nThis creates a security issue when there is a privilege or trust-boundary\ndifference between the process performing the append operation and the\nparty capable of manipulating the destination filesystem entry.\n\nFor example, a less-privileged attacker may be able to create or replace a\npredictable output file within a shared or attacker-writable directory. If\na more privileged application subsequently performs a FileMarshallableOut\nappend against that path, the resulting write can be redirected to a\ndifferent file accessible to the application.\nSecurity Impact\n\nAn attacker capable of manipulating the filesystem entry used as an append\ndestination may redirect Chronicle Wire output to another file writable by\nthe application\u0027s privileges.\n\nPotential consequences depend on the target application\u0027s filesystem\npermissions and the contents being written.\n\nAffected deployment patterns may include applications writing to:\n\n   - shared writable directories;\n   - predictable temporary locations;\n   - application export directories;\n   - CI/CD workspaces;\n   - shared container volumes;\n   - cache or working directories;\n   - plugin-controlled filesystem locations; or\n   - other locations where a less-privileged party can manipulate\n   destination entries.\n\nThe confirmed security primitive is *file write redirection through\nsymbolic-link following*.\n\nThe proof of concept does not establish arbitrary file overwrite because\nthe affected operation uses append semantics. The attacker-selected target\nmust also be writable by the application process.\nProof of Concept\n\nThe proof of concept creates an ordinary target file containing:\n\nbefore\n\nA symbolic link named:\n\nsafe-looking-output.yaml\n\nis then created pointing to:\n\ntarget.txt\n\nChronicle Wire is instructed to write to safe-looking-output.yaml with\nappend mode enabled.\n\nThe apparent destination is therefore the symbolic-link path, while the\nactual filesystem object modified by the operation is target.txt.\nObserved Results\n\nThe test confirmed the symbolic-link destination and target:\n\nFileMarshallableOut append followed symlink:\n/.../safe-looking-output.yaml\n\nFileMarshallableOut symlink target:\n/.../target.txt\n\nBefore the Chronicle Wire operation, the target contained:\n\nFileMarshallableOut symlink content before BEGIN\nbefore\nFileMarshallableOut symlink content before END\n\nThe value supplied to FileMarshallableOut was:\n\nFileMarshallableOut symlink value written:\nmessage=symlink-append-proof\n\nAfter the append operation, the target contained:\n\nFileMarshallableOut symlink content after BEGIN\nbefore\nmessage: symlink-append-proof\n...\nFileMarshallableOut symlink content after END\n\nThe original contents remained and the Chronicle Wire output was appended\ndirectly to the symbolic-link target.\n\nThis confirms that FileMarshallableOut followed the symbolic link during\nthe append operation.\nBoundary Validation\n\nNon-append mode was tested separately to determine whether the behavior\naffected all FileMarshallableOut file writes.\n\nThe original target contained:\n\nbefore\n\nAfter performing the non-append operation through the symbolic-link path,\nthe original target still contained:\n\nbefore\n\nThe test confirmed that non-append processing replaced the symbolic-link\npath rather than following the link and modifying its original target.\n\nThe demonstrated vulnerability is therefore specifically associated with:\n\n?append=true\n\nand the corresponding:\n\nnew FileOutputStream(path, true);\n\nfile-opening path.\nPoC Results\n\nThe security test confirmed the following behavior:\n\n[CONFIRMED] Append destination was a symbolic link[CONFIRMED] Symbolic\nlink referenced a separate target file[CONFIRMED] Chronicle Wire\nopened the apparent destination in append mode[CONFIRMED] Output was\nwritten to the symbolic-link target[CONFIRMED] Original target\ncontents remained intact[CONFIRMED] Chronicle Wire data was appended\nto the target[CONFIRMED] Non-append mode did not modify the original\nsymlink target\n\nThe runtime evidence demonstrates that append-mode output can cross the\napparent filesystem boundary established by the supplied destination path.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
            }
          ],
          "providerMetadata": {
            "dateUpdated": "2026-09-07T13:20:21Z",
            "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
            "shortName": "VULNARCHIVE"
          },
          "references": [
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/83"
            },
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://seclists.org/fulldisclosure/2026/Aug/83"
            },
            {
              "url": "https://github.com/ob1sec"
            },
            {
              "url": "https://linkedin.com/in/yourhandle"
            },
            {
              "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
            },
            {
              "url": "https://seclists.org/fulldisclosure/"
            },
            {
              "url": "https://www.linkedin.com/in/ronedgerson1"
            }
          ],
          "source": {
            "defect": [
              "https://seclists.org/fulldisclosure/2026/Aug/83"
            ],
            "discovery": "EXTERNAL"
          },
          "title": "Chronicle Wire v2026.8 FileMarshallableOut Append Operations Follow Symbolic Links and Allow File Write Redirection",
          "x_gcve": [
            {
              "recordType": "advisory",
              "relationships": [],
              "vulnId": "GCVE-1988-2026-0073",
              "x_vulnarchive": {
                "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/83",
                "automated": true,
                "contentSha256": "5de50e3c1671bae7dda757a3dc128e36b921139464af78fca0496bf95f07f08c",
                "evidenceScore": 7,
                "messageId": "",
                "originalUrl": "https://seclists.org/fulldisclosure/2026/Aug/83",
                "policy": "vulnarchive-1",
                "sourceFormat": "text/html",
                "sourcePublishedAt": "2026-08-22T12:41:27Z"
              }
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "assignerShortName": "VULNARCHIVE",
        "datePublished": "2026-09-07T13:20:21Z",
        "dateUpdated": "2026-09-07T13:20:21Z",
        "state": "PUBLISHED",
        "vulnId": "GCVE-1988-2026-0073"
      },
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }

    GCVE-1988-2026-0075

    Vulnerability from gna-1988 – Published: 2026-09-07 13:20 – Updated: 2026-09-07 13:20
    VLAI
    Title
    Chronicle Wire v2026.8 Arbitrary Class Instantiation During YAML Deserialization via Externally Controlled YAML Type Tags
    Summary
    Chronicle Wire permits YAML type tags supplied within serialized input to influence Java class selection and object instantiation during untyped deserialization. When applications deserialize attacker-controlled or otherwise untrusted YAML through APIs such as readObject() or object(Object.class), an externally controlled YAML type tag can identify a Java class that Chronicle Wire resolves through its configured ClassLookup. When the default permissive class lookup is used and the supplied class can be resolved, the resulting class can propagate through Chronicle Wire's generic object deserialization path and ultimately reach ObjectUtils.newInstance(clazz). Chronicle Wire can then invoke the selected class's deserialization lifecycle, including readMarshallable() where applicable. The security-sensitive behavior is therefore not limited to ordinary data binding. Externally supplied serialized data can influence *which Java class is instantiated during deserialization*. The accompanying proof of concept confirms that: - An externally controlled YAML type tag selects the Java class instantiated by readObject(). - The selected class's constructor is executed. - A selected class's readMarshallable() implementation is automatically invoked during deserialization. - An existing third-party class already present on the runtime classpath can be instantiated using a YAML type tag. - Configuring a restrictive ClassLookup prevents the demonstrated arbitrary class selection. The practical security impact depends on the classes available on the target application's classpath and whether untrusted YAML reaches an affected untyped deserialization API. The PoC establishes the arbitrary class-selection and instantiation primitive but does not claim universal arbitrary code execution. Vulnerability Details Chronicle Wire supports YAML type tags capable of identifying Java classes during deserialization. For example: !fully.qualified.ClassName The parser does not treat this value solely as descriptive metadata. The supplied class name is resolved using the wire's configured ClassLookup. The default wire configuration initializes the lookup using the global alias pool: protected ClassLookup classLookup = ClassAliasPool.CLASS_ALIASES; When a YAML TAG token is encountered, the supplied type is resolved: Class<?> typePrefix() { ... return classLookup().forName(stringBuilder); } The class represented by the serialized YAML can therefore influence the Java type selected during deserialization. In affected object-reading paths, Chronicle Wire can subsequently instantiate the resolved class: Class<?> clazz = typePrefix(); if (clazz != object.getClass()) object = ObjectUtils.newInstance(clazz); The externally selected type can also propagate into the generic object deserialization path: Object o = typePrefixOrObject(clazz); ... t = Wires.object2(..., (Class) o); Within Wires.object2(), the type supplied by serialized input can replace the caller's original type under several conditions: if (clazz == null || clazz.isAssignableFrom(clazz2) || ReadResolvable.class.isAssignableFrom(clazz2) || !ObjectUtils.isConcreteClass(clazz)) { clazz = clazz2; } Chronicle Wire can then instantiate the selected class: if (o == null) o = ObjectUtils.newInstance(clazz); and continue the object's deserialization lifecycle: Wires.readMarshallable( clazz, o, in.wireIn(), true); As a result, when permissive class resolution is available, externally controlled YAML can influence both the class instantiated by Chronicle Wire and the class-specific deserialization logic subsequently executed. Root Cause The root cause is the use of serialized YAML type information to select Java classes during generic or untyped object deserialization without a mandatory deny-by-default class allow-list. Chronicle Wire resolves externally supplied YAML type tags through its configured ClassLookup. When the default permissive lookup permits the requested type, the resulting class can propagate into generic object deserialization and reach ObjectUtils.newInstance(). The security boundary becomes particularly important when an application performs operations such as: TextWire.from(untrustedYaml).readObject(); or equivalent untyped deserialization. In this situation, the application is not exclusively determining the Java class being constructed. The serialized YAML participates in that decision. A restrictive ClassLookup can prevent arbitrary class resolution, but such a restriction is not inherent to the demonstrated default deserialization path. Proof of Concept Results The security test suite successfully reproduced multiple independent paths in which serialized type information caused Chronicle Wire to instantiate classes selected through the supplied Wire/YAML data. The tests completed successfully with no failures or errors: [INFO] Running net.openhft.chronicle.wire.SecurityAdditionalPoCTest [INFO] Tests run: 13, Failures: 0, Errors: 0, Skipped: 0 [INFO] BUILD SUCCESS Direct Tagged Class Instantiation The PoC confirmed that Chronicle Wire resolves a supplied YAML type tag and instantiates the corresponding Java class during deserialization. Observed result: WireObjectInput.readObject instantiated tagged class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe This confirms that the class encoded in serialized input is not merely parsed as metadata. The resolved type reaches object construction and results in an instance of the tagged class. Map Value Type Instantiation The same externally controlled type-selection behavior was reproduced while deserializing a typed value contained within a map. Observed result: Map value read instantiated tagged class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe This demonstrates that the behavior is not limited to a single top-level readObject() operation. Typed serialized values encountered within other object-reading paths can also cause tagged classes to be instantiated. File-Based Typed Deserialization The PoC additionally confirmed arbitrary class instantiation when typed serialized data is loaded from a caller-controlled file. The test file contained: !net.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe { marker: from-file } The test output confirmed the exact payload written to the file: WireType.fromFile payload written BEGIN !net.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe { marker: from-file } WireType.fromFile payload written END Chronicle Wire subsequently instantiated the class identified by the serialized type tag: WireType.fromFile instantiated tagged class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe This provides an additional concrete deserialization path where serialized type information determines the Java class instantiated by Chronicle Wire. Stream-Based File Deserialization The same behavior was confirmed through the file-stream deserialization path. Observed result: WireType.streamFromFile instantiated tagged class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe This demonstrates that externally supplied type information can reach class instantiation through more than one Chronicle Wire input API. Constructor and readMarshallable() Execution The strongest lifecycle evidence was produced through a MethodReader typed argument. The serialized argument selected the following class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe The test recorded both constructor and deserialization callback invocation: MethodReader typed argument instantiated class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe MethodReader typed argument constructor calls: 1 MethodReader typed argument readMarshallable calls: 1 This confirms that externally selected type information can result in more than creation of an inert Java object. For the selected class, Chronicle Wire caused: - the class to be resolved; - an instance to be constructed; - the constructor to execute; and - the class-specific readMarshallable() callback to execute. The observed invocation counts were: Constructor calls: 1 readMarshallable calls: 1 This provides direct evidence that class-specific executable lifecycle behavior is reached as a consequence of serialized type selection. Consolidated PoC Evidence The test results demonstrate arbitrary class instantiation through several Chronicle Wire deserialization paths: - WireObjectInput.readObject() instantiated an externally tagged class. - Map value deserialization instantiated an externally tagged class. - WireType.fromFile() instantiated the class identified by a YAML type tag contained in a caller-controlled file. - WireType.streamFromFile() instantiated an externally tagged class. - MethodReader typed argument deserialization instantiated an externally selected class. - Constructor execution was directly observed. - readMarshallable() execution was directly observed. - All 13 security tests completed without failure or error. The most significant lifecycle result was: MethodReader typed argument instantiated class: net.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe MethodReader typed argument constructor calls: 1 MethodReader typed argument readMarshallable calls: 1 Combined with the direct readObject(), map-value, fromFile(), and streamFromFile() results, the PoC demonstrates that externally supplied type information can influence Java class selection and cause the selected class to be instantiated across multiple Chronicle Wire deserialization surfaces. The PoC does not rely solely on inspecting the source code or confirming that a class name was successfully resolved. It observes actual object construction and class-specific deserialization callback execution at runtime. PoC Conclusion The test suite confirms the core security primitive described by this finding: *serialized type information can control which Java class Chronicle Wire instantiates during affected deserialization operations*. The runtime evidence confirms both object construction and execution of class-specific deserialization lifecycle behavior: [CONFIRMED] Externally supplied type selected Java class [CONFIRMED] Selected class instantiated [CONFIRMED] Constructor executed [CONFIRMED] readMarshallable() executed [CONFIRMED] Typed class instantiated through readObject() [CONFIRMED] Typed class instantiated through map value deserialization [CONFIRMED] Typed class instantiated through WireType.fromFile() [CONFIRMED] Typed class instantiated through WireType.streamFromFile() [CONFIRMED] 13 security tests completed with 0 failures and 0 errors These results establish the *arbitrary class selection and instantiation primitive*. The ultimate security impact remains dependent on the classes available on the target application's classpath and the trust boundary through which serialized input reaches Chronicle Wire. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
    Severity
    No CVSS data available.
    Impacted products
    Vendor Product Version
    unknown Chronicle Wire Affected: unknown
    Create a notification for this product.
    Credits

    {
      "containers": {
        "cna": {
          "affected": [
            {
              "product": "Chronicle Wire",
              "vendor": "unknown",
              "versions": [
                {
                  "status": "affected",
                  "version": "unknown"
                }
              ]
            }
          ],
          "credits": [
            {
              "lang": "en",
              "type": "finder",
              "value": "Ron E"
            }
          ],
          "descriptions": [
            {
              "lang": "en",
              "value": "Chronicle Wire permits YAML type tags supplied within serialized input to\ninfluence Java class selection and object instantiation during untyped\ndeserialization.\n\nWhen applications deserialize attacker-controlled or otherwise untrusted\nYAML through APIs such as readObject() or object(Object.class), an\nexternally controlled YAML type tag can identify a Java class that\nChronicle Wire resolves through its configured ClassLookup.\n\nWhen the default permissive class lookup is used and the supplied class can\nbe resolved, the resulting class can propagate through Chronicle Wire\u0027s\ngeneric object deserialization path and ultimately reach\nObjectUtils.newInstance(clazz). Chronicle Wire can then invoke the selected\nclass\u0027s deserialization lifecycle, including readMarshallable() where\napplicable.\n\nThe security-sensitive behavior is therefore not limited to ordinary data\nbinding. Externally supplied serialized data can influence *which Java\nclass is instantiated during deserialization*.\n\nThe accompanying proof of concept confirms that:\n\n   - An externally controlled YAML type tag selects the Java class\n   instantiated by readObject().\n   - The selected class\u0027s constructor is executed.\n   - A selected class\u0027s readMarshallable() implementation is automatically\n   invoked during deserialization.\n   - An existing third-party class already present on the runtime classpath\n   can be instantiated using a YAML type tag.\n   - Configuring a restrictive ClassLookup prevents the demonstrated\n   arbitrary class selection.\n\nThe practical security impact depends on the classes available on the\ntarget application\u0027s classpath and whether untrusted YAML reaches an\naffected untyped deserialization API. The PoC establishes the arbitrary\nclass-selection and instantiation primitive but does not claim universal\narbitrary code execution.\nVulnerability Details\n\nChronicle Wire supports YAML type tags capable of identifying Java classes\nduring deserialization.\n\nFor example:\n\n!fully.qualified.ClassName\n\nThe parser does not treat this value solely as descriptive metadata. The\nsupplied class name is resolved using the wire\u0027s configured ClassLookup.\n\nThe default wire configuration initializes the lookup using the global\nalias pool:\n\nprotected ClassLookup classLookup =\n    ClassAliasPool.CLASS_ALIASES;\n\nWhen a YAML TAG token is encountered, the supplied type is resolved:\n\nClass\u003c?\u003e typePrefix() {\n    ...\n    return classLookup().forName(stringBuilder);\n}\n\nThe class represented by the serialized YAML can therefore influence the\nJava type selected during deserialization.\n\nIn affected object-reading paths, Chronicle Wire can subsequently\ninstantiate the resolved class:\n\nClass\u003c?\u003e clazz = typePrefix();\n\nif (clazz != object.getClass())\n    object = ObjectUtils.newInstance(clazz);\n\nThe externally selected type can also propagate into the generic object\ndeserialization path:\n\nObject o = typePrefixOrObject(clazz);\n\n...\n\nt = Wires.object2(..., (Class) o);\n\nWithin Wires.object2(), the type supplied by serialized input can replace\nthe caller\u0027s original type under several conditions:\n\nif (clazz == null\n        || clazz.isAssignableFrom(clazz2)\n        || ReadResolvable.class.isAssignableFrom(clazz2)\n        || !ObjectUtils.isConcreteClass(clazz))\n{\n    clazz = clazz2;\n}\n\nChronicle Wire can then instantiate the selected class:\n\nif (o == null)\n    o = ObjectUtils.newInstance(clazz);\n\nand continue the object\u0027s deserialization lifecycle:\n\nWires.readMarshallable(\n    clazz,\n    o,\n    in.wireIn(),\n    true);\n\nAs a result, when permissive class resolution is available, externally\ncontrolled YAML can influence both the class instantiated by Chronicle Wire\nand the class-specific deserialization logic subsequently executed.\nRoot Cause\n\nThe root cause is the use of serialized YAML type information to select\nJava classes during generic or untyped object deserialization without a\nmandatory deny-by-default class allow-list.\n\nChronicle Wire resolves externally supplied YAML type tags through its\nconfigured ClassLookup. When the default permissive lookup permits the\nrequested type, the resulting class can propagate into generic object\ndeserialization and reach ObjectUtils.newInstance().\n\nThe security boundary becomes particularly important when an application\nperforms operations such as:\n\nTextWire.from(untrustedYaml).readObject();\n\nor equivalent untyped deserialization.\n\nIn this situation, the application is not exclusively determining the Java\nclass being constructed. The serialized YAML participates in that decision.\n\nA restrictive ClassLookup can prevent arbitrary class resolution, but such\na restriction is not inherent to the demonstrated default deserialization\npath.\nProof of Concept Results\n\nThe security test suite successfully reproduced multiple independent paths\nin which serialized type information caused Chronicle Wire to instantiate\nclasses selected through the supplied Wire/YAML data.\n\nThe tests completed successfully with no failures or errors:\n\n[INFO] Running net.openhft.chronicle.wire.SecurityAdditionalPoCTest\n\n[INFO] Tests run: 13, Failures: 0, Errors: 0, Skipped: 0\n\n[INFO] BUILD SUCCESS\n\nDirect Tagged Class Instantiation\n\nThe PoC confirmed that Chronicle Wire resolves a supplied YAML type tag and\ninstantiates the corresponding Java class during deserialization.\n\nObserved result:\n\nWireObjectInput.readObject instantiated tagged class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe\n\nThis confirms that the class encoded in serialized input is not merely\nparsed as metadata. The resolved type reaches object construction and\nresults in an instance of the tagged class.\nMap Value Type Instantiation\n\nThe same externally controlled type-selection behavior was reproduced while\ndeserializing a typed value contained within a map.\n\nObserved result:\n\nMap value read instantiated tagged class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe\n\nThis demonstrates that the behavior is not limited to a single top-level\nreadObject() operation. Typed serialized values encountered within other\nobject-reading paths can also cause tagged classes to be instantiated.\nFile-Based Typed Deserialization\n\nThe PoC additionally confirmed arbitrary class instantiation when typed\nserialized data is loaded from a caller-controlled file.\n\nThe test file contained:\n\n!net.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe {\n    marker: from-file\n}\n\nThe test output confirmed the exact payload written to the file:\n\nWireType.fromFile payload written BEGIN\n!net.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe {\nmarker: from-file }\nWireType.fromFile payload written END\n\nChronicle Wire subsequently instantiated the class identified by the\nserialized type tag:\n\nWireType.fromFile instantiated tagged class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$FilePathProbe\n\nThis provides an additional concrete deserialization path where serialized\ntype information determines the Java class instantiated by Chronicle Wire.\nStream-Based File Deserialization\n\nThe same behavior was confirmed through the file-stream deserialization\npath.\n\nObserved result:\n\nWireType.streamFromFile instantiated tagged class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$AdditionalTypedPathProbe\n\nThis demonstrates that externally supplied type information can reach class\ninstantiation through more than one Chronicle Wire input API.\nConstructor and readMarshallable() Execution\n\nThe strongest lifecycle evidence was produced through a MethodReader typed\nargument.\n\nThe serialized argument selected the following class:\n\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe\n\nThe test recorded both constructor and deserialization callback invocation:\n\nMethodReader typed argument instantiated class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe\n\nMethodReader typed argument constructor calls: 1\nMethodReader typed argument readMarshallable calls: 1\n\nThis confirms that externally selected type information can result in more\nthan creation of an inert Java object.\n\nFor the selected class, Chronicle Wire caused:\n\n   -\n\n   the class to be resolved;\n   -\n\n   an instance to be constructed;\n   -\n\n   the constructor to execute; and\n   -\n\n   the class-specific readMarshallable() callback to execute.\n\nThe observed invocation counts were:\n\nConstructor calls:        1\nreadMarshallable calls:   1\n\nThis provides direct evidence that class-specific executable lifecycle\nbehavior is reached as a consequence of serialized type selection.\nConsolidated PoC Evidence\n\nThe test results demonstrate arbitrary class instantiation through several\nChronicle Wire deserialization paths:\n\n   -\n\n   WireObjectInput.readObject() instantiated an externally tagged class.\n   -\n\n   Map value deserialization instantiated an externally tagged class.\n   -\n\n   WireType.fromFile() instantiated the class identified by a YAML type tag\n   contained in a caller-controlled file.\n   -\n\n   WireType.streamFromFile() instantiated an externally tagged class.\n   -\n\n   MethodReader typed argument deserialization instantiated an externally\n   selected class.\n   -\n\n   Constructor execution was directly observed.\n   -\n\n   readMarshallable() execution was directly observed.\n   -\n\n   All 13 security tests completed without failure or error.\n\nThe most significant lifecycle result was:\n\nMethodReader typed argument instantiated class:\nnet.openhft.chronicle.wire.SecurityAdditionalPoCTest$MethodReaderProbe\n\nMethodReader typed argument constructor calls: 1\nMethodReader typed argument readMarshallable calls: 1\n\nCombined with the direct readObject(), map-value, fromFile(), and\nstreamFromFile() results, the PoC demonstrates that externally supplied\ntype information can influence Java class selection and cause the selected\nclass to be instantiated across multiple Chronicle Wire deserialization\nsurfaces.\n\nThe PoC does not rely solely on inspecting the source code or confirming\nthat a class name was successfully resolved. It observes actual object\nconstruction and class-specific deserialization callback execution at\nruntime.\nPoC Conclusion\n\nThe test suite confirms the core security primitive described by this\nfinding: *serialized type information can control which Java class\nChronicle Wire instantiates during affected deserialization operations*.\n\nThe runtime evidence confirms both object construction and execution of\nclass-specific deserialization lifecycle behavior:\n\n[CONFIRMED] Externally supplied type selected Java class\n[CONFIRMED] Selected class instantiated\n[CONFIRMED] Constructor executed\n[CONFIRMED] readMarshallable() executed\n[CONFIRMED] Typed class instantiated through readObject()\n[CONFIRMED] Typed class instantiated through map value deserialization\n[CONFIRMED] Typed class instantiated through WireType.fromFile()\n[CONFIRMED] Typed class instantiated through WireType.streamFromFile()\n[CONFIRMED] 13 security tests completed with 0 failures and 0 errors\n\nThese results establish the *arbitrary class selection and instantiation\nprimitive*. The ultimate security impact remains dependent on the classes\navailable on the target application\u0027s classpath and the trust boundary\nthrough which serialized input reaches Chronicle Wire.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
            }
          ],
          "providerMetadata": {
            "dateUpdated": "2026-09-07T13:20:21Z",
            "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
            "shortName": "VULNARCHIVE"
          },
          "references": [
            {
              "tags": [
                "technical-description",
                "exploit"
              ],
              "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/103"
            },
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://seclists.org/fulldisclosure/2026/Aug/103"
            },
            {
              "url": "https://github.com/ob1sec"
            },
            {
              "url": "https://linkedin.com/in/yourhandle"
            },
            {
              "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
            },
            {
              "url": "https://seclists.org/fulldisclosure/"
            },
            {
              "url": "https://www.linkedin.com/in/ronedgerson1"
            }
          ],
          "source": {
            "defect": [
              "https://seclists.org/fulldisclosure/2026/Aug/103"
            ],
            "discovery": "EXTERNAL"
          },
          "title": "Chronicle Wire v2026.8 Arbitrary Class Instantiation During YAML Deserialization via Externally Controlled YAML Type Tags",
          "x_gcve": [
            {
              "recordType": "advisory",
              "relationships": [],
              "vulnId": "GCVE-1988-2026-0075",
              "x_vulnarchive": {
                "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Aug/103",
                "automated": true,
                "contentSha256": "373857b24efd6a689043e6cf615e0c3a0a62392da12986dc20b6425ac929092f",
                "evidenceScore": 9,
                "messageId": "",
                "originalUrl": "https://seclists.org/fulldisclosure/2026/Aug/103",
                "policy": "vulnarchive-1",
                "sourceFormat": "text/html",
                "sourcePublishedAt": "2026-08-22T12:42:32Z"
              }
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "assignerShortName": "VULNARCHIVE",
        "datePublished": "2026-09-07T13:20:21Z",
        "dateUpdated": "2026-09-07T13:20:21Z",
        "state": "PUBLISHED",
        "vulnId": "GCVE-1988-2026-0075"
      },
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }