Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript: Improve qhelp for js/server-crash. #13755

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

max-schaefer
Copy link
Collaborator

The examples now use fs.access instead of the deprecated fs.exists. I have also rewritten the async/await example, since as of Node.js v15 the default behaviour for uncaught exceptions has changed to terminating the process instead of logging a warning, making the previous advice incorrect.

The examples now use `fs.access` instead of the deprecated `fs.exists`. I have also rewritten the async/await example, since as of Node.js v15 the default behaviour for uncaught exceptions has changed to terminating the process instead of logging a warning, making the previous advice incorrect.
@github-actions
Copy link
Contributor

QHelp previews:

javascript/ql/src/Security/CWE-730/ServerCrash.qhelp

Server crash

Servers handle requests from clients until terminated deliberately by a server administrator. A client request that results in an uncaught server-side exception causes the current server response generation to fail, and should not have an effect on subsequent client requests.

Under some circumstances, uncaught exceptions can however cause the entire server to terminate abruptly. Such a behavior is highly undesirable, especially if it gives malicious users the ability to turn off the server at will, which is an efficient denial-of-service attack.

Recommendation

Ensure that the processing of client requests can not cause uncaught exceptions to terminate the entire server abruptly.

Example

The following server code checks if a client-provided file path is valid before saving data to it. It would be reasonable to expect that the server responds with an error response to client requests with invalid file paths. However, the server instead throws an exception, which is uncaught in the context of the asynchronous callback invocation (fs.access(...)). This causes the entire server to terminate abruptly.

const express = require("express"),
  fs = require("fs");

function save(rootDir, path, content) {
  if (!isValidPath(rootDir, req.query.filePath)) {
    throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server
  }
  // write content to disk
}

express().post("/save", (req, res) => {
  fs.access(rootDir, (err) => {
    if (err) {
      console.error(
        `Server setup is corrupted, ${rootDir} cannot be accessed!`
      );
      res.status(500);
      res.end();
      return;
    }
    save(rootDir, req.query.path, req.body);
    res.status(200);
    res.end();
  });
});

To remedy this, the server can catch the exception explicitly with a try/catch block, and generate an appropriate error response instead:

// ...
express().post("/save", (req, res) => {
  fs.access(rootDir, (err) => {
    // ...
    try {
      save(rootDir, req.query.path, req.body); // GOOD exception is caught below
      res.status(200);
      res.end();
    } catch (e) {
      res.status(500);
      res.end();
    }
  });
});

To simplify exception handling, it may be advisable to switch to async/await syntax instead of using callbacks, which allows wrapping the entire request handler in a try/catch block:

// ...
express().post("/save", async (req, res) => {
  try {
    await fs.promises.access(rootDir);
    save(rootDir, req.query.path, req.body); // GOOD exception is caught below
    res.status(200);
    res.end();
  } catch (e) {
    res.status(500);
    res.end();
  }
});

References

  • Common Weakness Enumeration: CWE-248.
  • Common Weakness Enumeration: CWE-730.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant