VYPR
Medium severity4.2NVD Advisory· Published May 18, 2026· Updated May 18, 2026

CVE-2026-8784

CVE-2026-8784

Description

A vulnerability was detected in npitre cramfs-tools up to 2.2. Affected is the function change_file_status of the file cramfsck.c. Performing a manipulation results in symlink following. The attack requires a local approach. The exploit is now public and may be used. The patch is named b4a3a695c9873f824907bd15659f2a6ac7667b4f. It is recommended to apply a patch to fix this issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

cramfsck in cramfs-tools up to 2.2 follows a preexisting symlink at the extraction root in continue-on-error mode, enabling local attackers to write files outside the intended directory.

Vulnerability

Overview

A vulnerability was detected in npitre cramfs-tools up to version 2.2. The affected function is change_file_status in cramfsck.c. The issue is a classic symlink following weakness (CWE-59) that occurs when the tool's continue-on-error mode (-c) is used during extraction with the -x flag. If the specified output directory already exists as a symlink, cramfsck fails to properly resolve the path before writing files, leading to writes that follow the symlink to arbitrary locations on the filesystem [1][2].

Exploitation

Scenario

The attack requires local access and a crafted pre-condition. An attacker can prepare a repository or firmware bundle containing a symlink (e.g., out -> ~/.ssh/) and a seemingly benign cramfs image. When a victim runs cramfsck -c -x out rootfs.cramfs — a common workflow for extracting potentially corrupted firmware images — the tool logs an error for the failed mkdir(out) call but continues extraction due to -c mode. The subsequent file writes then traverse the symlink, allowing the attacker to place files such as pwn.txt inside the victim's ~/.ssh/ directory or other sensitive locations [1][2].

Impact

Successful exploitation allows a local attacker to write arbitrary files (with the victim's permissions) to locations outside the intended extraction directory. This could lead to unauthorized modification of user configuration files (e.g., SSH authorized_keys) or other sensitive data, depending on the attacker's control over the cramfs image contents and the victim's environment [1][2].

Mitigation

The maintainer has released a fix in commit b4a3a695c9873f824907bd15659f2a6ac7667b4f [4]. The patch introduces a warn_error() function that behaves as die() except under -c mode, where it logs the error and continues. However, critically, it also hardens the extraction path by failing on symlink-related failures or by treating the extraction root symlink as an error that cannot be safely continued. Users are advised to update to the patched version immediately [3][4].

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
b4a3a695c987

cramfsck: make die() actually die; introduce warn_error() for -c mode

https://github.com/npitre/cramfs-toolsNicolas PitreApr 23, 2026via nvd-ref
1 file changed · +41 11
  • cramfsck.c+41 11 modified
    @@ -122,26 +122,50 @@ static void __attribute__((noreturn)) usage(int status)
     	exit(status);
     }
     
    -static void die(int status, int syserr, const char *fmt, ...)
    +static void print_error(int saved_errno, int syserr, const char *fmt, va_list arg_ptr)
     {
    -	va_list arg_ptr;
    -	int save = errno;
    -
     	fflush(0);
    -	va_start(arg_ptr, fmt);
     	fprintf(stderr, "%s: ", progname);
     	vfprintf(stderr, fmt, arg_ptr);
     	if (syserr) {
    -		fprintf(stderr, ": %s", strerror(save));
    +		fprintf(stderr, ": %s", strerror(saved_errno));
     	}
     	fprintf(stderr, "\n");
    +}
    +
    +static void __attribute__((noreturn)) die(int status, int syserr, const char *fmt, ...)
    +{
    +	int save = errno;
    +	va_list arg_ptr;
    +
    +	va_start(arg_ptr, fmt);
    +	print_error(save, syserr, fmt, arg_ptr);
    +	va_end(arg_ptr);
    +	exit(status);
    +}
    +
    +/*
    + * Non-fatal counterpart to die(): under -c (continue-on-error) it logs
    + * the error, folds the status into log_errors_result for the final
    + * exit code, and returns to the caller.  Without -c it behaves the
    + * same as die().  Use this only at sites where it is genuinely safe
    + * to proceed -- typically best-effort metadata updates.  Corruption
    + * checks and filesystem side-effect failures should use die().
    + */
    +static void warn_error(int status, int syserr, const char *fmt, ...)
    +{
    +	int save = errno;
    +	va_list arg_ptr;
    +
    +	va_start(arg_ptr, fmt);
    +	print_error(save, syserr, fmt, arg_ptr);
     	va_end(arg_ptr);
     	if (opt_continue > 0) {
     		log_errors_continue++;
    -        log_errors_result |= status;
    +		log_errors_result |= status;
     	} else {
     		exit(status);
    -    }
    +	}
     }
     
     static void test_super(int *start, size_t *length) {
    @@ -510,22 +534,28 @@ static void change_file_status(char *path, struct cramfs_inode *i)
     {
     	struct utimbuf epoch = { 0, 0 };
     
    +	/*
    +	 * Metadata updates are best-effort: under -c we keep going after
    +	 * a failure (e.g. chown/utime failing when not running as root),
    +	 * which is what continue-on-error mode was introduced for.  The
    +	 * extracted content itself has already been written.
    +	 */
     	if (euid == 0) {
     		if (lchown(path, i->uid, i->gid) < 0) {
    -			die(FSCK_ERROR, 1, "lchown failed: %s", path);
    +			warn_error(FSCK_ERROR, 1, "lchown failed: %s", path);
     		}
     		if (S_ISLNK(i->mode))
     			return;
     		if ((S_ISUID | S_ISGID) & i->mode) {
     			if (chmod(path, i->mode) < 0) {
    -				die(FSCK_ERROR, 1, "chown failed: %s", path);
    +				warn_error(FSCK_ERROR, 1, "chmod failed: %s", path);
     			}
     		}
     	}
     	if (S_ISLNK(i->mode))
     		return;
     	if (utime(path, &epoch) < 0) {
    -		die(FSCK_ERROR, 1, "utime failed: %s", path);
    +		warn_error(FSCK_ERROR, 1, "utime failed: %s", path);
     	}
     }
     
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

6

News mentions

0

No linked articles in our index yet.