CodeQL documentation

Potential file system race condition

ID: js/file-system-race
Kind: problem
Security severity: 7.7
Severity: warning
Precision: medium
Tags:
   - security
   - external/cwe/cwe-367
Query suites:
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

Click to see the query in the CodeQL repository

Often it is necessary to check the state of a file before using it. These checks usually take a file name to be checked, and if the check returns positively, then the file is opened or otherwise operated upon.

However, in the time between the check and the operation, the underlying file referenced by the file name could be changed by an attacker, causing unexpected behavior.

Recommendation

Use file descriptors instead of file names whenever possible.

Example

The following example shows a case where the code checks whether a file inside the /tmp/ folder exists, and if it doesn’t, the file is written to that location.

const fs = require("fs");
const os = require("os");
const path = require("path");

const filePath = path.join(os.tmpdir(), "my-temp-file.txt");

if (!fs.existsSync(filePath)) {
  fs.writeFileSync(filePath, "Hello", { mode: 0o600 });
}

However, in a multi-user environment the file might be created by another user between the existence check and the write.

This can be avoided by using fs.open to get a file descriptor, and then use that file descriptor in the write operation.

const fs = require("fs");
const os = require("os");
const path = require("path");

const filePath = path.join(os.tmpdir(), "my-temp-file.txt");

try {
  const fd = fs.openSync(filePath, fs.O_CREAT | fs.O_EXCL | fs.O_RDWR, 0o600);

  fs.writeFileSync(fd, "Hello");
} catch (e) {
  // file existed
}

References

  • © GitHub, Inc.
  • Terms
  • Privacy