Zennoxa Shield
Rules / C/C++
SHIELD-CPP-018

TOCTOU race with access then open

mediumC/C++CWE-367CVSS 6.3

What it detects

Checking permissions with access before open creates a time-of-check to time-of-use race.

How to fix

Open the file first and check permissions on the resulting descriptor with fstat.

Vulnerable — Shield flags thisspool.c
#include <unistd.h>
#include <fcntl.h>

int open_spool(void) {
    if (access("/var/spool/report.out", W_OK) != 0)   /* check */
        return -1;
    /* window here: the file can be swapped for a symlink */
    return open("/var/spool/report.out", O_WRONLY);   /* use */
}
Fixed — scans cleanspool.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int open_spool(void) {
    int fd = open("/var/spool/report.out", O_WRONLY | O_NOFOLLOW);
    if (fd < 0)
        return -1;
    struct stat st;                 /* check the opened descriptor */
    if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) {
        close(fd);
        return -1;
    }
    return fd;
}

Both snippets are verified against the shipped scanner: the vulnerable one triggers SHIELD-CPP-018, the fixed one does not.

SHIELD-CPP-018: TOCTOU race with access then open — Zennoxa Shield