Skip to content

Commit d387591

Browse files
committed
src: add --security-revert command line flag
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#26 Reviewed-By: Rod Vagg <r@va.gg> Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent c3e50ca commit d387591

File tree

4 files changed

+120
-8
lines changed

4 files changed

+120
-8
lines changed

node.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
'src/node_javascript.cc',
133133
'src/node_main.cc',
134134
'src/node_os.cc',
135+
'src/node_revert.cc',
135136
'src/node_util.cc',
136137
'src/node_v8.cc',
137138
'src/node_stat_watcher.cc',
@@ -171,6 +172,7 @@
171172
'src/node_version.h',
172173
'src/node_watchdog.h',
173174
'src/node_wrap.h',
175+
'src/node_revert.h',
174176
'src/node_i18n.h',
175177
'src/pipe_wrap.h',
176178
'src/tty_wrap.h',

src/node.cc

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "node_javascript.h"
77
#include "node_version.h"
88
#include "node_internals.h"
9+
#include "node_revert.h"
910

1011
#if defined HAVE_PERFCTR
1112
#include "node_counters.h"
@@ -1864,7 +1865,6 @@ static gid_t gid_by_name(Isolate* isolate, Local<Value> value) {
18641865
}
18651866
}
18661867

1867-
18681868
static void GetUid(const FunctionCallbackInfo<Value>& args) {
18691869
// uid_t is an uint32_t on all supported platforms.
18701870
args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
@@ -3039,6 +3039,16 @@ void SetupProcessObject(Environment* env,
30393039
READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
30403040
}
30413041

3042+
// --security-revert flags
3043+
#define V(code, _, __) \
3044+
do { \
3045+
if (IsReverted(REVERT_ ## code)) { \
3046+
READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
3047+
} \
3048+
} while (0);
3049+
REVERSIONS(V)
3050+
#undef V
3051+
30423052
size_t exec_path_len = 2 * PATH_MAX;
30433053
char* exec_path = new char[exec_path_len];
30443054
Local<String> exec_path_value;
@@ -3288,19 +3298,19 @@ static void PrintHelp() {
32883298
"\n"
32893299
"Environment variables:\n"
32903300
#ifdef _WIN32
3291-
"NODE_PATH ';'-separated list of directories\n"
3301+
"NODE_PATH ';'-separated list of directories\n"
32923302
#else
3293-
"NODE_PATH ':'-separated list of directories\n"
3303+
"NODE_PATH ':'-separated list of directories\n"
32943304
#endif
3295-
" prefixed to the module search path.\n"
3296-
"NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n"
3305+
" prefixed to the module search path.\n"
3306+
"NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n"
32973307
#if defined(NODE_HAVE_I18N_SUPPORT)
3298-
"NODE_ICU_DATA data path for ICU (Intl object) data\n"
3308+
"NODE_ICU_DATA data path for ICU (Intl object) data\n"
32993309
#if !defined(NODE_HAVE_SMALL_ICU)
3300-
" (will extend linked-in data)\n"
3310+
" (will extend linked-in data)\n"
33013311
#endif
33023312
#endif
3303-
"NODE_REPL_HISTORY path to the persistent REPL history file\n"
3313+
"NODE_REPL_HISTORY path to the persistent REPL history file\n"
33043314
"\n"
33053315
"Documentation can be found at https://nodejs.org/\n");
33063316
}
@@ -3406,6 +3416,9 @@ static void ParseArgs(int* argc,
34063416
track_heap_objects = true;
34073417
} else if (strcmp(arg, "--throw-deprecation") == 0) {
34083418
throw_deprecation = true;
3419+
} else if (strncmp(arg, "--security-revert=", 18) == 0) {
3420+
const char* cve = arg + 18;
3421+
Revert(cve);
34093422
} else if (strcmp(arg, "--prof-process") == 0) {
34103423
prof_process = true;
34113424
short_circuit = true;

src/node_revert.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "node_revert.h"
2+
#include <stdio.h>
3+
#include <string.h>
4+
5+
namespace node {
6+
7+
unsigned int reverted = 0;
8+
9+
const char* RevertMessage(const unsigned int cve) {
10+
#define V(code, label, msg) case REVERT_ ## code: return label ": " msg;
11+
switch (cve) {
12+
REVERSIONS(V)
13+
default:
14+
return "Unknown";
15+
}
16+
#undef V
17+
}
18+
19+
void Revert(const unsigned int cve) {
20+
reverted |= 1 << cve;
21+
printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
22+
}
23+
24+
void Revert(const char* cve) {
25+
#define V(code, label, _) \
26+
do { \
27+
if (strcmp(cve, label) == 0) { \
28+
Revert(REVERT_ ## code); \
29+
return; \
30+
} \
31+
} while (0);
32+
REVERSIONS(V)
33+
#undef V
34+
printf("Error: Attempt to revert an unknown CVE [%s]\n", cve);
35+
exit(12);
36+
}
37+
38+
bool IsReverted(const unsigned int cve) {
39+
return reverted & (1 << cve);
40+
}
41+
42+
bool IsReverted(const char * cve) {
43+
#define V(code, label, _) \
44+
do { \
45+
if (strcmp(cve, label) == 0) \
46+
return IsReverted(REVERT_ ## code); \
47+
} while (0);
48+
REVERSIONS(V)
49+
return false;
50+
#undef V
51+
}
52+
53+
} // namespace node

src/node_revert.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef SRC_NODE_REVERT_H_
2+
#define SRC_NODE_REVERT_H_
3+
4+
#include "node.h"
5+
6+
/**
7+
* Note that it is expected for this list to vary across specific LTS and
8+
* Stable versions! Only CVE's whose fixes require *breaking* changes within
9+
* a given LTS or Stable may be added to this list, and only with CTC
10+
* consensus.
11+
*
12+
* For *master* this list should always be empty!
13+
*
14+
**/
15+
#define REVERSIONS(XX)
16+
// XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title")
17+
18+
namespace node {
19+
20+
typedef enum {
21+
#define V(code, _, __) REVERT_ ## code,
22+
REVERSIONS(V)
23+
#undef V
24+
} reversions_t;
25+
26+
27+
/* A bit field for tracking the active reverts */
28+
extern unsigned int reverted;
29+
30+
/* Revert the given CVE (see reversions_t enum) */
31+
void Revert(const unsigned int cve);
32+
33+
/* Revert the given CVE by label */
34+
void Revert(const char* cve);
35+
36+
/* true if the CVE has been reverted **/
37+
bool IsReverted(const unsigned int cve);
38+
39+
/* true if the CVE has been reverted **/
40+
bool IsReverted(const char * cve);
41+
42+
} // namespace node
43+
44+
#endif // SRC_NODE_REVERT_H_

0 commit comments

Comments
 (0)