From 2af04e674d69863a318b311090a89aaae0108fdd Mon Sep 17 00:00:00 2001
From: andy finch <andyfinch7@gmail.com>
Date: Sun, 3 Mar 2019 16:52:41 -0500
Subject: [PATCH] Add write permissions requirement to
 `op_fetch_module_meta_data`. (#1874)

---
 src/compiler.rs |  2 +-
 src/ops.rs      | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/compiler.rs b/src/compiler.rs
index fa86617ce9..716a9bbeae 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -52,7 +52,7 @@ fn lazy_start(parent_state: &Arc<IsolateState>) -> Resource {
   let mut cell = C_RID.lock().unwrap();
   let permissions = DenoPermissions {
     allow_read: AtomicBool::new(true),
-    allow_write: AtomicBool::new(false),
+    allow_write: AtomicBool::new(true),
     allow_env: AtomicBool::new(false),
     allow_net: AtomicBool::new(true),
     allow_run: AtomicBool::new(false),
diff --git a/src/ops.rs b/src/ops.rs
index 92a71e7e23..5535ca1b90 100644
--- a/src/ops.rs
+++ b/src/ops.rs
@@ -374,11 +374,19 @@ fn op_fetch_module_meta_data(
   let specifier = inner.specifier().unwrap();
   let referrer = inner.referrer().unwrap();
 
+  // Check for allow read since this operation could be used to read from the file system.
   if !isolate.permissions.allow_read.load(Ordering::SeqCst) {
     debug!("No read permission for fetch_module_meta_data");
     return odd_future(permission_denied());
   }
 
+  // Check for allow write since this operation could be used to write to the file system.
+  if !isolate.permissions.allow_write.load(Ordering::SeqCst) {
+    debug!("No network permission for fetch_module_meta_data");
+    return odd_future(permission_denied());
+  }
+
+  // Check for allow net since this operation could be used to make https/http requests.
   if !isolate.permissions.allow_net.load(Ordering::SeqCst) {
     debug!("No network permission for fetch_module_meta_data");
     return odd_future(permission_denied());
@@ -1843,6 +1851,44 @@ mod tests {
     }
   }
 
+  #[test]
+  fn fetch_module_meta_fails_without_write() {
+    let state = IsolateState::mock();
+    let snapshot = libdeno::deno_buf::empty();
+    let permissions = DenoPermissions {
+      allow_read: AtomicBool::new(true),
+      allow_write: AtomicBool::new(false),
+      allow_env: AtomicBool::new(true),
+      allow_net: AtomicBool::new(true),
+      allow_run: AtomicBool::new(true),
+    };
+    let isolate = Isolate::new(snapshot, state, dispatch, permissions);
+    let builder = &mut FlatBufferBuilder::new();
+    let fetch_msg_args = msg::FetchModuleMetaDataArgs {
+      specifier: Some(builder.create_string("./somefile")),
+      referrer: Some(builder.create_string(".")),
+    };
+    let inner = msg::FetchModuleMetaData::create(builder, &fetch_msg_args);
+    let base_args = msg::BaseArgs {
+      inner: Some(inner.as_union_value()),
+      inner_type: msg::Any::FetchModuleMetaData,
+      ..Default::default()
+    };
+    let base = msg::Base::create(builder, &base_args);
+    msg::finish_base_buffer(builder, base);
+    let data = builder.finished_data();
+    let final_msg = msg::get_root_as_base(&data);
+    let fetch_result = op_fetch_module_meta_data(
+      &isolate,
+      &final_msg,
+      libdeno::deno_buf::empty(),
+    ).wait();
+    match fetch_result {
+      Ok(_) => assert!(true),
+      Err(e) => assert_eq!(e.to_string(), permission_denied().to_string()),
+    }
+  }
+
   #[test]
   fn fetch_module_meta_fails_without_net() {
     let state = IsolateState::mock();
@@ -1887,7 +1933,7 @@ mod tests {
     let snapshot = libdeno::deno_buf::empty();
     let permissions = DenoPermissions {
       allow_read: AtomicBool::new(true),
-      allow_write: AtomicBool::new(false),
+      allow_write: AtomicBool::new(true),
       allow_env: AtomicBool::new(false),
       allow_net: AtomicBool::new(true),
       allow_run: AtomicBool::new(false),