|
55 | 55 | # Using importlib.metadata avoids importing the SDK itself at module load time. |
56 | 56 | # Contract: sdk-boundary.md MUST:5 |
57 | 57 | # |
58 | | -# TESTING: Set SKIP_SDK_CHECK=1 to allow test imports without SDK installed. |
59 | | -# Tests use pytest.importorskip() and skip markers to handle SDK availability. |
| 58 | +# P1-6 Security Fix: SDK check bypass only allowed in pytest context. |
| 59 | +# The env var alone is not sufficient - pytest must be loaded in sys.modules. |
| 60 | +# This prevents production misuse while preserving test functionality. |
60 | 61 | import asyncio |
61 | 62 | import os as _os |
| 63 | +import sys as _sys |
62 | 64 | import threading |
63 | 65 | from importlib.metadata import PackageNotFoundError as _PkgNotFoundError |
64 | 66 | from importlib.metadata import version as _pkg_version |
65 | 67 |
|
66 | | -if not _os.environ.get("SKIP_SDK_CHECK"): |
| 68 | + |
| 69 | +def _is_pytest_running() -> bool: |
| 70 | + """Check if pytest is running (for test-only SDK check bypass).""" |
| 71 | + return "pytest" in _sys.modules |
| 72 | + |
| 73 | + |
| 74 | +# Only skip SDK check if BOTH conditions are met: |
| 75 | +# 1. SKIP_SDK_CHECK env var is set |
| 76 | +# 2. pytest is actually running (prevents production misuse) |
| 77 | +_skip_sdk_check = _os.environ.get("SKIP_SDK_CHECK") and _is_pytest_running() |
| 78 | + |
| 79 | +if not _skip_sdk_check: |
67 | 80 | try: |
68 | 81 | _pkg_version("github-copilot-sdk") |
69 | 82 | except _PkgNotFoundError as _e: |
|
72 | 85 | "Install with: pip install 'github-copilot-sdk>=0.2.0,<0.3.0'" |
73 | 86 | ) from _e |
74 | 87 |
|
75 | | -from collections.abc import Awaitable, Callable |
76 | | -from typing import Any |
| 88 | +# E402: These imports are intentionally after SDK check - we verify SDK |
| 89 | +# installation before importing modules that depend on it (Three-Medium). |
| 90 | +from collections.abc import Awaitable, Callable # noqa: E402 |
| 91 | +from typing import Any # noqa: E402 |
77 | 92 |
|
78 | | -from amplifier_core import ModelInfo, ModuleCoordinator, ProviderInfo |
| 93 | +from amplifier_core import ModelInfo, ModuleCoordinator, ProviderInfo # noqa: E402 |
79 | 94 |
|
80 | | -from .provider import GitHubCopilotProvider |
| 95 | +from .provider import GitHubCopilotProvider # noqa: E402 |
81 | 96 |
|
82 | 97 | # Contract: sdk-boundary:Membrane:MUST:1 — import from sdk_adapter package, not submodules |
83 | | -from .sdk_adapter import CopilotClientWrapper |
| 98 | +from .sdk_adapter import CopilotClientWrapper # noqa: E402 |
84 | 99 |
|
85 | 100 | __version__ = "2.0.0" |
86 | 101 |
|
|
0 commit comments