GCVE-1988-2026-0499
Vulnerability from gna-1988 – Published: 2026-11-02 07:30 – Updated: 2026-11-02 07:30{
"containers": {
"cna": {
"affected": [
{
"product": "Render",
"vendor": "Royal",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "disclosure via Fulldisclosure"
}
],
"descriptions": [
{
"lang": "en",
"value": "0day Rubbish Research Team is publicly disclosing a vulnerability in Royal\nRender 9.1.26b, the closed-source render-farm job manager for VFX and\nanimation studios from Binary Alchemy (proprietor Holger Schoenberger) of\nLudwigsburg, Germany. Royal Render\nis a different product from the Royal Server gateway sold by Royal Apps GmbH\nof Austria; the two are unrelated companies sharing one word in their names,\nand this disclosure concerns the German render manager only.\n\nThe product\u0027s central scheduler, rrServer, shipped as the rrServerconsole\nbinary, listens on TCP 7773 and speaks a custom binary protocol that is not\nHTTP. In the state the product ships in, it performs no identity check on a\nconnection at all. That is the vendor\u0027s own documentation speaking, not an\nobservation of a test instance: the help page shipped inside the\ninstallation tree at files/help/Authorization.html states \"By default, the\nrrServer does NOT check for a valid user if you connect to the rrServer\".\nAuthorization is an opt-in feature, either a submission whitelist or an\nauthorization-required-for-all-connections switch, and the\nsub/cfg_global/globalconfig.ini that the vendor\u0027s own rrSetup_linux\ninstaller writes leaves both off, with nTCPRequiresAuth=false and an empty\nnAuthWhiteList. The primary classification is CWE-306 with CWE-1188 co-equal\nand CWE-73, plus CWE-250, CWE-284 and CWE-1392 contributing.\n\nType and root cause. Among the shipped job types is one named Execute with\nrenderer name Once, defined in render_apps/_config/E01__ExecuteOnce.cfg,\nwhich declares SceneFileExtension= *.bat;*.sh; and whose Linux command line\nis the template CommandLine_Lx= \u003cEndsWith(\u003cScene\u003e , .sh) source \u003e \"\u003cScene\u003e\"\n\u003cAdditionalCommandlineParam\u003e. For a scene path ending in .sh the worker\nresolves that template to source \"\u003cScene\u003e\" and runs it in its own shell, in\nthe current shell rather than as a child process. The scene path reaches the\nworker as the length-prefixed UTF-16LE dataset field execOnce.file inside the\ncompressed job record, and nothing between the socket and the shell\nconstrains it: no principal exists by default against which a job type could\nbe filtered, there is no allow-list or canonicalisation against a project\nroot, no owner or mount check, and no signature of the file being sourced.\nThe verified submission record is 1387 bytes, a 340-byte header carrying a\nlittle-endian uint32 at offset 0x0e equal to the exact compressed length of\nthe trailing block, 1047, another at offset 0x12 equal to its exact\ndecompressed size, 55252, a uint16 length prefix of 23 at 0x1b followed by\nthe submitter hostname at 0x1d, and a zlib stream with header 78 5e from\noffset 0x154. Decompressed, the record holds the job type Execute at offset\n32, the renderer fragment ;Once at 596, the server version text rr9.1.26b at\n3688, the scene path /tmp/rr_clean_poc.sh as a 20-character UTF-16LE string\nat offset 3792, and the key execOnce.file at offsets 7818 and 8324. The\nscheduler accepted the credential-free record and answered with a normal\n346-byte functional reply rather than a rejection or a challenge.\n\nExecution identity, reported as measured. The worker built and ran source\n\"/tmp/rr_clean_poc.sh\". The marker file produced was 34 bytes, owned\nroot:root, and a sibling file captured the identity output\nuid=0(root) gid=0(root) groups=0(root). Root was reached because the worker\nprocess in the verification deployment was started from a root shell, and\nthe product enforces no privilege separation between the identity that\nreceives a job and the identity that executes it, so the honest claim is\narbitrary shell execution as the worker\u0027s identity. No shipped artefact\nfixes a non-root default worker identity and none mandates root; the ceiling\nis deployment-dependent, and the advisory says so wherever the identity\nmatters.\n\nVerification boundary. Static work was documentary and wire-level rather\nthan disassembly-based: the shipped job-type configuration, the shipped\nPython SDK, and the captured submission record with its decompressed job\ndata. Dynamic work was a live detonation against an installation made with\nthe vendor\u0027s rrSetup_linux installer with the configuration left as\ninstalled, unlicensed and therefore in two-client demonstration mode, with\nthe authorization key observed to govern behaviour. The chain was driven\nend to end from a second client host on a different network segment, in its\nown network namespace with a private-range source address and a hostname\nforeign to the scheduler, so remote reachability is demonstrated across a\nnetwork boundary rather than argued from a bind address. Two properties of\nthe run were supplied by the research harness and are stated as such: the\nscene script\u0027s content and its presence at a worker-readable path, because\nthe job record carries a path and never file content and no primitive over\nTCP 7773 was demonstrated that delivers bytes; and the worker\u0027s root start.\nThe all-interface bind of port 7773 was measured on the test instance, with\nno shipped artefact stating the default bind in either direction.\n\nScoring. The published headline is 8.1 High,\nCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H, from ISS = 0.914816, Impact at\nS:U = 5.873119 and Exploitability = 2.221167, base 8.094286 rounded up.\nAttack complexity carries the one precondition the researchers did not\nobtain from the product: the record names a path, so attacker-chosen commands\nneed a script at a worker-readable path, which the harness placed in the\nverified run. A conditional reading of 9.8 Critical at AC:L is published\nlabelled conditional, applying only where an attacker can also write to the\nshared render storage the product\u0027s own scene-distribution model uses, or\nwhere a structural command-injection observation is confirmed; neither\nbranch was detonated, so 9.8 is not the headline. Further labelled\nconditionals cover a changed-scope reading at 9.1 and 10.0, an\nauthorization-enabled reading published at all four privilege and complexity\ncombinations, 8.8, 7.5, 7.2 and 6.6, and a management-network-only reading at\n7.5 and 8.8. One structural observation is published as inference and not as\na finding: \u003cAdditionalCommandlineParam\u003e is appended outside the template\u0027s\nquoting, so shell metacharacters in it would be interpreted by the worker\u0027s\nshell; the verified record contains no such field in ASCII or UTF-16LE, it\nwas not executed, and it raises no published score.\n\nImpact. One anonymous submission reaches whichever worker is idle, so the\nprimitive fans out to the whole farm and to every mount each worker holds;\nthe executed command inherits the worker\u0027s full identity and environment.\nIndependently of execution, the verified record carries the product\u0027s own\ndestructive post-processing tasks PPDeleteJob and PPDeletebroken, so an\nanonymous submitter can also enqueue and destroy queue state. Detection is\nweak by construction because every packet is legitimate product traffic; the\nusable signals are an Execute or Once job whose execOnce.file names a path\noutside recognised project storage, and a configuration audit finding\nnTCPRequiresAuth=false with an empty whitelist on any scheduler reachable\nbeyond a management segment.\n\nMitigation summary: ship authorization on by default; separate the Execute\nand Once job type behind an explicit administrator capability denied by\ndefault; canonicalise and allow-list execOnce.file against project and\nshared-storage roots, rejecting symlink escapes and world-writable\ndirectories; pass job arguments as an argument vector or quote every\nsubstitution; run workers as a dedicated unprivileged account; authenticate\nthe protocol handshake at connect time for every client class; and bind TCP\n7773 to the render-management interface as a documented management port.\n\nThe proof of concept is Python 3 using only the standard library. It writes\nthe scene script to the worker-readable path as an explicit local\nprecondition, removes stale markers, opens one TCP connection to the target\nport with no credentials, sends the submission record, reports the reply\nlength and first bytes, polls for the marker file, and reports its size,\nownership and content together with the captured identity output; it exits\nnon-zero if no reply or no marker appears, separating a rejected submission\nfrom a worker that did not execute. A dump mode reproduces every job-record\noffset cited above.\n\nFull technical analysis and the reproducible proof of concept, published\nunconditionally:\n https://0day-rubbish.com/blog/royal-render-default-unauthenticated-job-submission-root-rce\n\nProject archive (ongoing disclosure series):\n https://github.com/Exploit-Garbage/0day-Rubbish\n\nBinary Alchemy, the proprietorship that sells Royal Render, was notified\nunconditionally through the single mailbox its legally required imprint\nprints and its support page names in words as the\nsupport address, which is the only channel used. The vendor publishes no RFC\n9116 security.txt, the request returning 404, and no security page or\nvulnerability-disclosure policy was found on the site. Nothing was submitted\nto any intake form and no individual was addressed by name. This disclosure\nis unconditional: the research is already public, no permission was asked\nfor, no embargo was requested, and nothing is withheld pending a reply. No\nvulnerability identifier has been assigned to this finding yet.\n\n--\n0day Rubbish Research Team\ndisclosure () 0day-rubbish com\nhttps://0day-rubbish.com\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-1188",
"description": "CWE-1188",
"lang": "en",
"type": "CWE"
},
{
"cweId": "CWE-1392",
"description": "CWE-1392",
"lang": "en",
"type": "CWE"
},
{
"cweId": "CWE-250",
"description": "CWE-250",
"lang": "en",
"type": "CWE"
},
{
"cweId": "CWE-284",
"description": "CWE-284",
"lang": "en",
"type": "CWE"
},
{
"cweId": "CWE-306",
"description": "CWE-306",
"lang": "en",
"type": "CWE"
},
{
"cweId": "CWE-73",
"description": "CWE-73",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-11-02T07:30:04Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Oct/33"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Oct/33"
},
{
"url": "https://0day-rubbish.com"
},
{
"url": "https://0day-rubbish.com/blog/royal-render-default-unauthenticated-job-submission-root-rce"
},
{
"url": "https://github.com/Exploit-Garbage/0day-Rubbish"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Oct/33"
],
"discovery": "EXTERNAL"
},
"title": "[0day-rubbish] Royal Render 9.1.26b: default-unauthenticated job submission on rrServer TCP 7773 reaches worker-side shell execution as the worker identity, measured root (8.1 High)",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0499",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Oct/33",
"automated": true,
"contentSha256": "d3a7fb11b06f5696d22aea6f5e238df169f7d07f7e31d89a7ae9bf4cebf8f952",
"evidenceScore": 11,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Oct/33",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-10-20T02:31:31Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-11-02T07:30:04Z",
"dateUpdated": "2026-11-02T07:30:04Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0499"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
How durations are calculated
Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.
Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.