Coverage Report

Created: 2025-08-03 10:06

/src/node/src/permission/permission.cc
Line
Count
Source (jump to first uncovered line)
1
#include "permission.h"
2
#include "base_object-inl.h"
3
#include "env-inl.h"
4
#include "memory_tracker-inl.h"
5
#include "node.h"
6
#include "node_errors.h"
7
#include "node_external_reference.h"
8
9
#include "v8.h"
10
11
#include <memory>
12
#include <string>
13
#include <vector>
14
15
namespace node {
16
17
using v8::Context;
18
using v8::FunctionCallbackInfo;
19
using v8::Local;
20
using v8::Object;
21
using v8::String;
22
using v8::Value;
23
24
namespace permission {
25
26
namespace {
27
28
// permission.has('fs.in', '/tmp/')
29
// permission.has('fs.in')
30
0
static void Has(const FunctionCallbackInfo<Value>& args) {
31
0
  Environment* env = Environment::GetCurrent(args);
32
0
  v8::Isolate* isolate = env->isolate();
33
0
  CHECK(args[0]->IsString());
34
35
0
  String::Utf8Value utf8_deny_scope(isolate, args[0]);
36
0
  if (*utf8_deny_scope == nullptr) {
37
0
    return;
38
0
  }
39
40
0
  const std::string deny_scope = *utf8_deny_scope;
41
0
  PermissionScope scope = Permission::StringToPermission(deny_scope);
42
0
  if (scope == PermissionScope::kPermissionsRoot) {
43
0
    return args.GetReturnValue().Set(false);
44
0
  }
45
46
0
  if (args.Length() > 1 && !args[1]->IsUndefined()) {
47
0
    String::Utf8Value utf8_arg(isolate, args[1]);
48
0
    if (*utf8_arg == nullptr) {
49
0
      return;
50
0
    }
51
0
    return args.GetReturnValue().Set(
52
0
        env->permission()->is_granted(scope, *utf8_arg));
53
0
  }
54
55
0
  return args.GetReturnValue().Set(env->permission()->is_granted(scope));
56
0
}
57
58
}  // namespace
59
60
#define V(Name, label, _)                                                      \
61
0
  if (perm == PermissionScope::k##Name) return #Name;
62
0
const char* Permission::PermissionToString(const PermissionScope perm) {
63
0
  PERMISSIONS(V)
64
0
  return nullptr;
65
0
}
66
#undef V
67
68
#define V(Name, label, _)                                                      \
69
0
  if (perm == label) return PermissionScope::k##Name;
70
0
PermissionScope Permission::StringToPermission(const std::string& perm) {
71
0
  PERMISSIONS(V)
72
0
  return PermissionScope::kPermissionsRoot;
73
0
}
74
#undef V
75
76
126k
Permission::Permission() : enabled_(false) {
77
126k
  std::shared_ptr<PermissionBase> fs = std::make_shared<FSPermission>();
78
126k
  std::shared_ptr<PermissionBase> child_p =
79
126k
      std::make_shared<ChildProcessPermission>();
80
126k
  std::shared_ptr<PermissionBase> worker_t =
81
126k
      std::make_shared<WorkerPermission>();
82
126k
  std::shared_ptr<PermissionBase> inspector =
83
126k
      std::make_shared<InspectorPermission>();
84
126k
#define V(Name, _, __)                                                         \
85
380k
  nodes_.insert(std::make_pair(PermissionScope::k##Name, fs));
86
380k
  FILESYSTEM_PERMISSIONS(V)
87
126k
#undef V
88
126k
#define V(Name, _, __)                                                         \
89
126k
  nodes_.insert(std::make_pair(PermissionScope::k##Name, child_p));
90
126k
  CHILD_PROCESS_PERMISSIONS(V)
91
126k
#undef V
92
126k
#define V(Name, _, __)                                                         \
93
126k
  nodes_.insert(std::make_pair(PermissionScope::k##Name, worker_t));
94
126k
  WORKER_THREADS_PERMISSIONS(V)
95
126k
#undef V
96
126k
#define V(Name, _, __)                                                         \
97
126k
  nodes_.insert(std::make_pair(PermissionScope::k##Name, inspector));
98
126k
  INSPECTOR_PERMISSIONS(V)
99
126k
#undef V
100
126k
}
101
102
void Permission::ThrowAccessDenied(Environment* env,
103
                                   PermissionScope perm,
104
0
                                   const std::string_view& res) {
105
0
  Local<Value> err = ERR_ACCESS_DENIED(env->isolate());
106
0
  CHECK(err->IsObject());
107
0
  if (err.As<Object>()
108
0
          ->Set(env->context(),
109
0
                env->permission_string(),
110
0
                v8::String::NewFromUtf8(env->isolate(),
111
0
                                        PermissionToString(perm),
112
0
                                        v8::NewStringType::kNormal)
113
0
                    .ToLocalChecked())
114
0
          .IsNothing() ||
115
0
      err.As<Object>()
116
0
          ->Set(env->context(),
117
0
                env->resource_string(),
118
0
                v8::String::NewFromUtf8(env->isolate(),
119
0
                                        std::string(res).c_str(),
120
0
                                        v8::NewStringType::kNormal)
121
0
                    .ToLocalChecked())
122
0
          .IsNothing())
123
0
    return;
124
0
  env->isolate()->ThrowException(err);
125
0
}
126
127
0
void Permission::EnablePermissions() {
128
0
  if (!enabled_) {
129
0
    enabled_ = true;
130
0
  }
131
0
}
132
133
void Permission::Apply(Environment* env,
134
                       const std::vector<std::string>& allow,
135
0
                       PermissionScope scope) {
136
0
  auto permission = nodes_.find(scope);
137
0
  if (permission != nodes_.end()) {
138
0
    permission->second->Apply(env, allow, scope);
139
0
  }
140
0
}
141
142
void Initialize(Local<Object> target,
143
                Local<Value> unused,
144
                Local<Context> context,
145
126k
                void* priv) {
146
126k
  SetMethodNoSideEffect(context, target, "has", Has);
147
148
126k
  target->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen).FromJust();
149
126k
}
150
151
0
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
152
0
  registry->Register(Has);
153
0
}
154
155
}  // namespace permission
156
}  // namespace node
157
158
NODE_BINDING_CONTEXT_AWARE_INTERNAL(permission, node::permission::Initialize)
159
NODE_BINDING_EXTERNAL_REFERENCE(permission,
160
                                node::permission::RegisterExternalReferences)