diff --git a/docs/introduction/advanced-settings.mdx b/docs/introduction/advanced-settings.mdx index e7297bd38..08f0e5472 100644 --- a/docs/introduction/advanced-settings.mdx +++ b/docs/introduction/advanced-settings.mdx @@ -309,6 +309,19 @@ Controls import path overrides during import resolution. Enables and disables resolution of imports from `sys.path`. + +For this to properly work, you must also set `allow_external` to `True`. + + +## Flag: `allow_external` +> **Default: `False`** + +Enables resolving imports, files, modules, and directories from outside of the repo path. + + +Turning this flag off may allow for bad actors to access files outside of the repo path! Use with caution! + + ## Flag: `ts_dependency_manager` > **Default: `False`** diff --git a/src/codegen/configs/models/codebase.py b/src/codegen/configs/models/codebase.py index b8484e63b..8846d245a 100644 --- a/src/codegen/configs/models/codebase.py +++ b/src/codegen/configs/models/codebase.py @@ -21,6 +21,7 @@ def __init__(self, prefix: str = "CODEBASE", *args, **kwargs) -> None: import_resolution_paths: list[str] = Field(default_factory=lambda: []) import_resolution_overrides: dict[str, str] = Field(default_factory=lambda: {}) py_resolve_syspath: bool = False + allow_external: bool = False ts_dependency_manager: bool = False ts_language_engine: bool = False v8_ts_engine: bool = False diff --git a/src/codegen/sdk/codebase/codebase_context.py b/src/codegen/sdk/codebase/codebase_context.py index 8840adce5..92d441e2f 100644 --- a/src/codegen/sdk/codebase/codebase_context.py +++ b/src/codegen/sdk/codebase/codebase_context.py @@ -381,7 +381,7 @@ def get_directory(self, directory_path: PathLike, create_on_missing: bool = Fals """ # If not part of repo path, return None absolute_path = self.to_absolute(directory_path) - if not self.is_subdir(absolute_path): + if not self.is_subdir(absolute_path) and not self.config.allow_external: assert False, f"Directory {absolute_path} is not part of repo path {self.repo_path}" return None @@ -611,7 +611,7 @@ def get_edges(self) -> list[tuple[NodeId, NodeId, EdgeType, Usage | None]]: def get_file(self, file_path: os.PathLike, ignore_case: bool = False) -> SourceFile | None: # If not part of repo path, return None absolute_path = self.to_absolute(file_path) - if not self.is_subdir(absolute_path): + if not self.is_subdir(absolute_path) and not self.config.allow_external: assert False, f"File {file_path} is not part of the repository path" # Check if file exists in graph diff --git a/src/codegen/sdk/core/codebase.py b/src/codegen/sdk/core/codebase.py index 34d899441..f5b853a6e 100644 --- a/src/codegen/sdk/core/codebase.py +++ b/src/codegen/sdk/core/codebase.py @@ -213,6 +213,13 @@ def __init__( self.ctx = CodebaseContext(projects, config=config, secrets=secrets, io=io, progress=progress) self.console = Console(record=True, soft_wrap=True) + # Assert config assertions + # External import resolution must be enabled if syspath is enabled + if self.ctx.config.py_resolve_syspath: + if not self.ctx.config.allow_external: + msg = "allow_external must be set to True when py_resolve_syspath is enabled" + raise ValueError(msg) + @noapidoc def __str__(self) -> str: return f"" diff --git a/tests/unit/codegen/sdk/python/import_resolution/test_import_resolution.py b/tests/unit/codegen/sdk/python/import_resolution/test_import_resolution.py index ebbe5d724..085b285a9 100644 --- a/tests/unit/codegen/sdk/python/import_resolution/test_import_resolution.py +++ b/tests/unit/codegen/sdk/python/import_resolution/test_import_resolution.py @@ -277,6 +277,8 @@ def func(): # Enable resolution via sys.path codebase.ctx.config.py_resolve_syspath = True + # Allow resolving files and modules outside of the repo path + codebase.ctx.config.allow_external = True # =====[ Imports cannot be found without sys.path being set ]===== assert len(consumer_file.imports) == 1 @@ -372,6 +374,8 @@ def func(): # Ensure we don't have overrites and enable syspath resolution codebase.ctx.config.import_resolution_paths = [] codebase.ctx.config.py_resolve_syspath = True + # Allow resolving files and modules outside of the repo path + codebase.ctx.config.allow_external = True # =====[ Import with sys.path set can be found ]===== assert len(consumer_file.imports) == 1 @@ -419,6 +423,8 @@ def func(): # Ensure we don't have overrites and enable syspath resolution codebase.ctx.config.import_resolution_paths = [] codebase.ctx.config.py_resolve_syspath = True + # Allow resolving files and modules outside of the repo path + codebase.ctx.config.allow_external = True # =====[ Default import works ]===== assert len(consumer_file.imports) == 1