feat: add --allow-import flag (#25469)

This replaces `--allow-net` for import permissions and makes the
security sandbox stricter by also checking permissions for statically
analyzable imports.

By default, this has a value of
`--allow-import=deno.land:443,jsr.io:443,esm.sh:443,raw.githubusercontent.com:443,gist.githubusercontent.com:443`,
but that can be overridden by providing a different set of hosts.

Additionally, when no value is provided, import permissions are inferred
from the CLI arguments so the following works because
`fresh.deno.dev:443` will be added to the list of allowed imports:

```ts
deno run -A -r https://fresh.deno.dev
```

---------

Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
Bartek Iwańczuk 2024-09-26 02:50:54 +01:00 committed by GitHub
parent 05415bb9de
commit 5504acea67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
507 changed files with 1116 additions and 483 deletions

View file

@ -11,7 +11,6 @@ use crate::cache::ModuleInfoCache;
use crate::cache::ParsedSourceCache;
use crate::colors;
use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchPermissionsOption;
use crate::file_fetcher::FileFetcher;
use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
@ -41,6 +40,7 @@ use deno_graph::ResolutionError;
use deno_graph::SpecifierError;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::fs_util::specifier_to_file_path;
use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::package::PackageNv;
@ -249,6 +249,19 @@ impl ModuleGraphCreator {
package_configs: &[JsrPackageConfig],
build_fast_check_graph: bool,
) -> Result<ModuleGraph, AnyError> {
fn graph_has_external_remote(graph: &ModuleGraph) -> bool {
// Earlier on, we marked external non-JSR modules as external.
// If the graph contains any of those, it would cause type checking
// to crash, so since publishing is going to fail anyway, skip type
// checking.
graph.modules().any(|module| match module {
deno_graph::Module::External(external_module) => {
matches!(external_module.specifier.scheme(), "http" | "https")
}
_ => false,
})
}
let mut roots = Vec::new();
for package_config in package_configs {
roots.extend(package_config.config_file.resolve_export_value_urls()?);
@ -262,9 +275,12 @@ impl ModuleGraphCreator {
})
.await?;
self.graph_valid(&graph)?;
if self.options.type_check_mode().is_true() {
if self.options.type_check_mode().is_true()
&& !graph_has_external_remote(&graph)
{
self.type_check_graph(graph.clone()).await?;
}
if build_fast_check_graph {
let fast_check_workspace_members = package_configs
.iter()
@ -279,6 +295,7 @@ impl ModuleGraphCreator {
},
)?;
}
Ok(graph)
}
@ -370,6 +387,7 @@ pub struct ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
}
impl ModuleGraphBuilder {
@ -386,6 +404,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
) -> Self {
Self {
options,
@ -399,6 +418,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter,
file_fetcher,
global_http_cache,
root_permissions_container,
}
}
@ -670,20 +690,26 @@ impl ModuleGraphBuilder {
/// Creates the default loader used for creating a graph.
pub fn create_graph_loader(&self) -> cache::FetchCacher {
self.create_fetch_cacher(FetchPermissionsOption::AllowAll)
self.create_fetch_cacher(self.root_permissions_container.clone())
}
pub fn create_fetch_cacher(
&self,
permissions: FetchPermissionsOption,
permissions: PermissionsContainer,
) -> cache::FetchCacher {
cache::FetchCacher::new(
self.file_fetcher.clone(),
self.options.resolve_file_header_overrides(),
self.global_http_cache.clone(),
self.npm_resolver.clone(),
self.module_info_cache.clone(),
permissions,
cache::FetchCacherOptions {
file_header_overrides: self.options.resolve_file_header_overrides(),
permissions,
is_deno_publish: matches!(
self.options.sub_command(),
crate::args::DenoSubcommand::Publish { .. }
),
},
)
}