Skip to content

Commit 28a6f6f

Browse files
fix: gate --components-path file execution behind AIRBYTE_ENABLE_UNSAFE_CODE
Co-Authored-By: Daryna Ishchenko <darina.ishchenko17@gmail.com>
1 parent d0e5851 commit 28a6f6f

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

airbyte_cdk/cli/source_declarative_manifest/_run.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
from airbyte_cdk.sources.declarative.concurrent_declarative_source import (
4444
ConcurrentDeclarativeSource,
4545
)
46+
from airbyte_cdk.sources.declarative.parsers.custom_code_compiler import (
47+
AirbyteCustomCodeNotPermittedError,
48+
custom_code_execution_permitted,
49+
)
4650
from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource
4751
from airbyte_cdk.sources.source import TState
4852
from airbyte_cdk.utils.datetime_helpers import ab_datetime_now
@@ -279,10 +283,17 @@ def _parse_manifest_from_file(filepath: str) -> dict[str, Any] | None:
279283

280284

281285
def _register_components_from_file(filepath: str) -> None:
282-
"""Load and register components from a Python file specified in the args."""
286+
"""Load and register components from a Python file specified in the args.
287+
288+
The file is caller-supplied Python that is executed via `exec_module`, so it is
289+
untrusted code and must be gated behind `AIRBYTE_ENABLE_UNSAFE_CODE`.
290+
"""
283291
import importlib.util
284292
import sys
285293

294+
if not custom_code_execution_permitted():
295+
raise AirbyteCustomCodeNotPermittedError
296+
286297
components_path = Path(filepath)
287298

288299
module_name = "components"

unit_tests/source_declarative_manifest/test_source_declarative_w_custom_components.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,34 @@ def _read_fn(*args, **kwargs):
288288
_read_fn()
289289

290290

291-
def test_register_components_from_file(components_file: str) -> None:
292-
"""Test that components can be properly loaded from a file."""
291+
def test_register_components_from_file(
292+
components_file: str,
293+
monkeypatch: pytest.MonkeyPatch,
294+
) -> None:
295+
"""Test that components can be properly loaded from a file when custom code is permitted."""
296+
monkeypatch.setenv(ENV_VAR_ALLOW_CUSTOM_CODE, "true")
297+
293298
# Register the components
294299
_register_components_from_file(components_file)
295300

296301
# Verify the components were loaded correctly
297302
verify_components_loaded()
303+
304+
305+
def test_register_components_from_file_is_gated(
306+
components_file: str,
307+
monkeypatch: pytest.MonkeyPatch,
308+
) -> None:
309+
"""A `--components-path` file is caller-supplied Python executed via `exec_module`.
310+
311+
It must be gated behind `AIRBYTE_ENABLE_UNSAFE_CODE`: with the env var unset the file must
312+
not be executed and the loader must raise `AirbyteCustomCodeNotPermittedError` before any
313+
module-level code runs.
314+
"""
315+
monkeypatch.delenv(ENV_VAR_ALLOW_CUSTOM_CODE, raising=False)
316+
317+
with pytest.raises(AirbyteCustomCodeNotPermittedError):
318+
_register_components_from_file(components_file)
319+
320+
assert "components" not in sys.modules
321+
assert "source_declarative_manifest.components" not in sys.modules

0 commit comments

Comments
 (0)