Skip to content

Commit

Permalink
src: add --security-revert command line flag
Browse files Browse the repository at this point in the history
The `--security-revert={cvenum}` command line flag is a special purpose
flag to be used only in stable or LTS branches when a breaking change
is required to address a security vulnerability. Whenever a vulnerability
requires a breaking change, and a CVE has been assigned, the flag can
be used to force Node to revert to the insecure behavior that was
implemented before the fix was applied.

Note that this flag is intended to be used only as a last resort in the
case a security update breaks existing code. When used, a security
warning will be printed to stderr when Node launches.

The `--security-revert={cvenum}` flag takes a single CVE number as an
argument. Multiple instances of the `--security-revert={cvenum}` flag
can be used on the command line to revert multiple changes.

Whenever a new `--security-revert={cvenum}` is enabled, it should be
documented in the release notes and in the API docs.

Master and the first release of a new major (e.g. v6.0) should not have
any reverts available.

Every time a new `--security-revert={cvenum}` is added, there should be
a semver-minor bump in the stable and LTS branch.

PR-URL: nodejs-private/node-private#20
  • Loading branch information
jasnell committed Feb 9, 2016
1 parent 1c4ea61 commit da3750f
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
'src/node_javascript.cc',
'src/node_main.cc',
'src/node_os.cc',
'src/node_revert.cc',
'src/node_util.cc',
'src/node_v8.cc',
'src/node_stat_watcher.cc',
Expand Down Expand Up @@ -156,6 +157,7 @@
'src/node_version.h',
'src/node_watchdog.h',
'src/node_wrap.h',
'src/node_revert.h',
'src/node_i18n.h',
'src/pipe_wrap.h',
'src/tty_wrap.h',
Expand Down
14 changes: 14 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "node_javascript.h"
#include "node_version.h"
#include "node_internals.h"
#include "node_revert.h"

#if defined HAVE_PERFCTR
#include "node_counters.h"
Expand Down Expand Up @@ -2976,6 +2977,16 @@ void SetupProcessObject(Environment* env,
READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
}

// --security-revert flags
#define V(code, _, __) \
do { \
if (IsReverted(REVERT_ ## code)) { \
READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
} \
} while (0);
REVERSIONS(V)
#undef V

size_t exec_path_len = 2 * PATH_MAX;
char* exec_path = new char[exec_path_len];
Local<String> exec_path_value;
Expand Down Expand Up @@ -3339,6 +3350,9 @@ static void ParseArgs(int* argc,
track_heap_objects = true;
} else if (strcmp(arg, "--throw-deprecation") == 0) {
throw_deprecation = true;
} else if (strncmp(arg, "--security-revert=", 18) == 0) {
const char* cve = arg + 18;
Revert(cve);
} else if (strcmp(arg, "--v8-options") == 0) {
new_v8_argv[new_v8_argc] = "--help";
new_v8_argc += 1;
Expand Down
53 changes: 53 additions & 0 deletions src/node_revert.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "node_revert.h"
#include <stdio.h>
#include <string.h>

namespace node {

unsigned int reverted = 0;

const char* RevertMessage(const unsigned int cve) {
#define V(code, label, msg) case REVERT_ ## code: return label ": " msg;
switch (cve) {
REVERSIONS(V)
default:
return "Unknown";
}
#undef V
}

void Revert(const unsigned int cve) {
reverted |= 1 << cve;
printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
}

void Revert(const char* cve) {
#define V(code, label, _) \
do { \
if (strcmp(cve, label) == 0) { \
Revert(REVERT_ ## code); \
return; \
} \
} while (0);
REVERSIONS(V)
#undef V
printf("Error: Attempt to revert an unknown CVE [%s]\n", cve);
exit(12);
}

bool IsReverted(const unsigned int cve) {
return reverted & (1 << cve);
}

bool IsReverted(const char * cve) {
#define V(code, label, _) \
do { \
if (strcmp(cve, label) == 0) \
return IsReverted(REVERT_ ## code); \
} while (0);
REVERSIONS(V)
return false;
#undef V
}

} // namespace node
43 changes: 43 additions & 0 deletions src/node_revert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef SRC_NODE_REVERT_H_
#define SRC_NODE_REVERT_H_

#include "node.h"

/**
* Note that it is expected for this list to vary across specific LTS and
* Stable versions! Only CVE's whose fixes require *breaking* changes within
* a given LTS or Stable may be added to this list, and only with CTC
* consensus.
*
* For *master* this list should always be empty!
*
**/
#define REVERSIONS(XX)
// XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title")

namespace node {

typedef enum {
#define V(code, _, __) REVERT_ ## code,
REVERSIONS(V)
#undef V
} reversions_t;

/* A bit field for tracking the active reverts */
extern unsigned int reverted;

/* Revert the given CVE (see reversions_t enum) */
void Revert(const unsigned int cve);

/* Revert the given CVE by label */
void Revert(const char* cve);

/* true if the CVE has been reverted **/
bool IsReverted(const unsigned int cve);

/* true if the CVE has been reverted **/
bool IsReverted(const char * cve);

} // namespace node

#endif // SRC_NODE_REVERT_H_

0 comments on commit da3750f

Please sign in to comment.