fix(security): contain sandbox paths and output - #931
Conversation
|
Warning Review limit reached
Next review available in: 25 minutes Limit details: You’ve used all 1 included review currently available under your plan. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
📝 WalkthroughWalkthrough샌드박스 명령과 웹 E2E 서비스에 출력·로그 바이트 제한을 추가했습니다. 초과 시 프로세스 그룹을 종료하고 종료 코드 Changes샌드박스 자원 제한
Estimated code review effort: 5 (Critical) | ~100 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review Please review the unchanged exact source head |
|
I will report semantic source findings separately from infrastructure and policy readiness. This review does not approve the pull request.
|
|
@coderabbitai review Please review exact source head |
|
I will treat only exact-head evidence as authoritative. I will keep semantic source findings separate from CI, security, supply-chain, and policy readiness. This review does not approve the draft pull request or infer independent human approval. ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (11)
scripts/ci/bounded_subprocess.py (1)
109-117: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value도달 불가능한 분기가 100% 분기 커버리지 요구와 충돌할 수 있습니다.
validate_output_limit는 최소 한도를MINIMUM_OUTPUT_LIMIT_BYTES(4,096)로 강제합니다.TRUNCATION_MARKER는 그보다 훨씬 짧습니다. 따라서suffix_budget은 검증된 한도에서 항상 양수입니다.if suffix_budget else b""의 거짓 분기는 정상 경로에서 실행되지 않습니다.
scripts/ci/코드에 100% 분기 커버리지를 유지해야 하므로, 이 분기를 직접 호출하는 단위 테스트를 추가하거나 분기를 제거하십시오.As per coding guidelines: "Maintain 100% test coverage and 100% interrogate docstring coverage for code under
scripts/ci/".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/bounded_subprocess.py` around lines 109 - 117, The suffix_budget zero branch in _render_bounded_bytes is unreachable after validate_output_limit enforces MINIMUM_OUTPUT_LIMIT_BYTES. Remove the conditional fallback and construct the suffix using the guaranteed-positive budget, preserving the marker-plus-suffix truncation behavior and 100% branch coverage.Source: Coding guidelines
scripts/ci/sandboxed_verify.py (3)
288-288: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value타입이 확정된 결과에는
getattr기본값이 필요하지 않습니다.
completed는bounded_subprocess.BoundedCompletedProcess입니다. 이 dataclass는output_limited: bool필드를 항상 가집니다.getattr(completed, "output_limited", False)의 기본값은 실행되지 않으며, 나중에 계약이 깨져도 조용히False로 처리합니다.312행의
getattr은 다릅니다. 해당except는 기반 클래스subprocess.TimeoutExpired를 잡고, 그 클래스에는output_limited가 없습니다. 그곳의 기본값은 유지하십시오.♻️ 제안 리팩터
- output_limited = bool(getattr(completed, "output_limited", False)) + output_limited = completed.output_limited🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/sandboxed_verify.py` at line 288, Update the assignment in the completed-process handling path to access the guaranteed output_limited field directly on completed instead of using getattr with a fallback. Leave the getattr usage in the TimeoutExpired exception handler unchanged, since that handler receives a base exception without this field.
159-188: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win구현은 정확합니다. 실행 시점에 생성되는 링크에 대한 한계를 문서화하십시오.
경계 검사 자체는 견고합니다.
os.walk(..., followlinks=False)는 링크된 디렉터리로 내려가지 않으므로candidate.parent의 모든 구성 요소는source_root아래의 실제 디렉터리입니다. 따라서(candidate.parent / target).resolve(strict=False)는 신뢰할 수 있는 기준점에서 시작합니다. 링크 체인도resolve가 중간 링크를 따라가므로 각 링크가 개별적으로 차단됩니다. 절대 링크를 거부하는 결정도 복사본이 원본 체크아웃을 다시 가리키는 경우를 막습니다.한 가지 경계 조건이 남습니다. 이 검증은 명령 실행 전에 한 번만 실행됩니다. 신뢰할 수 없는 검증 명령은 실행 중에 복사본 안에 탈출 심볼릭 링크를 새로 만들고 그것을 따라갈 수 있습니다. 이는 사전 검사로는 막을 수 없는 고유한 한계입니다.
docs/doctoring/sandboxed-verification-symlink-boundary.md에 이 한계를 명시하면 이후 검토자가 이 통제를 실행 시점 봉쇄로 오해하지 않습니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/sandboxed_verify.py` around lines 159 - 188, Document the runtime symlink limitation in docs/doctoring/sandboxed-verification-symlink-boundary.md: explain that validate_repository_symlinks performs only a pre-execution scan, so an untrusted verification command may create and follow an escaping symlink during execution; clarify that this check is not runtime containment.
197-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win심볼릭 링크 거부가 처리되지 않은 예외로 전파됩니다.
validate_repository_symlinks는ValueError를 발생시킵니다.main()의try블록은 이 예외를 처리하지 않습니다.finally의emit_result는 실행되지만exit_code는 초기값 1로 남고, 그다음 예외가main()밖으로 전파됩니다. 호출자는 명확한 종료 코드 대신 traceback을 받습니다.동작은 fail-closed이므로 보안 결함은 아닙니다. 다만 이 PR이 출력 제한에 대해
123을 도입한 방식과 일관되게, 경로 경계 거부에도 명시적 메시지와 안정적인 종료 코드를 부여하십시오. 그러면 방출되는 증거의exit_code가 일반 실패와 경계 거부를 구분합니다.♻️ 제안 리팩터
copied_repo = sandbox / "repo" try: - copied_repo = copy_workspace(Path(args.repo_root), sandbox, args.ignore) + try: + copied_repo = copy_workspace(Path(args.repo_root), sandbox, args.ignore) + except ValueError as error: + print(f"sandboxed-verify: {error}", file=sys.stderr) + exit_code = PATH_BOUNDARY_EXIT_CODE + return exit_code env = scrubbed_env(sandbox, args.allow_env)
PATH_BOUNDARY_EXIT_CODE는123,124,125와 충돌하지 않는 값으로 정의하고, 해당 값을docs/doctoring/sandboxed-verification-symlink-boundary.md와CHANGELOG.md에 기록하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/sandboxed_verify.py` around lines 197 - 198, Handle the ValueError raised by validate_repository_symlinks within main() so it does not escape after emit_result; emit an explicit path-boundary rejection message and set a dedicated stable PATH_BOUNDARY_EXIT_CODE distinct from 123, 124, and 125. Ensure the emitted evidence records that code while preserving the existing general-failure behavior, and document the new code in the specified symlink-boundary guide and CHANGELOG.md.tests/test_bounded_subprocess_contract.py (1)
26-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value전역
os모듈에서killpg를 삭제하면 같은 프로세스의 다른 테스트에 영향을 줄 수 있습니다.
bounded.os는 표준 라이브러리os모듈 자체입니다.monkeypatch.delattr(bounded.os, "killpg")는 테스트 동안os.killpg를 프로세스 전역에서 제거합니다.bounded_subprocess의 drain 스레드는 데몬 스레드이고 오버플로 시kill_process_group을 통해os.killpg를 호출합니다. 이전 테스트에서 남은 데몬 스레드가 이 구간에서 실행되면AttributeError가 발생합니다.
hasattr검사를 모듈 수준 헬퍼로 감싸고 그 헬퍼를 패치하면 전역 변경 없이 같은 fail-closed 경로를 검증할 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_bounded_subprocess_contract.py` around lines 26 - 32, Update test_supported_platform_requires_posix_killpg and the platform-support check to use a module-level helper that reports whether os.killpg is available, then monkeypatch that helper to return false instead of deleting killpg from the global os module. Preserve the expected OutputLimitUnsupportedError fail-closed behavior.tests/test_sandboxed_web_e2e_branch_contract.py (1)
112-122: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win정확한 경계값 4096에 대한 어서션을 추가하십시오.
현재 테스트는 4바이트와 4097바이트만 검증합니다.
service_output_limited는st_size > log_limit_bytes를 사용합니다. 비교 연산자가>=로 바뀌어도 이 테스트는 통과합니다. 정확히 한도와 같은 크기를 추가하면 off-by-one 회귀를 잡습니다.♻️ 제안 보강
service.log_path.write_bytes(b"safe") assert not sandboxed_web_e2e.service_output_limited(service) + service.log_path.write_bytes(b"x" * 4096) + assert not sandboxed_web_e2e.service_output_limited(service) service.log_path.write_bytes(b"x" * 4097) assert sandboxed_web_e2e.service_output_limited(service)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_sandboxed_web_e2e_branch_contract.py` around lines 112 - 122, Extend test_service_limit_fallback_handles_missing_small_and_large_files to write exactly 4096 bytes and assert service_output_limited(service) is false, while preserving the existing checks for smaller and larger files.scripts/ci/sandboxed_web_e2e.py (2)
253-265: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value
max_lines검증을 파일 존재 검사보다 먼저 수행하십시오.현재
path.exists()가 False이면max_lines검증을 건너뜁니다. 그 결과tail_text(missing_path, max_lines=0)은 예외 없이 빈 문자열을 반환합니다. 같은 잘못된 입력이 파일 존재 여부에 따라 다르게 처리됩니다. 인자 검증을 함수 시작부로 옮기면 계약이 일관됩니다.♻️ 제안 리팩터
def tail_text( path: Path, max_lines: int = 80, max_bytes: int = DEFAULT_TAIL_BYTES, ) -> str: """Return final lines after a byte-bounded service evidence read.""" - if not path.exists(): - return "" if max_lines <= 0: raise ValueError("max_lines must be positive") + if not path.exists(): + return "" bounded_text = bounded_subprocess.read_bounded_suffix(path, max_bytes)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/sandboxed_web_e2e.py` around lines 253 - 265, Move the max_lines validation in tail_text before the path.exists() check so non-positive values always raise ValueError, including for missing paths. Preserve the existing empty-string result for nonexistent paths with valid arguments.
404-415: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
stop_service실패 후 프로세스 그룹을 강제 종료하십시오.
stop_service가 예외를 던지면 루프는 해당 서비스를 건너뛰고 다음 서비스로 진행합니다. 이때 해당 서비스의 자식 프로세스 그룹은 종료되지 않은 상태로 남을 수 있습니다. 라인 441에서 sandbox 디렉터리는 삭제되지만 프로세스는 계속 실행됩니다. CI 러너에 고아 프로세스가 누적됩니다.예외 경로에서
bounded_subprocess.kill_process_group을 최선 노력으로 한 번 더 호출하면 이 누수가 닫힙니다.♻️ 제안 보강
for service in reversed(services): try: stop_service(service) except (OSError, RuntimeError, subprocess.SubprocessError): + with contextlib.suppress(OSError, subprocess.SubprocessError): + bounded_subprocess.kill_process_group(service.process) output_limited = True if exit_code != 124: exit_code = bounded_subprocess.OUTPUT_LIMIT_EXIT_CODE print( "sandboxed-web-e2e: bounded service capture failed", file=sys.stderr, )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/ci/sandboxed_web_e2e.py` around lines 404 - 415, Update the exception path in the finally cleanup loop around stop_service to make a best-effort bounded_subprocess.kill_process_group call for the failed service before continuing to the next service. Preserve the existing exception handling and exit-code behavior, and ensure cleanup errors from the fallback kill do not interrupt cleanup of remaining services.tests/test_sandboxed_verify_output_limits.py (1)
161-179: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value두 CLI 예산 거부 테스트가 for 루프로 여러 케이스를 검증합니다. 공통 근본 원인은 파라미터화 대신 루프를 사용한 점입니다. 루프에서는 첫 케이스가 실패하면 나머지 케이스가 실행되지 않고, 실패 보고에 어느 값이 문제인지 나타나지 않습니다.
tests/test_sandboxed_verify_output_limits.py#L161-L179:for value in [...]루프를@pytest.mark.parametrize("value", ["4095", str(bounded.MAXIMUM_OUTPUT_LIMIT_BYTES + 1)])로 바꾸고 본문에서 단일 값만 검증하십시오.tests/test_sandboxed_web_e2e_output_limits.py#L241-L264:for option, value in [...]루프를@pytest.mark.parametrize("option, value", [...])로 바꾸고 본문에서 단일(option, value)쌍만 검증하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_sandboxed_verify_output_limits.py` around lines 161 - 179, Replace the loop in tests/test_sandboxed_verify_output_limits.py:161-179 with `@pytest.mark.parametrize`("value", ["4095", str(bounded.MAXIMUM_OUTPUT_LIMIT_BYTES + 1)]) and have the test validate one value per invocation. Also replace the loop in tests/test_sandboxed_web_e2e_output_limits.py:241-264 with `@pytest.mark.parametrize`("option, value", [...]) so each option/value pair runs as a separate test case with clear failure attribution.tests/test_sandboxed_web_e2e_output_limits.py (2)
42-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
4096한도와4097상한 검사가 두 테스트에 리터럴로 중복됩니다. 공통 근본 원인은한도 + 1바이트계약이 이름 없는 리터럴로 표현된 점입니다. 한도를 변경하면 각 테스트에서 두 개의 리터럴을 함께 수정해야 하고, 한쪽만 수정하면 어서션이 조용히 느슨해집니다.
tests/test_sandboxed_web_e2e_output_limits.py#L42-L65: 지역 변수log_limit_bytes = 4096을 도입하고 라인 58의 인자와 라인 62의<= log_limit_bytes + 1검사에 사용하십시오.tests/test_sandboxed_web_e2e_output_limits.py#L267-L301: 같은 지역 변수를 도입하고 라인 289의--service-log-limit-bytes값과 라인 299의<= log_limit_bytes + 1검사에 사용하십시오.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_sandboxed_web_e2e_output_limits.py` around lines 42 - 65, Introduce a local log_limit_bytes = 4096 in test_sandboxed_web_e2e_output_limits.py at lines 42-65 and use it for the start_service limit argument and the <= log_limit_bytes + 1 assertion. Apply the same local variable and substitutions at lines 267-301 for the --service-log-limit-bytes argument and size assertion.
144-175: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win서비스 준비 출력에 대한 동기화 지점이 없습니다. 테스트가 불안정할 수 있습니다.
라인 171과 172는 서비스 로그 tail에
backend-ready와frontend-ready가 나타난다고 단언합니다. 그러나 이 실행은--backend-ready-url과--frontend-ready-url을 지정하지 않습니다. 따라서wait_for_url은 즉시 True를 반환하고main은 곧바로 E2E 명령을 실행한 뒤 정리 단계로 진입합니다.서비스 자식은 별도의 Python 인터프리터입니다. 부하가 높은 러너에서 인터프리터 시작이 늦어지면
stop_service가 SIGTERM을 보냅니다. 그 경우 로그가 비어 있고 어서션이 실패합니다.준비 URL을 사용하거나, 서비스가 준비 표시를 기록할 때까지 로그 파일을 폴링하면 이 경쟁 조건이 제거됩니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_sandboxed_web_e2e_output_limits.py` around lines 144 - 175, Update test_normal_services_and_e2e_preserve_existing_success_contract to synchronize service startup before running the E2E command: either provide reachable --backend-ready-url and --frontend-ready-url values or poll each service log until backend-ready and frontend-ready are recorded. Preserve the existing success and payload assertions while ensuring both readiness messages are emitted before cleanup can terminate the child processes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 16-17: Under the “### Fixed” section of CHANGELOG.md, add a
changelog entry for the security boundary introduced by
validate_repository_symlinks: reject repository symlinks that resolve outside
the copied verification workspace, including absolute links, causing
verification to fail.
In `@scripts/ci/bounded_subprocess.py`:
- Around line 322-341: Update _cleanup_capture_startup_failure to close only
streams not owned by successfully started captures, rather than closing every
stream in streams while reader threads may still be active. Use each
BoundedOutputCapture’s stream ownership (adding a read-only stream property if
needed) to exclude captured streams from the close loop, while preserving the
existing cleanup and join behavior.
In `@scripts/ci/sandboxed_verify.py`:
- Around line 298-304: In main(), stop setting output_limited for the
OutputLimitUnsupportedError path because this exception indicates platform
capability failure, not an output-budget breach. Initialize
output_limit_unsupported to False, set it to True in that exception handler, and
pass it to emit_result under a separate evidence field while preserving the
existing fail-closed exit code.
In `@tests/test_sandboxed_verify_symlink_boundary.py`:
- Around line 64-82: 보이지 않는 증거 방출을 검증하도록
test_timeout_without_partial_streams_still_emits_failed_evidence를 수정하십시오.
capsys로 SANDBOXED_VERIFY_RESULT 출력 행을 읽고 JSON으로 파싱한 뒤, 실패 결과 페이로드의 구조와
output_limit_bytes 및 output_limited 필드를 포함한 정확한 값을 단언하십시오. 이를 위해 json을 import하고
기존 반환 코드 124 단언은 유지하십시오.
---
Nitpick comments:
In `@scripts/ci/bounded_subprocess.py`:
- Around line 109-117: The suffix_budget zero branch in _render_bounded_bytes is
unreachable after validate_output_limit enforces MINIMUM_OUTPUT_LIMIT_BYTES.
Remove the conditional fallback and construct the suffix using the
guaranteed-positive budget, preserving the marker-plus-suffix truncation
behavior and 100% branch coverage.
In `@scripts/ci/sandboxed_verify.py`:
- Line 288: Update the assignment in the completed-process handling path to
access the guaranteed output_limited field directly on completed instead of
using getattr with a fallback. Leave the getattr usage in the TimeoutExpired
exception handler unchanged, since that handler receives a base exception
without this field.
- Around line 159-188: Document the runtime symlink limitation in
docs/doctoring/sandboxed-verification-symlink-boundary.md: explain that
validate_repository_symlinks performs only a pre-execution scan, so an untrusted
verification command may create and follow an escaping symlink during execution;
clarify that this check is not runtime containment.
- Around line 197-198: Handle the ValueError raised by
validate_repository_symlinks within main() so it does not escape after
emit_result; emit an explicit path-boundary rejection message and set a
dedicated stable PATH_BOUNDARY_EXIT_CODE distinct from 123, 124, and 125. Ensure
the emitted evidence records that code while preserving the existing
general-failure behavior, and document the new code in the specified
symlink-boundary guide and CHANGELOG.md.
In `@scripts/ci/sandboxed_web_e2e.py`:
- Around line 253-265: Move the max_lines validation in tail_text before the
path.exists() check so non-positive values always raise ValueError, including
for missing paths. Preserve the existing empty-string result for nonexistent
paths with valid arguments.
- Around line 404-415: Update the exception path in the finally cleanup loop
around stop_service to make a best-effort bounded_subprocess.kill_process_group
call for the failed service before continuing to the next service. Preserve the
existing exception handling and exit-code behavior, and ensure cleanup errors
from the fallback kill do not interrupt cleanup of remaining services.
In `@tests/test_bounded_subprocess_contract.py`:
- Around line 26-32: Update test_supported_platform_requires_posix_killpg and
the platform-support check to use a module-level helper that reports whether
os.killpg is available, then monkeypatch that helper to return false instead of
deleting killpg from the global os module. Preserve the expected
OutputLimitUnsupportedError fail-closed behavior.
In `@tests/test_sandboxed_verify_output_limits.py`:
- Around line 161-179: Replace the loop in
tests/test_sandboxed_verify_output_limits.py:161-179 with
`@pytest.mark.parametrize`("value", ["4095",
str(bounded.MAXIMUM_OUTPUT_LIMIT_BYTES + 1)]) and have the test validate one
value per invocation. Also replace the loop in
tests/test_sandboxed_web_e2e_output_limits.py:241-264 with
`@pytest.mark.parametrize`("option, value", [...]) so each option/value pair runs
as a separate test case with clear failure attribution.
In `@tests/test_sandboxed_web_e2e_branch_contract.py`:
- Around line 112-122: Extend
test_service_limit_fallback_handles_missing_small_and_large_files to write
exactly 4096 bytes and assert service_output_limited(service) is false, while
preserving the existing checks for smaller and larger files.
In `@tests/test_sandboxed_web_e2e_output_limits.py`:
- Around line 42-65: Introduce a local log_limit_bytes = 4096 in
test_sandboxed_web_e2e_output_limits.py at lines 42-65 and use it for the
start_service limit argument and the <= log_limit_bytes + 1 assertion. Apply the
same local variable and substitutions at lines 267-301 for the
--service-log-limit-bytes argument and size assertion.
- Around line 144-175: Update
test_normal_services_and_e2e_preserve_existing_success_contract to synchronize
service startup before running the E2E command: either provide reachable
--backend-ready-url and --frontend-ready-url values or poll each service log
until backend-ready and frontend-ready are recorded. Preserve the existing
success and payload assertions while ensuring both readiness messages are
emitted before cleanup can terminate the child processes.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 01f67cd3-3b3c-4a93-9c08-53fb8c91dc3e
📒 Files selected for processing (17)
CHANGELOG.mddocs/doctoring/sandboxed-output-resource-bounds.mddocs/doctoring/sandboxed-verification-symlink-boundary.mdscripts/ci/bounded_subprocess.pyscripts/ci/sandboxed_verify.pyscripts/ci/sandboxed_web_e2e.pytests/test_bounded_subprocess.pytests/test_bounded_subprocess_capture_startup.pytests/test_bounded_subprocess_contract.pytests/test_repository_branch_coverage_execution_sandboxes.pytests/test_sandboxed_entrypoint_and_cleanup_coverage.pytests/test_sandboxed_service_capture_startup.pytests/test_sandboxed_verify_output_limits.pytests/test_sandboxed_verify_symlink_boundary.pytests/test_sandboxed_web_e2e.pytests/test_sandboxed_web_e2e_branch_contract.pytests/test_sandboxed_web_e2e_output_limits.py
|
@coderabbitai review Re-evaluate exact current head |
|
I will evaluate this head independently. I will keep semantic source findings separate from workflow and policy status. This review does not infer independent human approval or merge authority.
|
|
@opencode-agent review Evaluate exact current head |
|
@coderabbitai review Review exact current head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
target='dd2132b5aedc56859ffa81568d42ab9e81e52b65'
repo='ContextualWisdomLab/.github'
printf '%s\n' '== Local commit and diff scope =='
git rev-parse HEAD
git cat-file -t "$target"
git merge-base "$target" origin/main
git diff --name-status "$(git merge-base "$target" origin/main)" "$target"
git diff --stat "$(git merge-base "$target" origin/main)" "$target"
printf '%s\n' '== Production module outlines =='
for f in scripts/ci/bounded_subprocess.py scripts/ci/sandboxed_verify.py scripts/ci/sandboxed_web_e2e.py; do
if test -f "$f"; then
printf '\n-- %s --\n' "$f"
ast-grep outline "$f" --items all --view expanded || true
fi
done
printf '%s\n' '== Focused test module outlines =='
fd -t f '^test_(bounded_subprocess|sandboxed_verify|sandboxed_web_e2e|sandboxed_service_capture_startup|sandboxed_entrypoint_and_cleanup_coverage)' tests \
-x sh -c 'echo "-- $1 --"; ast-grep outline "$1" --items all --view expanded || true' sh {}
printf '%s\n' '== Exact-head GitHub status =='
gh api "repos/$repo/commits/$target/check-runs?per_page=100" \
--jq '.check_runs[] | [.name,.status,.conclusion,.head_sha,.html_url] | `@tsv`' || true
printf '%s\n' '== Pull request metadata and unresolved review-thread count =='
gh pr view 931 --repo "$repo" --json isDraft,headRefOid,baseRefOid,mergeStateStatus,reviewDecision,url \
|| true
gh api graphql -F owner='ContextualWisdomLab' -F name='.github' -F number=931 -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes { isResolved isOutdated comments(first: 1) { nodes { author { login } } } }
}
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length' \
|| trueLength of output: 34043 🏁 Script executed: #!/bin/bash
set -euo pipefail
show() {
file="$1"; start="$2"; end="$3"
printf '\n===== %s:%s-%s =====\n' "$file" "$start" "$end"
sed -n "${start},${end}p" "$file" | nl -ba -v "$start"
}
show scripts/ci/bounded_subprocess.py 1 443
show scripts/ci/sandboxed_verify.py 1 396
show scripts/ci/sandboxed_web_e2e.py 1 520
printf '\n===== Documentation: boundary claims =====\n'
rg -n -C 4 -i 'pre.execution|pre-execution|symlink|absolute|escape|limit|suffix|reader|join|process group|timeout|readiness|exit code|POSIX|limitation' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.md
printf '\n===== Focused semantic-test assertions =====\n'
for f in \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py; do
printf '\n-- %s --\n' "$f"
rg -n -C 2 'assert |raises\(|output_limited|PATH_BOUNDARY|OUTPUT_LIMIT|returncode|exit code|kill|join|symlink|timeout|readiness|unsupported|pre.execution' "$f"
doneLength of output: 1705 🏁 Script executed: #!/bin/bash
set -euo pipefail
show() {
file="$1"; start="$2"; end="$3"
printf '\n===== %s:%s-%s =====\n' "$file" "$start" "$end"
sed -n "${start},${end}p" "$file"
}
show scripts/ci/bounded_subprocess.py 1 443
show scripts/ci/sandboxed_verify.py 1 396
show scripts/ci/sandboxed_web_e2e.py 1 520
printf '\n===== Documentation: boundary claims =====\n'
rg -n -C 4 -i 'pre.execution|pre-execution|symlink|absolute|escape|limit|suffix|reader|join|process group|timeout|readiness|exit code|POSIX|limitation' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.md
printf '\n===== Focused semantic-test assertions =====\n'
for f in \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py; do
printf '\n-- %s --\n' "$f"
rg -n -C 2 'assert |raises\(|output_limited|PATH_BOUNDARY|OUTPUT_LIMIT|returncode|exit code|kill|join|symlink|timeout|readiness|unsupported|pre.execution' "$f"
doneLength of output: 103912 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Path-boundary handlers and result fields =='
rg -n -C 8 'RepositoryPathBoundaryError|path_boundary_rejected|copy_workspace\(' \
scripts/ci/sandboxed_verify.py \
scripts/ci/sandboxed_web_e2e.py \
tests
printf '%s\n' '== Web E2E main exception handling and result payload =='
sed -n '268,396p' scripts/ci/sandboxed_web_e2e.py
printf '%s\n' '== Verify main path-boundary handling and result payload =='
sed -n '232,382p' scripts/ci/sandboxed_verify.py
printf '%s\n' '== Web E2E symlink test candidates =='
rg -n -i -C 3 'symlink|path.boundary|boundary.rejected|exit_code.*126|PATH_BOUNDARY' \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
|| true
printf '%s\n' '== Changed-line attribution for the web E2E wrapper =='
git blame -L 268,396 dd2132b5aedc56859ffa81568d42ab9e81e52b65 -- scripts/ci/sandboxed_web_e2e.pyLength of output: 42799
Semantic finding
Verified controls
Readiness evidenceGitHub reports zero unresolved review threads. The observed current-head checks are terminal and associated with the requested SHA. Successful checks are readiness evidence only. They do not resolve the semantic finding, provide independent human approval, or grant merge authority. 🧠 Learnings usedYou are interacting with an AI system. |
|
@opencode-agent review Review exact current head |
Rate Limit Exceeded
|
|
Exact-current-head review request for Review the complete 17-file sandbox boundary: pre-execution rejection of absolute/repository-escaping symlinks with stable path-boundary evidence; bounded final-suffix stdout/stderr and service logs; POSIX process-group termination and cleanup; output-limit vs unsupported-platform evidence separation; finite reader finalization; exact boundary-size tests; synchronized service startup; and documented runtime symlink limitation. All four actionable CodeRabbit findings and associated nitpicks are addressed and resolved. Trusted uv Materializer Quality CI, Strix Changed Path Quality CI, CodeQL PR, Python Security, Security Scan, SAST Semgrep, Secret Scan, OSV-Scanner PR, Scorecard PR, and SBOM Generation are terminal-success on this exact head. Keep this exact head unchanged. Do not update the branch, synthesize author approval, treat pre-scan as runtime containment, weaken output bounds or process cleanup, merge, release, or bypass protection. @coderabbitai review |
Rate Limit Exceeded
|
|
Exact-current-head automated and independent review requested for Fresh evidence: all directly observed exact-head workflows are terminal-success and all current CodeRabbit findings are resolved. Review the two bounded boundaries: copied workspaces reject absolute or repository-escaping symlinks before execution while explicitly not claiming runtime containment; command/service output is continuously drained into finite final-suffix evidence, process groups are terminated on overflow, persisted logs and tail reads are bounded, reader finalization is finite, and stable exits distinguish resource limit 123, timeout 124, readiness 125, and path boundary 126. Unsupported process-group capability remains fail-closed and separately represented from an actual output overflow. Submit an exact-head verdict without updating the branch, weakening byte/process cleanup budgets, claiming OS/network sandboxing, importing #906 evidence, synthesizing author approval, or bypassing protection. @coderabbitai review |
Rate Limit Exceeded
|
|
Exact-current-head review request for Review the unchanged current tree read-only, verify all security and evidence boundaries, and report only current-head findings. Do not update the branch or bypass the required independent approvals. @opencode-agent review |
|
@opencode-agent review Review exact current head only. Do not merge, mutate credentials, or synthesize author approval. GitHub review/Checks wait is not a blocker for the remaining queue. |
|
Reviewed. Review threads already resolved in source. Added ARCHITECTURE.md and Darwin installer isolation. Local suite 1036 passed x2, coverage 100%. Auto-merge armed. |
There was a problem hiding this comment.
Pull request overview
OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.
Findings
1. HIGH Current-head GitHub Checks - Fix failed required checks before approval
- Problem: Failed same-head checks remain for
27bfd09df8e956dfc03d974a9ccd7bec9c2ed58c. - Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
- Fix: Read and fix the failed check logs below, then rerun the current-head checks.
- Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.
Failed checks:
- Bandit (Python SAST) check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94510134556)
- Close Empty PR/close-empty: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703574/job/94509904414)
- CodeQL PR/Detect CodeQL languages: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703536/job/94509904394)
- Detect CodeQL languages check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703536/job/94509904394)
- Detect Python check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94509904295)
- OSV-Scanner PR/osv-scan / osv-scan: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718704024/job/94509906098)
- Python 3.10 compatibility contract check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703498/job/94509904911)
- Python 3.14 full quality gate check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703498/job/94509904770)
- Python Security/Bandit (Python SAST): CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94510134556)
- Python Security/Detect Python: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94509904295)
- Python Security/pip-audit (Python dependency audit): CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94510134465)
- SAST Semgrep/Semgrep (multi-language SAST): CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703554/job/94509904277)
- SBOM Generation/generate-sbom: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703527/job/94509904786)
- Scorecard PR/Scorecard: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703528/job/94509904485)
- Scorecard check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703528/job/94509904485)
- Secret Scan/gitleaks (secret scan): CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703546/job/94509904381)
- Security Scan/dependency-review: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904375)
- Security Scan/osv-scan: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904620)
- Security Scan/scorecard: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904423)
- Security Scan/trivy-fs: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904378)
- Semgrep (multi-language SAST) check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703554/job/94509904277)
- Strix Changed Path Quality CI/exact-head-path-policy: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703484/job/94509903796)
- Trusted uv Materializer Quality CI/Python 3.10 compatibility contract: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703498/job/94509904911)
- Trusted uv Materializer Quality CI/Python 3.14 full quality gate: CANCELLED (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703498/job/94509904770)
- close-empty check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703574/job/94509904414)
- coverage-source-tree check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703695/job/94510161566)
- dependency-review check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904375)
- exact-head-path-policy check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703484/job/94509903796)
- generate-sbom check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703527/job/94509904786)
- gitleaks (secret scan) check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703546/job/94509904381)
- osv-scan / osv-scan check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718704024/job/94509906098)
- osv-scan check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904620)
- pip-audit (Python dependency audit) check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703537/job/94510134465)
- required-workflow-bootstrap check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703695/job/94509904729)
- scorecard check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904423)
- trivy-fs check run: cancelled (https://github.com/ContextualWisdomLab/.github/actions/runs/31718703490/job/94509904378)
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (4 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (4 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
Evidence --> S3["CI script (4 files)"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script (4 files)"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (12 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (12 files)"]
R4 --> V4["targeted test run"]
OpenCode Review Overview
Pull request overviewOpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed. Findings1. HIGH Current-head GitHub Checks - Fix failed required checks before approval
Failed checks:
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: CHANGELOG.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
Evidence --> S3["CI script (3 files)"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script (3 files)"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (11 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (11 files)"]
R4 --> V4["targeted test run"]
|
|
Returned to Draft because the exact current tree mixes the bounded sandbox execution repair with an unrelated trusted-uv materializer branch. The buyer-visible slice is coherent: copied-workspace symlink containment, bounded stdout/stderr and service-log retention, whole-process-group cleanup, deterministic overflow/timeout/readiness/path exits, and realistic flood regressions. Head Rebuild from protected |
|
@coderabbitai review Review only exact current head |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
target='aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79'
base='6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba'
printf '%s\n' '== Exact source identities and changed paths =='
printf 'HEAD: '; git rev-parse HEAD
printf 'target type: '; git cat-file -t "$target"
printf 'base type: '; git cat-file -t "$base"
printf 'merge-base: '; git merge-base "$target" "$base"
git diff --name-status "$base" "$target"
printf '%s\n' '== Production module outlines =='
for file in scripts/ci/bounded_subprocess.py scripts/ci/sandboxed_verify.py scripts/ci/sandboxed_web_e2e.py; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --view expanded
done
printf '%s\n' '== Boundary implementation references =='
rg -n -C 6 \
'RepositoryPathBoundaryError|validate_repository_symlinks|copy_workspace\(|PATH_BOUNDARY_EXIT_CODE|path_boundary_rejected|run_bounded_command|BoundedOutputCapture|kill_process_group|finalize|join\(|read_bounded_suffix|OUTPUT_LIMIT|TIMEOUT|READINESS' \
scripts/ci/bounded_subprocess.py \
scripts/ci/sandboxed_verify.py \
scripts/ci/sandboxed_web_e2e.py
printf '%s\n' '== Focused regression inventory =='
fd -t f '^test_(bounded_subprocess|sandboxed_verify|sandboxed_web_e2e|sandboxed_service_capture_startup|sandboxed_entrypoint_and_cleanup_coverage)' tests \
-x sh -c 'printf "\n-- %s --\n" "$1"; ast-grep outline "$1" --items all --view compact' sh {}
printf '%s\n' '== Current review thread count and requested-head checks =='
gh pr view 931 --repo ContextualWisdomLab/.github --json headRefOid,baseRefOid,isDraft,mergeStateStatus,url
gh api 'repos/ContextualWisdomLab/.github/commits/aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79/check-runs?per_page=100' \
--jq '.check_runs[] | [.name, .status, .conclusion, .head_sha] | `@tsv`' || true
gh api graphql -F owner='ContextualWisdomLab' -F name='.github' -F number=931 -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) { nodes { isResolved } }
}
}
}' --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length' || trueLength of output: 53671 🏁 Script executed: #!/bin/bash
set -euo pipefail
show() {
local file="$1" start="$2" end="$3"
printf '\n===== %s:%s-%s =====\n' "$file" "$start" "$end"
nl -ba -v "$start" "$file" | sed -n "${start},${end}p"
}
show scripts/ci/bounded_subprocess.py 100 443
show scripts/ci/sandboxed_verify.py 164 356
show scripts/ci/sandboxed_web_e2e.py 129 475
printf '%s\n' '===== Web E2E path-boundary and exit-code regression references ====='
rg -n -i -C 5 \
'RepositoryPathBoundaryError|path_boundary_rejected|PATH_BOUNDARY_EXIT_CODE|symlink|absolute target|escapes repository|exit_code.{0,20}126|return.{0,20}126' \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_sandboxed_verify_symlink_boundary.py
printf '%s\n' '===== Bounded subprocess and service cleanup assertions ====='
rg -n -C 3 \
'join\(|READER_JOIN|capture|startup|kill_process_group|output_limited|TimeoutExpired|returncode|suffix|stored_bytes|truncated' \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py
printf '%s\n' '===== Materializer test delta ====='
git diff --find-renames --unified=80 6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79 -- tests/test_materialize_base_python_requirements.py
printf '%s\n' '===== Documentation limitation statements ====='
rg -n -C 4 -i \
'pre-execution|runtime|not.*contain|does not.*contain|symlink|process group|reader|join|suffix|exit code|123|124|125|126' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.mdLength of output: 2243 🏁 Script executed: #!/bin/bash
set -euo pipefail
show() {
local file="$1" start="$2" end="$3"
printf '\n===== %s:%s-%s =====\n' "$file" "$start" "$end"
cat -n "$file" | sed -n "${start},${end}p"
}
show scripts/ci/bounded_subprocess.py 100 443
show scripts/ci/sandboxed_verify.py 164 356
show scripts/ci/sandboxed_web_e2e.py 129 475
printf '%s\n' '===== Web E2E path-boundary and exit-code regression references ====='
rg -n -i -C 5 \
'RepositoryPathBoundaryError|path_boundary_rejected|PATH_BOUNDARY_EXIT_CODE|symlink|absolute target|escapes repository|exit_code.{0,20}126|return.{0,20}126' \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_sandboxed_verify_symlink_boundary.py || true
printf '%s\n' '===== Bounded subprocess and service cleanup assertions ====='
rg -n -C 3 \
'join\(|READER_JOIN|capture|startup|kill_process_group|output_limited|TimeoutExpired|returncode|suffix|stored_bytes|truncated' \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py
printf '%s\n' '===== Materializer test delta ====='
git diff --find-renames --unified=80 \
6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba \
aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79 \
-- tests/test_materialize_base_python_requirements.py
printf '%s\n' '===== Documentation limitation statements ====='
rg -n -C 4 -i \
'pre-execution|runtime|not.*contain|does not.*contain|symlink|process group|reader|join|suffix|exit code|123|124|125|126' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.mdLength of output: 140970
Semantic findings
Verified controls
Scope note
Readiness and approvalThis is a source review only. The initial check-status query did not complete because the earlier inspection stopped before that section. The user also states that exact-head checks are still regenerating. I do not treat nonterminal checks as acceptance. This review does not grant approval, merge authority, or independent human approval.
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found source-backed failed-check findings that must be addressed before merge.
- Result: REQUEST_CHANGES
- Reason: failed current-head checks were mapped to line-specific findings below for
aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79. - Head SHA:
aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79 - Workflow run: 31819360398
- Workflow attempt: 1
Failed checks
- Strix Security Scan/strix: FAILURE (https://github.com/ContextualWisdomLab/.github/actions/runs/31806061284/job/94785154741)
- Strix Security Scan/strix: failure (https://github.com/ContextualWisdomLab/.github/actions/runs/31806061284/job/94785154741)
Findings
1. HIGH .github/workflows/strix.yml:525 - Strix unsupported-model errors must name the allowed providers
-
Problem: Strix failed because the trusted self-test log reported missing "STRIX_LLM must select NVIDIA NIM Nemotron, GitHub Models openai/gpt-5 or newer, direct OpenAI GPT-5.4 or newer, OpenRouter openrouter/free, or an approved organization Vertex AI model".
-
Root cause: The failed check is executing trusted-base workflow material, so this exact line must exist in the trusted workflow/test contract before the check can pass.
-
Fix: Keep or add the current-head line at ".github/workflows/strix.yml:525" so trusted-base Strix/OpenCode evidence contains "STRIX_LLM must select NVIDIA NIM Nemotron, GitHub Models openai/gpt-5 or newer, direct OpenAI GPT-5.4 or newer, OpenRouter openrouter/free, or an approved organization Vertex AI model".
-
Regression test: Keep scripts/ci/test_strix_quick_gate.sh assertions covering this exact string.
-
Suggested edit: ensure
.github/workflows/strix.yml:525contains the literalSTRIX_LLM must select NVIDIA NIM Nemotron, GitHub Models openai/gpt-5 or newer, direct OpenAI GPT-5.4 or newer, OpenRouter openrouter/free, or an approved organization Vertex AI model; if the line was removed from trusted-base material, restore it exactly before approving.
2. MEDIUM scripts/ci/sandboxed_web_e2e.py:1 - Strix report from nvidia_nim/nvidia/nemotron-3-super-120b-a12b: SSRF in sandboxed_web_e2e.py via backend-ready-url and frontend-ready-url parameters
-
Problem: Strix Security Scan failed and nvidia_nim/nvidia/nemotron-3-super-120b-a12b reported "SSRF in sandboxed_web_e2e.py via backend-ready-url and frontend-ready-url parameters" with severity MEDIUM. Endpoint: /scripts/ci/sandboxed_web_e2e.py. Method: GET. Code location evidence: target/endpoint: /workspace/strix-pr-scope.F19oLv/scripts/ci/sandboxed_web_e2e.py.
-
Root cause: The failed Strix evidence contains a distinct model vulnerability report, so OpenCode must not collapse it into provider-quota or generic check-failure text.
-
Fix: Inspect and patch scripts/ci/sandboxed_web_e2e.py:1 for this exact report before approval; apply the remediation described by Strix for "SSRF in sandboxed_web_e2e.py via backend-ready-url and frontend-ready-url parameters" and keep the review finding tied to this line.
-
Regression test: Add or update coverage that exercises the reported endpoint/path and proves the MEDIUM finding cannot recur.
-
Suggested edit: change
scripts/ci/sandboxed_web_e2e.py:1for theSSRF in sandboxed_web_e2e.py via backend-ready-url and frontend-ready-url parametersreport from modelnvidia_nim/nvidia/nemotron-3-super-120b-a12b; preserve the exact endpoint/scripts/ci/sandboxed_web_e2e.py, methodGET, and Code Location evidencetarget/endpoint: /workspace/strix-pr-scope.F19oLv/scripts/ci/sandboxed_web_e2e.pyin the OpenCode review finding.
3. HIGH .github/workflows/strix.yml:810 - Strix provider signal left current-head security evidence incomplete
-
Problem: Strix produced one or more vulnerability report windows that did not map to an existing repository file, then the failed log reported provider infrastructure/failure-signal output such as LLM CONNECTION FAILED, RateLimitError, budget-limit, "Below-threshold findings detected", "Unable to map Strix findings", or fallback provider signal. Unmapped reports: nvidia_nim/nvidia/nemotron-3-super-120b-a12b reported "SSRF in sandboxed_web_e2e.py via backend-ready-url and frontend-ready-url arguments" (MEDIUM; Strix report did not include a mappable Code Location).
-
Root cause: The scanner evidence is incomplete even after model reports were emitted; unmapped or provider-failed Strix reports are scanner evidence blockers, not source-backed code review findings. OpenCode must not anchor a report to an unrelated workflow line unless the report includes a mappable repository Code Location.
-
Fix: Re-run Strix after GitHub Models capacity recovers or run an explicitly configured manual provider evidence scan with valid credentials; keep .github/workflows/strix.yml:810 aligned with the approved fallback model list.
-
Regression test: Keep failed-check evidence and validation covering provider-signal failures after vulnerability reports, including unmapped/nonexistent Code Locations, so partial reports cannot be downgraded to approval or converted into hallucinated source fixes.
-
Suggested edit: do not change unrelated source lines for unmapped reports; first obtain a clean Strix rerun or a report with a repository Code Location, while keeping
.github/workflows/strix.yml:810on the approved GitHub Models fallback route.
Failed check evidence for line-specific fixes
Failed GitHub Check Evidence
- PR: #931
- Head SHA:
aa9192895cb89f85fb0bd8fd7c8fde0250f4fc79 - Repository:
ContextualWisdomLab/.github
Line-specific repair contract
-
Treat the check logs and annotations below as diagnostic evidence, not as a complete review.
-
For each actionable failed check, inspect the local source or diff and identify the exact file line that must change.
-
OpenCode
REQUEST_CHANGESfindings must includepath,line,root_cause,fix_direction,regression_test_direction, andsuggested_diff. -
Do not request changes with only a GitHub Actions URL or a generic check name.
-
When Strix logs contain multiple
Vulnerability ReportorModel ... Vulnerabilities ...sections, include every model-reported vulnerability in the review evidence and findings, including model name, title, severity, endpoint, and Code Locations/path:line evidence when present. -
Create one OpenCode finding per Strix model vulnerability report; do not satisfy two model reports with one combined finding, even when titles or locations match.
Failed check: Strix Security Scan/strix
- Type:
check_run - Conclusion:
FAILURE - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31806061284/job/94785154741
- Workflow run id:
31806061284 - Check run id:
94785154741
Failed job steps
- step 26: Run Strix (quick) (failure)
Check annotations
- .github:966-966 [failure] Process completed with exit code 1.
Failed log signal summary
strix UNKNOWN STEP 2026-08-14T14:24:56.9252895Z [command]/usr/bin/tar xz --warning=no-unknown-keyword --overwrite -C /home/runner/work/_temp/c578d995-87a2-4798-a111-437b83c4e8d9 -f /home/runner/work/_temp/a172ab9a-064e-4117-8dee-9104e53cf1a7
strix UNKNOWN STEP 2026-08-14T14:25:01.7979714Z ^[[36;1m print(f"::error::Could not parse GitHub workflow context JSON: {exc}", file=sys.stderr)^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:01.7986550Z ^[[36;1m print("::error::Trusted workflow repository resolved to an invalid name.", file=sys.stderr)^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:01.7988377Z ^[[36;1m print("::error::Trusted workflow ref resolved to an invalid value.", file=sys.stderr)^[[0m
strix UNKNOWN STEP "body": "## Buyer and security outcome\n\nThis Ready change closes two repository-owned availability and filesystem boundaries in the central sandbox wrappers without weakening execution, review, or merge policy:\n\n1. copied verification workspaces reject absolute and repository-escaping symlink targets before an untrusted command runs; and\n2. short-lived command streams plus long-running backend/frontend logs are continuously drained into explicit bounded final-suffix evidence.\n\nIssue #766 remains open until protected integration and protected-main operational acceptance. The separately reviewed credential-redaction line in #906 is not claimed as shipped or bundled here.\n\n## Exact identity\n\n- source head: `dd2132b5aedc56859ffa81568d42ab9e81e52b65`\n- PR-base snapshot: `6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba`\n- independently resolved live `main` tip: `6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba`\n- ancestry: ahead 15, behind 0; merge base equals live main\n\nNo predecessor-head, synthetic merge revision, queued workflow, status-only result, automated model result, or author action transfers to this head.\n\n## Symlink containment\n\n`copy_workspace` validates the exact copied tree after ignore rules are applied. Absolute links and relative links resolving outside the copied repository fail closed. Internal relative links remain links; ignored paths do not create false positives. This is filesystem containment, not an operating-system or network sandbox claim.\n\nThe original RED commit was `faca1f145f237ce7b561218d707a40ae33471b88`; the ignored-path regression was preserved at `6f597306a7414e4ab027af42c8d8672f8da8de39`.\n\n## Output-resource RCA and remedy\n\nThe first failing boundary was retention: `subprocess.run(..., stdout=PIPE, stderr=PIPE)` buffered complete short-lived streams in parent memory, services wrote ordinary unbounded log files, and `tail_text()` read complete files before selecting final lines.\n\nRejected remedies:\n\n- process-wide `RLIMIT_FSIZE`, because it would also cap legitimate coverage databases, build artifacts, archives, and application files;\n- truncating only after `communicate()` or `read_text()`, because exhaustion occurs before that boundary;\n- retaining only the beginning of output, because terminal diagnostic suffixes are more useful;\n- non-POSIX silent fallback without process-group authority.\n\nImplemented:\n\n- reusable `bounded_subprocess.py` with one binary reader thread per pipe, locked final-suffix buffers, one overflow transition, and finite 30-second reader joins;\n- 1 MiB default per stdout/stderr stream, 4 MiB per combined service log, and validation from 4 KiB through 64 MiB;\n- `shell=False`, structured argv, `start_new_session=True`, and whole-process-group termination on the first overflowing stream;\n- stable resource exit `123`, timeout `124`, and readiness `125`, with timeout retaining precedence;\n- bounded persisted service evidence and a 64 KiB seek-from-end tail read;\n- explicit fail-closed behavior when POSIX process-group termination is unavailable;\n- stable copied-workspace path-boundary exit `126` with non-sensitive `path_boundary_rejected` evidence;\n- forced process-group kill and bounded reap if orderly service capture finalization raises.\n\nThe test-only RED head `b4547a55a732f3f2f6b64e5924bca11e10871599` failed collection because the bounded runner did not exist. GREEN is the exact current head.\n\n## Exact local proof\n\nAt the exact current tree:\n\n- focused path-boundary, process-cleanup, and capture-ownership suite: 27 passed;\n- complete repository suite: 1,036 passed plus 16 subtests;\n- owned production coverage: 7,314/7,314 statements and 2,880/2,880 branches, 100%;\n- changed public production objects: 52/52 documented, 100%;\n- compilation and `git diff --check`: pass.\n\nTests exercise isolated platform-capability probes, missing-file budget validation, the exact service evidence ceiling, real stdout and stderr floods, service-log overflow before E2E sentinel execution, Unicode and partial UTF-8 suffixes, real readiness-synchronized ordinary success, exact 4 KiB boundary behavior, timeouts, reader errors, stuck readers, sibling finalization, capture-startup cleanup, unsupported platforms, invalid budgets, bounded kept-sandbox files, symlink containment, and exit-code precedence.\n\n## Governance, limitations, and rollback\n\nEnvironment scrubbing, readiness SSRF controls, exact-head evidence, semantic review, independent approval, and branch protection remain separate authorities. This slice does not cap repository-copy size, application artifacts, CPU beyond existing timeouts, process count, address space, network traffic, or unrelated processes. A descendant that creates a new session can escape process-group termination, but finite reader joins convert retained descriptors into deterministic failure instead of an unbounded workflow wait.\n\nRollback requires a separately reviewed replacement proving bounded parent memory, bounded service evidence files, finite reader finalization, timeout/cleanup behavior, and realistic flood resistance.\n\n## Merge gate\n\nThe 2026-08-12 Ready transition started a fresh exact-head required-check and review cycle; queued or running evidence is not passing. Keep unmerged until every required exact-head CI/security/supply-chain workflow is terminal-success, semantic review has no valid unresolved finding, live-base compatibility is refetched, two qualifying independent approvals including last-push approval exist, and repository protection permits integration. After merge, run protected-main command and service flood canaries before closing #766.\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n* **새로운 기능**\n * 샌드박스 검증 및 웹 E2E 실행에 stdout/stderr와 서비스 로그의 출력 크기 제한을 추가했습니다.\n * 출력 초과 시 관련 프로세스를 안전하게 종료하고 결과에 제한 상태를 표시합니다.\n * 저장소 외부로 연결되는 위험한 심볼릭 링크를 실행 전에 차단합니다.\n * 타임아웃 발생 시에도 제한된 출력과 증거를 보존합니다.\n\n* **문서**\n * 출력·실행 시간 제한 및 심볼릭 링크 보안 정책을 문서화했습니다.\n\n* **버그 수정**\n * 캡처 초기화와 정리 실패를 안전하게 처리하고, 우선순위에 따른 종료 코드를 유지합니다.\n\n<!-- end of auto-generated comment: release notes by coderabbit.ai -->",
strix UNKNOWN STEP 2026-08-14T14:25:02.9824865Z hint: to use in all of your new repositories, which will suppress this warning,
strix UNKNOWN STEP 2026-08-14T14:25:04.8060329Z HEAD is now at 6eb06cd fix(strix): bound quality timeout fixtures (#823)
strix UNKNOWN STEP 2026-08-14T14:25:05.9162736Z ^[[36;1m echo "::error::Strix target repository must belong to ContextualWisdomLab."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:05.9164608Z ^[[36;1m echo "::error::Target repository visibility did not resolve to true or false."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:07.3081095Z ^[[36;1m echo "::error::PR number and head SHA are required for trusted PR-scope Strix evidence."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:07.3082393Z ^[[36;1m echo "::error::PR head SHA must be a 40-character git SHA."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:07.3083454Z ^[[36;1m echo "::error::PR base SHA must be a 40-character git SHA."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:07.3100409Z ^[[36;1mecho "::error::PR head ref did not resolve to expected commit $PR_HEAD_SHA after retries." >&2^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8744576Z ^[[36;1m echo "::error::PR head SHA must be a 40-character git SHA."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8921037Z ^[[36;1m echo '::error::STRIX_LLM must not select mini or nano GPT-5 variants for security evidence.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8925617Z ^[[36;1m echo '::error::STRIX_GITHUB_MODELS_TOKEN is required for GitHub Models Strix scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8929366Z ^[[36;1m echo '::error::STRIX_OPENAI_API_KEY is required for Strix OpenAI Platform scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8932738Z ^[[36;1m echo '::error::OPENROUTER_API_KEY is required for Strix OpenRouter scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8934312Z ^[[36;1m echo '::error::NVIDIA NIM hosted trial scans are limited to public repositories.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8937112Z ^[[36;1m echo '::error::NVIDIA_NIM_API_KEY is required for Strix NVIDIA NIM scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8940541Z ^[[36;1m echo '::error::GCP_SA_KEY is required for Vertex AI Strix scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:09.8941959Z ^[[36;1m echo '::error::STRIX_LLM must select NVIDIA NIM Nemotron, GitHub Models openai/gpt-5 or newer, direct OpenAI GPT-5.4 or newer, OpenRouter openrouter/free, or an approved organization Vertex AI model.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:10.0273753Z ^[[36;1m echo "::error::Pinned Strix installation did not produce a trusted absolute executable path."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:10.0275136Z ^[[36;1m echo "::error::Refusing a Strix executable from a workspace or runner-temp path."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:10.0277680Z ^[[36;1m echo "::error::Pinned Strix installation did not produce a trusted absolute scripts root."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:10.0279107Z ^[[36;1m echo "::error::Pinned Strix executable is outside the trusted scripts root."^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4297541Z ^[[36;1m echo '::error::STRIX_GITHUB_MODELS_TOKEN is required for GitHub Models Strix scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4299346Z ^[[36;1m echo '::error::STRIX_OPENAI_API_KEY is required for Strix OpenAI Platform scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4301080Z ^[[36;1m echo '::error::OPENROUTER_API_KEY is required for Strix OpenRouter scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4302791Z ^[[36;1m echo '::error::NVIDIA_NIM_API_KEY is required for Strix NVIDIA NIM scans.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4816110Z ^[[36;1m echo '::error::STRIX_LLM must not select mini or nano GPT-5 variants for security evidence.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.4828924Z ^[[36;1m echo '::error::STRIX_LLM must select NVIDIA NIM Nemotron, GitHub Models openai/gpt-5 or newer, direct OpenAI GPT-5.4 or newer, OpenRouter openrouter/free, or an approved organization Vertex AI model.'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.5008378Z ^[[36;1m# LLM-backend-unavailable outcomes (GitHub Models "Too many requests"^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.5016922Z ^[[36;1mbackend_unavailable_signal='RateLimitError|Too many requests\. For more on scraping GitHub|exceeded your current quota|insufficient_quota|billing details|"status"[[:space:]]*:[[:space:]]*"RESOURCE_EXHAUSTED"|tokens_limit_reached|Request body too large|Max size:[[:space:]]*[0-9]+[[:space:]]+tokens|Error code:[[:space:]]*413|LLM CONNECTION FAILED|Could not establish connection to the language model|LLM warm-up failed|Configured model and fallback models were unavailable|Configured Vertex model and fallback models were unavailable|emitted provider infrastructure or failure-signal output|before provider infrastructure failure|litellm(\.exceptions)?\.NotFoundError[^[:cntrl:]]*Nvidia_nimException[^[:cntrl:]]*Error code:[[:space:]]*404'^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.5024494Z ^[[36;1m echo "::warning title=Strix backend unavailable::Strix could not complete because its LLM backend was unavailable (rate limit / token cap / connection or warm-up failure) before producing a vulnerability report. Treating as a neutral skip so an infrastructure outage does not block merges; genuine findings still fail the check. See the strix-reports artifact and the run log."^[[0m
strix UNKNOWN STEP 2026-08-14T14:55:19.0587016Z Strix report artifacts emitted warning/fatal/denied/timeout output; failing closed.
strix UNKNOWN STEP 2026-08-14T15:10:59.8217327Z │ '--startup-timeout', '5', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8217885Z │ '--e2e-timeout', '5' │
strix UNKNOWN STEP 2026-08-14T15:10:59.8219511Z │ timeout=15) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8230052Z │ 5. Consider using a timeout and limiting the depth of redirects (though │
strix UNKNOWN STEP 2026-08-14T15:10:59.8240877Z raw_response = await [REDACTED].with_raw_response.create(**data, timeout=timeout)
strix UNKNOWN STEP 2026-08-14T15:10:59.8324399Z │ "echo e2e" --startup-timeout 5 --e2e-timeout 5 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8336852Z │ '--startup-timeout', '5', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8337215Z │ '--e2e-timeout', '5' │
strix UNKNOWN STEP 2026-08-14T15:10:59.8338654Z │ proc = subprocess.run(cmd, timeout=10, capture_output=True, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8350258Z raw_response = await [REDACTED].with_raw_response.create(**data, timeout=timeout)
strix UNKNOWN STEP 2026-08-14T15:10:59.8398913Z raw_response = await [REDACTED].with_raw_response.create(**data, timeout=timeout)
strix UNKNOWN STEP 2026-08-14T15:10:59.8627796Z Strix report artifacts emitted warning/fatal/denied/timeout output; failing closed.
strix UNKNOWN STEP 2026-08-14T15:11:00.8239324Z ##[error]Process completed with exit code 1.
Strix model attempt and finding summary
strix UNKNOWN STEP 2026-08-14T14:25:46.5008378Z ^[[36;1m# LLM-backend-unavailable outcomes (GitHub Models "Too many requests"^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:46.5016922Z ^[[36;1mbackend_unavailable_signal='RateLimitError|Too many requests\. For more on scraping GitHub|exceeded your current quota|insufficient_quota|billing details|"status"[[:space:]]*:[[:space:]]*"RESOURCE_EXHAUSTED"|tokens_limit_reached|Request body too large|Max size:[[:space:]]*[0-9]+[[:space:]]+tokens|Error code:[[:space:]]*413|LLM CONNECTION FAILED|Could not establish connection to the language model|LLM warm-up failed|Configured model and fallback models were unavailable|Configured Vertex model and fallback models were unavailable|emitted provider infrastructure or failure-signal output|before provider infrastructure failure|litellm(\.exceptions)?\.NotFoundError[^[:cntrl:]]*Nvidia_nimException[^[:cntrl:]]*Error code:[[:space:]]*404'^[[0m
strix UNKNOWN STEP 2026-08-14T14:55:19.0199355Z │ Model nvidia_nim/nvidia/nemotron-3-super-120b-a12b │
strix UNKNOWN STEP 2026-08-14T14:55:19.0199779Z │ Vulnerabilities 0 │
strix UNKNOWN STEP 2026-08-14T14:55:19.0588749Z Strix run failed for model 'nvidia_nim/nvidia/nemotron-3-super-120b-a12b' after 1771s (exit code 1).
strix UNKNOWN STEP 2026-08-14T15:10:59.8389869Z │ Model nvidia_nim/nvidia/nemotron-3-super-120b-a12b │
strix UNKNOWN STEP 2026-08-14T15:10:59.8390278Z │ Vulnerabilities 2 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8390640Z │ MEDIUM: 2 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8629887Z Strix run failed for model 'nvidia_nim/nvidia/nemotron-3-super-120b-a12b' after 880s (exit code 1).
Strix vulnerability report window 1 (log lines 2124-2326)
strix UNKNOWN STEP 2026-08-14T15:10:59.8155763Z │ Penetration test initiated │
strix UNKNOWN STEP 2026-08-14T15:10:59.8156301Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8156839Z │ Target /tmp/strix-pr-scope.F19oLv │
strix UNKNOWN STEP 2026-08-14T15:10:59.8157482Z │ Output strix_runs/strix-pr-scope-f19olv_a76c │
strix UNKNOWN STEP 2026-08-14T15:10:59.8158028Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8158568Z │ Vulnerabilities will be displayed in real-time. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8159211Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8159728Z ╰──────────────────────────────────────────────────────────────────────────────╯
strix UNKNOWN STEP 2026-08-14T15:10:59.8160022Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8160027Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8160329Z ╭─ VULN-0001 ──────────────────────────────────────────────────────────────────╮
strix UNKNOWN STEP 2026-08-14T15:10:59.8160821Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8161308Z │ Vulnerability Report │
strix UNKNOWN STEP 2026-08-14T15:10:59.8161793Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8162317Z │ Title: SSRF in sandboxed_web_e2e.py via backend-ready-url and │
strix UNKNOWN STEP 2026-08-14T15:10:59.8162937Z │ frontend-ready-url parameters │
strix UNKNOWN STEP 2026-08-14T15:10:59.8163439Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8163933Z │ Severity: MEDIUM │
strix UNKNOWN STEP 2026-08-14T15:10:59.8164398Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8164849Z │ CVSS Score: 5.3 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8165475Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8166050Z │ Target: /workspace/strix-pr-scope.F19oLv/scripts/ci/sandboxed_web_e2e.py │
strix UNKNOWN STEP 2026-08-14T15:10:59.8166658Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8167539Z │ Endpoint: /scripts/ci/sandboxed_web_e2e.py │
strix UNKNOWN STEP 2026-08-14T15:10:59.8168402Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8168928Z │ Method: GET │
strix UNKNOWN STEP 2026-08-14T15:10:59.8169432Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8169965Z │ CVSS Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N │
strix UNKNOWN STEP 2026-08-14T15:10:59.8170506Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8171009Z │ Description │
strix UNKNOWN STEP 2026-08-14T15:10:59.8171576Z │ The sandboxed_web_e2e.py script accepts user-controlled URLs via the │
strix UNKNOWN STEP 2026-08-14T15:10:59.8172533Z │ --backend-ready-url and --frontend-ready-url command-line arguments and │
strix UNKNOWN STEP 2026-08-14T15:10:59.8173253Z │ makes HTTP requests to these URLs using urllib.request without adequate │
strix UNKNOWN STEP 2026-08-14T15:10:59.8174004Z │ network restrictions. This allows an attacker who can control these │
strix UNKNOWN STEP 2026-08-14T15:10:59.8174735Z │ arguments to cause the script to make requests to arbitrary internal or │
strix UNKNOWN STEP 2026-08-14T15:10:59.8175642Z │ external services, potentially leading to service enumeration, credential │
strix UNKNOWN STEP 2026-08-14T15:10:59.8176374Z │ disclosure, or further attacks. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8177023Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8177562Z │ Impact │
strix UNKNOWN STEP 2026-08-14T15:10:59.8178217Z │ An attacker who can manipulate the arguments passed to │
strix UNKNOWN STEP 2026-08-14T15:10:59.8178894Z │ sandboxed_web_e2e.py (e.g., through CI/CD pipeline configuration, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8179533Z │ environment variables, or other means) can cause the script to perform │
strix UNKNOWN STEP 2026-08-14T15:10:59.8180286Z │ Server-Side Request Forgery (SSRF) requests. This could allow probing of │
strix UNKNOWN STEP 2026-08-14T15:10:59.8181032Z │ internal services, disclosure of sensitive information from internal │
strix UNKNOWN STEP 2026-08-14T15:10:59.8181727Z │ endpoints, or use as a pivot for further attacks depending on the │
strix UNKNOWN STEP 2026-08-14T15:10:59.8182359Z │ reachable services and their responses. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8182896Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8183396Z │ Technical Analysis │
strix UNKNOWN STEP 2026-08-14T15:10:59.8184020Z │ The script uses [REDACTED]() with a NoRedirectHandler to │
strix UNKNOWN STEP 2026-08-14T15:10:59.8184695Z │ poll the provided URLs for readiness. The wait_for_url function repeatedly │
strix UNKNOWN STEP 2026-08-14T15:10:59.8185496Z │ attempts to open the URL until it responds or times out. There is no │
strix UNKNOWN STEP 2026-08-14T15:10:59.8186160Z │ validation or restriction on the URL scheme, host, or port, allowing │
strix UNKNOWN STEP 2026-08-14T15:10:59.8187022Z │ requests to any reachable destination (e.g., 127.0.0.1, internal IPs, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8187678Z │ cloud metadata endpoints, etc.). The script only validates that the URL │
strix UNKNOWN STEP 2026-08-14T15:10:59.8188342Z │ starts with http:// or https://, but does not restrict to expected domains │
strix UNKNOWN STEP 2026-08-14T15:10:59.8188975Z │ or block internal addresses. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8189568Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8190064Z │ PoC Description │
strix UNKNOWN STEP 2026-08-14T15:10:59.8190670Z │ 1. Start an HTTP server on a controlled address (e.g., 127.0.0.1:9999) to │
strix UNKNOWN STEP 2026-08-14T15:10:59.8191292Z │ log incoming requests. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8191925Z │ 2. Run sandboxed_web_e2e.py with the server URL specified for both │
strix UNKNOWN STEP 2026-08-14T15:10:59.8192812Z │ --backend-ready-url and --frontend-ready-url. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8193561Z │ 3. Observe that the script makes HTTP GET requests to the server, as │
strix UNKNOWN STEP 2026-08-14T15:10:59.8194237Z │ evidenced by server logs. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8194889Z │ 4. The same technique can be used to target internal services (e.g., │
strix UNKNOWN STEP 2026-08-14T15:10:59.8195727Z │ 127.0.0.1:80, [REDACTED].254, etc.) if they are reachable from the │
strix UNKNOWN STEP 2026-08-14T15:10:59.8196329Z │ sandbox environment. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8196848Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8197324Z │ PoC Code │
strix UNKNOWN STEP 2026-08-14T15:10:59.8197881Z │ #!/usr/bin/env python3 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8198504Z │ import http.server │
strix UNKNOWN STEP 2026-08-14T15:10:59.8199123Z │ import subprocess │
strix UNKNOWN STEP 2026-08-14T15:10:59.8199715Z │ import sys │
strix UNKNOWN STEP 2026-08-14T15:10:59.8200272Z │ import threading │
strix UNKNOWN STEP 2026-08-14T15:10:59.8200833Z │ import time │
strix UNKNOWN STEP 2026-08-14T15:10:59.8201364Z │ import requests │
strix UNKNOWN STEP 2026-08-14T15:10:59.8201870Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8202398Z │ def start_server(port=9999): │
strix UNKNOWN STEP 2026-08-14T15:10:59.8203031Z │ server = [REDACTED](('127.0.0.1', port), │
strix UNKNOWN STEP 2026-08-14T15:10:59.8203710Z │ [REDACTED]) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8204388Z │ thread = threading.Thread(target=server.serve_forever) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8204990Z │ thread.daemon = True │
strix UNKNOWN STEP 2026-08-14T15:10:59.8205702Z │ thread.start() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8206291Z │ # Give the server a moment to start │
strix UNKNOWN STEP 2026-08-14T15:10:59.8206875Z │ time.sleep(0.5) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8207387Z │ return server, thread │
strix UNKNOWN STEP 2026-08-14T15:10:59.8207919Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8208373Z │ def main(): │
strix UNKNOWN STEP 2026-08-14T15:10:59.8208886Z │ # Start the HTTP server │
strix UNKNOWN STEP 2026-08-14T15:10:59.8209622Z │ server, thread = start_server(9999) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8210158Z │ try: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8210722Z │ # Run the sandboxed_web_e2e.py script with our server as the │
strix UNKNOWN STEP 2026-08-14T15:10:59.8211257Z │ readiness URL │
strix UNKNOWN STEP 2026-08-14T15:10:59.8211769Z │ cmd = [ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8212252Z │ sys.executable, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8212858Z │ '/workspace/strix-pr-scope.F19oLv/scripts/ci/sandboxed_web_e2e │
strix UNKNOWN STEP 2026-08-14T15:10:59.8213435Z │ .py', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8213943Z │ '--backend-cmd', 'sleep 20', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8214651Z │ '--frontend-cmd', 'sleep 20', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8215539Z │ '--backend-ready-url', 'http://127.0.0.1:9999/', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8216203Z │ '--frontend-ready-url', 'http://127.0.0.1:9999/', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8216800Z │ '--e2e-cmd', 'echo "E2E completed"', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8217327Z │ '--startup-timeout', '5', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8217885Z │ '--e2e-timeout', '5' │
strix UNKNOWN STEP 2026-08-14T15:10:59.8218425Z │ ] │
strix UNKNOWN STEP 2026-08-14T15:10:59.8218987Z │ result = subprocess.run(cmd, capture_output=True, text=True, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8219511Z │ timeout=15) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8219904Z │ print("Script STDOUT:", result.stdout) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8220299Z │ print("Script STDERR:", result.stderr) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8220685Z │ print("Return code:", result.returncode) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8221073Z │ # Check if the script printed the RESULT_MARKER │
strix UNKNOWN STEP 2026-08-14T15:10:59.8221472Z │ if 'SANDBOXED_WEB_E2E_RESULT' in result.stdout: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8221901Z │ print("Script executed successfully") │
strix UNKNOWN STEP 2026-08-14T15:10:59.8222356Z │ else: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8222722Z │ print("Script may have failed") │
strix UNKNOWN STEP 2026-08-14T15:10:59.8223072Z │ finally: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8223430Z │ server.shutdown() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8223806Z │ thread.join() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8224146Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8224478Z │ if __name__ == '__main__': │
strix UNKNOWN STEP 2026-08-14T15:10:59.8224812Z │ main() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8225124Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8225672Z │ Remediation │
strix UNKNOWN STEP 2026-08-14T15:10:59.8226082Z │ 1. Implement URL validation to restrict the allowed hosts or IP ranges for │
strix UNKNOWN STEP 2026-08-14T15:10:59.8226542Z │ the --backend-ready-url and --frontend-ready-url arguments. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8227002Z │ 2. Consider using an allowlist of expected URLs or patterns. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8227613Z │ 3. Alternatively, disable the readiness URL feature if not required and │
strix UNKNOWN STEP 2026-08-14T15:10:59.8228043Z │ use other methods to determine service readiness. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8228465Z │ 4. If the URLs must be user-configurable, implement strict schema │
strix UNKNOWN STEP 2026-08-14T15:10:59.8228884Z │ validation and block internal IP ranges (e.g., 127.0.0.0/8, 10.0.0.0/8, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8229291Z │ 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16) and cloud metadata │
strix UNKNOWN STEP 2026-08-14T15:10:59.8229650Z │ endpoints. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8230052Z │ 5. Consider using a timeout and limiting the depth of redirects (though │
strix UNKNOWN STEP 2026-08-14T15:10:59.8230491Z │ the script already disables redirects). │
strix UNKNOWN STEP 2026-08-14T15:10:59.8230922Z │ 6. Monitor and log outgoing requests from the script for unexpected │
strix UNKNOWN STEP 2026-08-14T15:10:59.8231655Z │ destinations. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8232161Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8232688Z ╰──────────────────────────────────────────────────────────────────────────────╯
strix UNKNOWN STEP 2026-08-14T15:10:59.8232987Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8233463Z 2026-08-14 15:10:56.229 ERROR strix-pr-scope-f19olv_a76c - [REDACTED]: Error during vulnerability deduplication check
strix UNKNOWN STEP 2026-08-14T15:10:59.8234079Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8234842Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 886, in acompletion
strix UNKNOWN STEP 2026-08-14T15:10:59.8236127Z headers, response = await self.make_openai_chat_completion_request(
strix UNKNOWN STEP 2026-08-14T15:10:59.8236454Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8236692Z ...<4 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8236868Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8237027Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8237540Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/litellm_core_utils/logging_utils.py", line 289, in async_wrapper
strix UNKNOWN STEP 2026-08-14T15:10:59.8238049Z result = await func(*args, **kwargs)
strix UNKNOWN STEP 2026-08-14T15:10:59.8238344Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8238923Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 447, in make_openai_chat_completion_request
strix UNKNOWN STEP 2026-08-14T15:10:59.8239534Z raise e
strix UNKNOWN STEP 2026-08-14T15:10:59.8240121Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 427, in make_openai_chat_completion_request
strix UNKNOWN STEP 2026-08-14T15:10:59.8240877Z raw_response = await [REDACTED].with_raw_response.create(**data, timeout=timeout)
strix UNKNOWN STEP 2026-08-14T15:10:59.8241367Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8242138Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_legacy_response.py", line 384, in wrapped
strix UNKNOWN STEP 2026-08-14T15:10:59.8242851Z return cast(LegacyAPIResponse[R], await func(*args, **kwargs))
strix UNKNOWN STEP 2026-08-14T15:10:59.8243209Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8243869Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/resources/chat/completions/completions.py", line 2814, in create
strix UNKNOWN STEP 2026-08-14T15:10:59.8244572Z return await self._post(
strix UNKNOWN STEP 2026-08-14T15:10:59.8244836Z ^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8245025Z ...<54 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8245336Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8245513Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8246110Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_base_client.py", line 1931, in post
strix UNKNOWN STEP 2026-08-14T15:10:59.8246924Z return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
strix UNKNOWN STEP 2026-08-14T15:10:59.8247631Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8248162Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_base_client.py", line 1716, in request
strix UNKNOWN STEP 2026-08-14T15:10:59.8248778Z raise self._make_status_error_from_response(err.response) from None
strix UNKNOWN STEP 2026-08-14T15:10:59.8249088Z openai.NotFoundError: Error code: 404
strix UNKNOWN STEP 2026-08-14T15:10:59.8249241Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8249390Z During handling of the above exception, another exception occurred:
strix UNKNOWN STEP 2026-08-14T15:10:59.8249601Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8249693Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8250115Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/main.py", line 657, in acompletion
strix UNKNOWN STEP 2026-08-14T15:10:59.8250540Z response = await init_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8250756Z ^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8251321Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 946, in acompletion
strix UNKNOWN STEP 2026-08-14T15:10:59.8251787Z raise OpenAIError(
strix UNKNOWN STEP 2026-08-14T15:10:59.8251972Z ...<4 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8252146Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8252393Z [REDACTED].common_utils.OpenAIError: Error code: 404
strix UNKNOWN STEP 2026-08-14T15:10:59.8252608Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8252758Z During handling of the above exception, another exception occurred:
strix UNKNOWN STEP 2026-08-14T15:10:59.8252976Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8253067Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8253533Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/strix/report/dedupe.py", line 192, in check_duplicate
strix UNKNOWN STEP 2026-08-14T15:10:59.8253987Z response = await model.get_response(
strix UNKNOWN STEP 2026-08-14T15:10:59.8254217Z ^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8288959Z ...<10 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8289152Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8289309Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8289856Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/extensions/models/litellm_model.py", line 220, in get_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8290394Z response = await self._fetch_response(
strix UNKNOWN STEP 2026-08-14T15:10:59.8290638Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8290850Z ...<10 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8291035Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8291186Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8291660Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/extensions/models/litellm_model.py", line 531, in _fetch_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8292167Z ret = await litellm.acompletion(
strix UNKNOWN STEP 2026-08-14T15:10:59.8292395Z ^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8292603Z ...<19 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8292780Z )
Strix vulnerability report window 2 (log lines 2351-2553)
strix UNKNOWN STEP 2026-08-14T15:10:59.8301208Z ...<5 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8301409Z extra_information=extra_information,
strix UNKNOWN STEP 2026-08-14T15:10:59.8301644Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8301849Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8302002Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8302507Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/litellm_core_utils/exception_mapping_utils.py", line 410, in _map_openai_exception
strix UNKNOWN STEP 2026-08-14T15:10:59.8303267Z raise NotFoundError(
strix UNKNOWN STEP 2026-08-14T15:10:59.8303560Z ...<5 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8303818Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8304416Z [REDACTED]: litellm.NotFoundError: NotFoundError: Nvidia_nimException - Error code: 404
strix UNKNOWN STEP 2026-08-14T15:10:59.8305416Z ╭─ VULN-0002 ──────────────────────────────────────────────────────────────────╮
strix UNKNOWN STEP 2026-08-14T15:10:59.8305919Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8306357Z │ Vulnerability Report │
strix UNKNOWN STEP 2026-08-14T15:10:59.8306725Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8307103Z │ Title: SSRF in sandboxed_web_e2e.py via backend-ready-url and │
strix UNKNOWN STEP 2026-08-14T15:10:59.8307532Z │ frontend-ready-url arguments │
strix UNKNOWN STEP 2026-08-14T15:10:59.8307890Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8308248Z │ Severity: MEDIUM │
strix UNKNOWN STEP 2026-08-14T15:10:59.8308589Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8308918Z │ CVSS Score: 6.5 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8309240Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8309617Z │ Target: local_code: /tmp/strix-pr-scope.F19oLv (workspace: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8310050Z │ /workspace/strix-pr-scope.F19oLv) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8310407Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8310733Z │ Method: GET │
strix UNKNOWN STEP 2026-08-14T15:10:59.8311055Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8311413Z │ CVSS Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N │
strix UNKNOWN STEP 2026-08-14T15:10:59.8311760Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8312099Z │ Description │
strix UNKNOWN STEP 2026-08-14T15:10:59.8312502Z │ The script sandboxed_web_e2e.py accepts --backend-ready-url and │
strix UNKNOWN STEP 2026-08-14T15:10:59.8312956Z │ --frontend-ready-url arguments and uses them in wait_for_url function │
strix UNKNOWN STEP 2026-08-14T15:10:59.8313397Z │ which makes HTTP requests without restricting to external networks, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8313832Z │ allowing Server-Side Request Forgery. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8314195Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8314515Z │ Impact │
strix UNKNOWN STEP 2026-08-14T15:10:59.8315056Z │ An attacker who can control the arguments (e.g., if the script is invoked │
strix UNKNOWN STEP 2026-08-14T15:10:59.8315866Z │ via a web service or CI pipeline) can make the script send requests to │
strix UNKNOWN STEP 2026-08-14T15:10:59.8316427Z │ internal services, potentially leading to information disclosure, internal │
strix UNKNOWN STEP 2026-08-14T15:10:59.8316995Z │ network probing, or interaction with cloud metadata services. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8317419Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8317766Z │ Technical Analysis │
strix UNKNOWN STEP 2026-08-14T15:10:59.8318181Z │ The wait_for_url function uses urllib.request to poll the provided URL. It │
strix UNKNOWN STEP 2026-08-14T15:10:59.8318625Z │ only checks that the URL starts with http:// or https:// but does not │
strix UNKNOWN STEP 2026-08-14T15:10:59.8319054Z │ validate that the URL is not pointing to an internal resource. This allows │
strix UNKNOWN STEP 2026-08-14T15:10:59.8319502Z │ an attacker to supply a URL like http://[REDACTED].254/latest/meta-data/ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8319943Z │ (AWS metadata) or http://localhost:8080/admin. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8320396Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8320945Z │ PoC Description │
strix UNKNOWN STEP 2026-08-14T15:10:59.8321581Z │ 1. Start a simple HTTP server on a chosen port and interface (e.g., │
strix UNKNOWN STEP 2026-08-14T15:10:59.8322153Z │ 127.0.0.1:9999). │
strix UNKNOWN STEP 2026-08-14T15:10:59.8322593Z │ 2. Run the script with: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8323081Z │ ./scripts/ci/sandboxed_web_e2e.py --backend-ready-url │
strix UNKNOWN STEP 2026-08-14T15:10:59.8323517Z │ "http://127.0.0.1:9999/" --frontend-ready-url "http://127.0.0.1:9999/" │
strix UNKNOWN STEP 2026-08-14T15:10:59.8323954Z │ --backend-cmd "echo backend" --frontend-cmd "echo frontend" --e2e-cmd │
strix UNKNOWN STEP 2026-08-14T15:10:59.8324399Z │ "echo e2e" --startup-timeout 5 --e2e-timeout 5 │
strix UNKNOWN STEP 2026-08-14T15:10:59.8324831Z │ 3. Observe that the HTTP server receives two GET requests (one for each │
strix UNKNOWN STEP 2026-08-14T15:10:59.8325406Z │ URL). │
strix UNKNOWN STEP 2026-08-14T15:10:59.8325755Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8326094Z │ PoC Code │
strix UNKNOWN STEP 2026-08-14T15:10:59.8326464Z │ import http.server │
strix UNKNOWN STEP 2026-08-14T15:10:59.8326869Z │ import threading │
strix UNKNOWN STEP 2026-08-14T15:10:59.8327299Z │ import time │
strix UNKNOWN STEP 2026-08-14T15:10:59.8327660Z │ import subprocess │
strix UNKNOWN STEP 2026-08-14T15:10:59.8328029Z │ import sys │
strix UNKNOWN STEP 2026-08-14T15:10:59.8328358Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8328706Z │ def start_server(port=9999): │
strix UNKNOWN STEP 2026-08-14T15:10:59.8329111Z │ server = [REDACTED](('127.0.0.1', port), │
strix UNKNOWN STEP 2026-08-14T15:10:59.8329542Z │ [REDACTED]) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8329976Z │ thread = threading.Thread(target=server.serve_forever) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8330369Z │ thread.daemon = True │
strix UNKNOWN STEP 2026-08-14T15:10:59.8330730Z │ thread.start() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8331092Z │ return server, thread │
strix UNKNOWN STEP 2026-08-14T15:10:59.8331428Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8332026Z │ if __name__ == '__main__': │
strix UNKNOWN STEP 2026-08-14T15:10:59.8332411Z │ server, thread = start_server(9999) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8332768Z │ try: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8333131Z │ # Run the sandboxed_web_e2e.py script with the arguments pointing │
strix UNKNOWN STEP 2026-08-14T15:10:59.8333508Z │ to our server │
strix UNKNOWN STEP 2026-08-14T15:10:59.8333837Z │ cmd = [ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8334194Z │ sys.executable, 'scripts/ci/sandboxed_web_e2e.py', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8334596Z │ '--backend-ready-url', 'http://127.0.0.1:9999/', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8334992Z │ '--frontend-ready-url', 'http://127.0.0.1:9999/', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8335721Z │ '--backend-cmd', 'echo backend', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8336113Z │ '--frontend-cmd', 'echo frontend', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8336489Z │ '--e2e-cmd', 'echo e2e', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8336852Z │ '--startup-timeout', '5', │
strix UNKNOWN STEP 2026-08-14T15:10:59.8337215Z │ '--e2e-timeout', '5' │
strix UNKNOWN STEP 2026-08-14T15:10:59.8337546Z │ ] │
strix UNKNOWN STEP 2026-08-14T15:10:59.8337906Z │ # We don't care about the output, just that the server gets │
strix UNKNOWN STEP 2026-08-14T15:10:59.8338273Z │ requests │
strix UNKNOWN STEP 2026-08-14T15:10:59.8338654Z │ proc = subprocess.run(cmd, timeout=10, capture_output=True, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8339040Z │ text=True) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8339417Z │ print("Script output:", proc.stdout) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8339807Z │ print("Script stderr:", proc.stderr) │
strix UNKNOWN STEP 2026-08-14T15:10:59.8340169Z │ finally: │
strix UNKNOWN STEP 2026-08-14T15:10:59.8340529Z │ server.shutdown() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8340884Z │ thread.join() │
strix UNKNOWN STEP 2026-08-14T15:10:59.8341208Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8341544Z │ Remediation │
strix UNKNOWN STEP 2026-08-14T15:10:59.8341941Z │ Implement URL validation in wait_for_url to block internal IP addresses │
strix UNKNOWN STEP 2026-08-14T15:10:59.8342356Z │ (like 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, │
strix UNKNOWN STEP 2026-08-14T15:10:59.8342897Z │ 169.254.0.0/16) and optionally restrict to only expected domains if known. │
strix UNKNOWN STEP 2026-08-14T15:10:59.8343265Z │ │
strix UNKNOWN STEP 2026-08-14T15:10:59.8343630Z ╰──────────────────────────────────────────────────────────────────────────────╯
strix UNKNOWN STEP 2026-08-14T15:10:59.8343822Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8344106Z 2026-08-14 15:10:56.956 ERROR strix-pr-scope-f19olv_a76c - [REDACTED]: Strix scan strix-pr-scope-f19olv_a76c failed
strix UNKNOWN STEP 2026-08-14T15:10:59.8344534Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8345057Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 1065, in async_streaming
strix UNKNOWN STEP 2026-08-14T15:10:59.8345848Z headers, response = await self.make_openai_chat_completion_request(
strix UNKNOWN STEP 2026-08-14T15:10:59.8346175Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8346408Z ...<4 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8346709Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8346867Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8347329Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/litellm_core_utils/logging_utils.py", line 289, in async_wrapper
strix UNKNOWN STEP 2026-08-14T15:10:59.8347823Z result = await func(*args, **kwargs)
strix UNKNOWN STEP 2026-08-14T15:10:59.8348045Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8348566Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 447, in make_openai_chat_completion_request
strix UNKNOWN STEP 2026-08-14T15:10:59.8349088Z raise e
strix UNKNOWN STEP 2026-08-14T15:10:59.8349578Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 427, in make_openai_chat_completion_request
strix UNKNOWN STEP 2026-08-14T15:10:59.8350258Z raw_response = await [REDACTED].with_raw_response.create(**data, timeout=timeout)
strix UNKNOWN STEP 2026-08-14T15:10:59.8350691Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8351184Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_legacy_response.py", line 384, in wrapped
strix UNKNOWN STEP 2026-08-14T15:10:59.8351671Z return cast(LegacyAPIResponse[R], await func(*args, **kwargs))
strix UNKNOWN STEP 2026-08-14T15:10:59.8351972Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8352491Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/resources/chat/completions/completions.py", line 2814, in create
strix UNKNOWN STEP 2026-08-14T15:10:59.8352985Z return await self._post(
strix UNKNOWN STEP 2026-08-14T15:10:59.8353186Z ^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8353375Z ...<54 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8353550Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8353706Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8354064Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_base_client.py", line 1931, in post
strix UNKNOWN STEP 2026-08-14T15:10:59.8354566Z return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
strix UNKNOWN STEP 2026-08-14T15:10:59.8354913Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8355518Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/openai/_base_client.py", line 1716, in request
strix UNKNOWN STEP 2026-08-14T15:10:59.8356038Z raise self._make_status_error_from_response(err.response) from None
strix UNKNOWN STEP 2026-08-14T15:10:59.8356351Z openai.NotFoundError: Error code: 404
strix UNKNOWN STEP 2026-08-14T15:10:59.8356501Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8356653Z During handling of the above exception, another exception occurred:
strix UNKNOWN STEP 2026-08-14T15:10:59.8356869Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8356958Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8357384Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/main.py", line 657, in acompletion
strix UNKNOWN STEP 2026-08-14T15:10:59.8357794Z response = await init_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8357999Z ^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8358457Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/litellm/llms/openai/openai.py", line 1115, in async_streaming
strix UNKNOWN STEP 2026-08-14T15:10:59.8359049Z raise OpenAIError(
strix UNKNOWN STEP 2026-08-14T15:10:59.8359232Z ...<4 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8359400Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8359637Z [REDACTED].common_utils.OpenAIError: Error code: 404
strix UNKNOWN STEP 2026-08-14T15:10:59.8359844Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8359991Z During handling of the above exception, another exception occurred:
strix UNKNOWN STEP 2026-08-14T15:10:59.8360201Z
strix UNKNOWN STEP 2026-08-14T15:10:59.8360286Z Traceback (most recent call last):
strix UNKNOWN STEP 2026-08-14T15:10:59.8360779Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/strix/core/runner.py", line 268, in run_strix_scan
strix UNKNOWN STEP 2026-08-14T15:10:59.8361208Z result = await run_agent_loop(
strix UNKNOWN STEP 2026-08-14T15:10:59.8361414Z ^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8361616Z ...<12 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8361795Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8361951Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8362441Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/strix/core/execution.py", line 78, in run_agent_loop
strix UNKNOWN STEP 2026-08-14T15:10:59.8362923Z result = await _run_noninteractive_until_lifecycle(
strix UNKNOWN STEP 2026-08-14T15:10:59.8363185Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8363405Z ...<10 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8363574Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8363731Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8364188Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/strix/core/execution.py", line 281, in _run_noninteractive_until_lifecycle
strix UNKNOWN STEP 2026-08-14T15:10:59.8364678Z result = await _run_cycle(
strix UNKNOWN STEP 2026-08-14T15:10:59.8364881Z ^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8365065Z ...<11 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8365374Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8365589Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8365983Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/strix/core/execution.py", line 355, in _run_cycle
strix UNKNOWN STEP 2026-08-14T15:10:59.8366432Z async for event in stream.stream_events():
strix UNKNOWN STEP 2026-08-14T15:10:59.8366667Z ...<4 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8366916Z logger.exception("stream event sink failed for %s", agent_id)
strix UNKNOWN STEP 2026-08-14T15:10:59.8367419Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/result.py", line 773, in stream_events
strix UNKNOWN STEP 2026-08-14T15:10:59.8367842Z raise self._stored_exception
strix UNKNOWN STEP 2026-08-14T15:10:59.8368277Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/result.py", line 850, in _await_task_safely
strix UNKNOWN STEP 2026-08-14T15:10:59.8368694Z await task
strix UNKNOWN STEP 2026-08-14T15:10:59.8369099Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/result.py", line 608, in _await_run_and_cleanup
strix UNKNOWN STEP 2026-08-14T15:10:59.8369539Z result = await original_task
strix UNKNOWN STEP 2026-08-14T15:10:59.8369740Z ^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8370188Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/run_internal/run_loop.py", line 1014, in start_streaming
strix UNKNOWN STEP 2026-08-14T15:10:59.8370673Z turn_result = await run_single_turn_streamed(
strix UNKNOWN STEP 2026-08-14T15:10:59.8370922Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8371135Z ...<18 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8371307Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8371463Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8371898Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/run_internal/run_loop.py", line 1476, in run_single_turn_streamed
strix UNKNOWN STEP 2026-08-14T15:10:59.8372378Z async for event in retry_stream:
strix UNKNOWN STEP 2026-08-14T15:10:59.8372596Z ...<136 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8372778Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8373254Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/run_internal/model_retry.py", line 652, in stream_response_with_retry
strix UNKNOWN STEP 2026-08-14T15:10:59.8373745Z event = await stream.__anext__()
strix UNKNOWN STEP 2026-08-14T15:10:59.8373963Z ^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8374444Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/extensions/models/litellm_model.py", line 334, in stream_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8375088Z response, stream = await self._fetch_response(
strix UNKNOWN STEP 2026-08-14T15:10:59.8375488Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^
strix UNKNOWN STEP 2026-08-14T15:10:59.8375702Z ...<10 lines>...
strix UNKNOWN STEP 2026-08-14T15:10:59.8375874Z )
strix UNKNOWN STEP 2026-08-14T15:10:59.8376025Z ^
strix UNKNOWN STEP 2026-08-14T15:10:59.8376475Z File "/opt/hostedtoolcache/Python/3.13.15/x64/lib/python3.13/site-packages/agents/extensions/models/litellm_model.py", line 531, in _fetch_response
strix UNKNOWN STEP 2026-08-14T15:10:59.8376993Z ret = await litellm.acompletion(
strix UNKNOWN STEP 2026-08-14T15:10:59.8377207Z ^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed log excerpt
strix UNKNOWN STEP 2026-08-14T14:24:53.5207815Z Current runner version: '2.336.0'
strix UNKNOWN STEP 2026-08-14T14:24:53.5229480Z ##[group]Runner Image Provisioner
strix UNKNOWN STEP 2026-08-14T14:24:53.5230213Z Hosted Compute Agent
strix UNKNOWN STEP 2026-08-14T14:24:53.5230718Z Version: 20260729.566
strix UNKNOWN STEP 2026-08-14T14:24:53.5231340Z Commit: cf7153fe6e25b664e8693c24944bf2b00355d109
strix UNKNOWN STEP 2026-08-14T14:24:53.5231982Z Build Date: 2026-07-29T19:17:02Z
strix UNKNOWN STEP 2026-08-14T14:24:53.5232805Z Worker ID: {f3ed27a4-7906-40e0-9606-19e9c225d697}
strix UNKNOWN STEP 2026-08-14T14:24:53.5233435Z Azure Region: westus3
strix UNKNOWN STEP 2026-08-14T14:24:53.5233933Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:24:53.5235112Z ##[group]Operating System
strix UNKNOWN STEP 2026-08-14T14:24:53.5235828Z Ubuntu
strix UNKNOWN STEP 2026-08-14T14:24:53.5236345Z 24.04.4
strix UNKNOWN STEP 2026-08-14T14:24:53.5236809Z LTS
strix UNKNOWN STEP 2026-08-14T14:24:53.5237268Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:24:53.5237837Z ##[group]Runner Image
strix UNKNOWN STEP 2026-08-14T14:24:53.5238415Z Image: ubuntu-24.04
strix UNKNOWN STEP 2026-08-14T14:24:53.5238925Z Version: 20260810.271.1
strix UNKNOWN STEP 2026-08-14T14:24:53.5239965Z Included Software: https://github.com/actions/runner-images/blob/ubuntu24/20260810.271/images/ubuntu/Ubuntu2404-Readme.md
strix UNKNOWN STEP 2026-08-14T14:24:53.5241281Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu24%2F20260810.271
strix UNKNOWN STEP 2026-08-14T14:24:53.5242126Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:24:53.5243307Z ##[group]GITHUB_TOKEN Permissions
strix UNKNOWN STEP 2026-08-14T14:24:53.5245088Z Actions: read
strix UNKNOWN STEP 2026-08-14T14:24:53.5245846Z Contents: read
strix UNKNOWN STEP 2026-08-14T14:24:53.5246362Z Metadata: read
strix UNKNOWN STEP 2026-08-14T14:24:53.5246819Z Models: read
strix UNKNOWN STEP 2026-08-14T14:24:53.5247361Z Statuses: write
strix UNKNOWN STEP 2026-08-14T14:24:53.5247844Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:24:53.5249677Z Secret source: Actions
strix UNKNOWN STEP 2026-08-14T14:24:53.5250732Z Prepare workflow directory
strix UNKNOWN STEP 2026-08-14T14:24:53.5563841Z Prepare all required actions
strix UNKNOWN STEP 2026-08-14T14:24:53.5618501Z Getting action download info
strix UNKNOWN STEP 2026-08-14T14:24:53.8737975Z Download action repository 'step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920' (SHA:bf7454d06d71f1098171f2acdf0cd4708d7b5920)
strix UNKNOWN STEP 2026-08-14T14:24:55.0318242Z Download action repository 'actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97' (SHA:5fda3b95a4ea91299a34e894583c3862153e4b97)
strix UNKNOWN STEP 2026-08-14T14:24:55.3295777Z Download action repository 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' (SHA:9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)
strix UNKNOWN STEP 2026-08-14T14:24:55.3698499Z Download action repository 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' (SHA:043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)
strix UNKNOWN STEP 2026-08-14T14:24:55.5826542Z Complete job name: strix
strix UNKNOWN STEP 2026-08-14T14:24:55.6748158Z ##[group]Run step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920
strix UNKNOWN STEP 2026-08-14T14:24:55.6749811Z with:
strix UNKNOWN STEP 2026-08-14T14:24:55.6750551Z egress-policy: audit
strix UNKNOWN STEP 2026-08-14T14:24:55.6751415Z disable-file-monitoring: true
strix UNKNOWN STEP 2026-08-14T14:24:55.6759373Z token: [REDACTED]
strix UNKNOWN STEP 2026-08-14T14:24:55.6760153Z disable-telemetry: false
strix UNKNOWN STEP 2026-08-14T14:24:55.6761018Z disable-sudo: false
strix UNKNOWN STEP 2026-08-14T14:24:55.6761866Z disable-sudo-and-containers: false
strix UNKNOWN STEP 2026-08-14T14:24:55.6762846Z use-policy-store: false
strix UNKNOWN STEP 2026-08-14T14:24:55.6763745Z deploy-on-self-hosted-vm: false
strix UNKNOWN STEP 2026-08-14T14:24:55.6764840Z env:
strix UNKNOWN STEP 2026-08-14T14:24:55.6765707Z FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
strix UNKNOWN STEP 2026-08-14T14:24:55.6766670Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:24:55.7840225Z [harden-runner] pre-step
strix UNKNOWN STEP 2026-08-14T14:24:55.7841633Z [!] Current Configuration:
strix UNKNOWN STEP 2026-08-14T14:24:55.7850599Z {"repo":"ContextualWisdomLab/.github","run_id":"31806061284","correlation_id":"cfabb5ae-3922-4e6d-8d22-804e33c4aac1","working_directory":"/home/runner/work/.github/.github","api_url":"https://[REDACTED].io/v1","telemetry_url":"https://[REDACTED].io/v1","allowed_endpoints":"","egress_policy":"audit","disable_telemetry":false,"disable_sudo":false,"disable_sudo_and_containers":false,"disable_file_monitoring":true,"private":false,"is_github_hosted":true,"is_debug":false,"one_time_key":"","api_key":[REDACTED],"use_policy_store":false,"deploy_on_self_hosted_vm":false}
strix UNKNOWN STEP 2026-08-14T14:24:55.7859351Z
strix UNKNOWN STEP 2026-08-14T14:24:55.7860397Z ^[[32mView security insights and recommended policy at:^[[0m
strix UNKNOWN STEP 2026-08-14T14:24:55.7862709Z https://app.stepsecurity.io/github/ContextualWisdomLab/.github/actions/runs/31806061284
strix UNKNOWN STEP 2026-08-14T14:24:55.7865444Z RUNNER_NAME: GitHub Actions 1000859170
strix UNKNOWN STEP 2026-08-14T14:24:56.3532068Z Runner IP Address: 20.168.103.6
strix UNKNOWN STEP 2026-08-14T14:24:56.3532750Z Step Security Job Correlation ID: cfabb5ae-3922-4e6d-8d22-804e33c4aac1
strix UNKNOWN STEP 2026-08-14T14:24:56.3716758Z [!] Checking TLS_STATUS: ContextualWisdomLab
strix UNKNOWN STEP 2026-08-14T14:24:56.5006413Z [!] TLS_NOT_ENABLED: ContextualWisdomLab
strix UNKNOWN STEP 2026-08-14T14:24:56.9175848Z ✅ Checksum verification passed. checksum=4b14d8a3a5fbcef95af55e0c54d3bee6f44da802878c10289a4ca0b79b6d0237
strix UNKNOWN STEP 2026-08-14T14:24:56.9252895Z [command]/usr/bin/tar xz --warning=no-unknown-keyword --overwrite -C /home/runner/work/_temp/c578d995-87a2-4798-a111-437b83c4e8d9 -f /home/runner/work/_temp/a172ab9a-064e-4117-8dee-9104e53cf1a7
strix UNKNOWN STEP 2026-08-14T14:25:01.5050040Z Initialized
strix UNKNOWN STEP 2026-08-14T14:25:01.5239698Z ##[group]Run step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920
strix UNKNOWN STEP 2026-08-14T14:25:01.5240074Z with:
strix UNKNOWN STEP 2026-08-14T14:25:01.5240269Z egress-policy: audit
strix UNKNOWN STEP 2026-08-14T14:25:01.5240505Z disable-file-monitoring: true
strix UNKNOWN STEP 2026-08-14T14:25:01.5242691Z token: [REDACTED]
strix UNKNOWN STEP 2026-08-14T14:25:01.5242892Z disable-telemetry: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5243103Z disable-sudo: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5243316Z disable-sudo-and-containers: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5243555Z use-policy-store: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5243772Z deploy-on-self-hosted-vm: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5243994Z env:
strix UNKNOWN STEP 2026-08-14T14:25:01.5244183Z FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
strix UNKNOWN STEP 2026-08-14T14:25:01.5244436Z STATE_disableSudo: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5244661Z STATE_disableSudoAndContainers: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5244931Z STATE_monitorStatusCode: 200
strix UNKNOWN STEP 2026-08-14T14:25:01.5245152Z STATE_addSummary: true
strix UNKNOWN STEP 2026-08-14T14:25:01.5245630Z STATE_correlation_id: cfabb5ae-3922-4e6d-8d22-804e33c4aac1
strix UNKNOWN STEP 2026-08-14T14:25:01.5245912Z STATE_isTLS: false
strix UNKNOWN STEP 2026-08-14T14:25:01.5246105Z ##[endgroup]
strix UNKNOWN STEP 2026-08-14T14:25:01.5884589Z [harden-runner] main-step
strix UNKNOWN STEP 2026-08-14T14:25:01.5889209Z ^[[32mView security insights and recommended policy at:^[[0m
strix UNKNOWN STEP 2026-08-14T14:25:01.5890055Z https://app.stepsecurity.io/github/ContextualWisdomLab/.github/actions/runs/31806061284
strix UNKNOWN STEP 2026-08-14T14:25:01.6114732Z ##[group]Run actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
strix UNKNOWN STEP 2026-08-14T14:25:01.6115476Z with:
strix UNKNOWN STEP 2026-08-14T14:25:01.6115766Z python-version: 3.13
strix UNKNOWN STEP 2026-08-14T14:25:01.6116102Z check-latest: false
strix UNKNOWN STEP 2026-08-14T14:25:01.6120063Z token: [REDACTED]
... truncated 2934 middle log lines ...
strix UNKNOWN STEP 2026-08-14T15:11:03.3230786Z Fri, 14 Aug 2026 15:00:47 GMT:domain resolved: [REDACTED].io., ip address: 32.184.221.89, TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3231398Z Fri, 14 Aug 2026 15:00:50 GMT:domain resolved: [REDACTED]., ip address: 140.82.113.23, TTL: 60
strix UNKNOWN STEP 2026-08-14T15:11:03.3232019Z Fri, 14 Aug 2026 15:01:27 GMT:domain resolved: [REDACTED].com., ip address: 75.2.113.119, TTL: 300
strix UNKNOWN STEP 2026-08-14T15:11:03.3232600Z Fri, 14 Aug 2026 15:01:27 GMT:endpoint called ip address:port 75.2.113.119:443, domain: [REDACTED].com., pid: 8814, process: python3.13
strix UNKNOWN STEP 2026-08-14T15:11:03.3233280Z Fri, 14 Aug 2026 15:02:20 GMT:domain resolved: [REDACTED]., ip address: 140.82.113.23, TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3233873Z Fri, 14 Aug 2026 15:02:56 GMT:domain resolved: us.i.posthog.com., ip address: 44.222.47.131, TTL: 58
strix UNKNOWN STEP 2026-08-14T15:11:03.3234351Z Fri, 14 Aug 2026 15:02:56 GMT:domain resolved: [REDACTED].sh., ip address: 54.[REDACTED], TTL: 60
strix UNKNOWN STEP 2026-08-14T15:11:03.3234965Z Fri, 14 Aug 2026 15:03:50 GMT:domain resolved: [REDACTED]., ip address: 140.82.112.24, TTL: 59
strix UNKNOWN STEP 2026-08-14T15:11:03.3235820Z Fri, 14 Aug 2026 15:04:17 GMT:domain resolved: [REDACTED]., ip address: 140.82.112.23, TTL: 54
strix UNKNOWN STEP 2026-08-14T15:11:03.3236511Z Fri, 14 Aug 2026 15:05:20 GMT:domain resolved: [REDACTED]., ip address: 140.82.114.23, TTL: 58
strix UNKNOWN STEP 2026-08-14T15:11:03.3237255Z Fri, 14 Aug 2026 15:05:20 GMT:domain resolved: [REDACTED].io., ip address: 44.[REDACTED], TTL: 41
strix UNKNOWN STEP 2026-08-14T15:11:03.3237887Z Fri, 14 Aug 2026 15:06:50 GMT:domain resolved: [REDACTED]., ip address: 140.82.114.23, TTL: 60
strix UNKNOWN STEP 2026-08-14T15:11:03.3238553Z Fri, 14 Aug 2026 15:06:50 GMT:domain resolved: [REDACTED].io., ip address: 32.184.221.89, TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3239477Z Fri, 14 Aug 2026 15:06:50 GMT:endpoint called ip address:port 140.82.114.23:443, domain: [REDACTED]., pid: 1892, process: hosted-compute-agent
strix UNKNOWN STEP 2026-08-14T15:11:03.3240313Z Fri, 14 Aug 2026 15:08:20 GMT:domain resolved: [REDACTED]., ip address: 140.82.113.24, TTL: 60
strix UNKNOWN STEP 2026-08-14T15:11:03.3240938Z Fri, 14 Aug 2026 15:08:20 GMT:domain resolved: [REDACTED].io., ip address: 44.[REDACTED], TTL: 48
strix UNKNOWN STEP 2026-08-14T15:11:03.3241450Z Fri, 14 Aug 2026 15:08:34 GMT:domain resolved: [REDACTED].com., ip address: 99.83.136.103, TTL: 300
strix UNKNOWN STEP 2026-08-14T15:11:03.3242065Z Fri, 14 Aug 2026 15:09:50 GMT:domain resolved: [REDACTED]., ip address: 140.82.112.23, TTL: 46
strix UNKNOWN STEP 2026-08-14T15:11:03.3242679Z Fri, 14 Aug 2026 15:09:50 GMT:domain resolved: [REDACTED].io., ip address: 44.[REDACTED], TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3243261Z Fri, 14 Aug 2026 15:10:17 GMT:domain resolved: [REDACTED]., ip address: 140.82.113.24, TTL: 44
strix UNKNOWN STEP 2026-08-14T15:11:03.3243816Z Fri, 14 Aug 2026 15:10:56 GMT:domain resolved: us.i.posthog.com., ip address: 52.6.181.181, TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3244351Z Fri, 14 Aug 2026 15:10:56 GMT:endpoint called ip address:port 52.6.181.181:443, domain: us.i.posthog.com., pid: 8814, process: python3.13
strix UNKNOWN STEP 2026-08-14T15:11:03.3244915Z Fri, 14 Aug 2026 15:10:56 GMT:domain resolved: [REDACTED].sh., ip address: 34.[REDACTED], TTL: 60
strix UNKNOWN STEP 2026-08-14T15:11:03.3245675Z Fri, 14 Aug 2026 15:10:56 GMT:endpoint called ip address:port 34.[REDACTED]:443, domain: [REDACTED].sh., pid: 8814, process: python3.13
strix UNKNOWN STEP 2026-08-14T15:11:03.3246338Z Fri, 14 Aug 2026 15:11:00 GMT:domain resolved: [REDACTED].com., ip address: 140.82.114.22, TTL: 45
strix UNKNOWN STEP 2026-08-14T15:11:03.3247044Z Fri, 14 Aug 2026 15:11:01 GMT:endpoint called ip address:port 140.82.114.22:443, domain: [REDACTED].com., pid: 13371, process: node
strix UNKNOWN STEP 2026-08-14T15:11:03.3247752Z Fri, 14 Aug 2026 15:11:01 GMT:domain resolved: [REDACTED].windows.net., ip address: 20.209.226.1, TTL: 30
strix UNKNOWN STEP 2026-08-14T15:11:03.3248463Z Fri, 14 Aug 2026 15:11:01 GMT:endpoint called ip address:port 140.82.114.22:443, domain: [REDACTED].com., pid: 1999, process: Runner.Worker
strix UNKNOWN STEP 2026-08-14T15:11:03.3249371Z Fri, 14 Aug 2026 15:11:01 GMT:endpoint called ip address:port 20.209.226.1:443, domain: [REDACTED].windows.net., pid: 13371, process: node
strix UNKNOWN STEP 2026-08-14T15:11:03.3250395Z Fri, 14 Aug 2026 15:11:01 GMT:endpoint called ip address:port 20.209.226.1:443, domain: [REDACTED].windows.net., pid: 1999, process: Runner.Worker
strix UNKNOWN STEP 2026-08-14T15:11:03.3251142Z
strix UNKNOWN STEP 2026-08-14T15:11:03.3251299Z Fri, 14 Aug 2026 15:11:02 GMT:post_event called
strix UNKNOWN STEP 2026-08-14T15:11:03.3251559Z
strix UNKNOWN STEP 2026-08-14T15:11:03.3251664Z status:
strix UNKNOWN STEP 2026-08-14T15:11:03.3251915Z Initialized
strix UNKNOWN STEP 2026-08-14T15:11:03.3260493Z agent.service log:
strix UNKNOWN STEP 2026-08-14T15:11:03.3261311Z Aug 14 14:24:58 runnervmzvulz systemd[1]: /etc/systemd/system/agent.service:9: Standard output type syslog is obsolete, automatically updating to journal. Please update your unit file, and consider removing the setting altogether.
strix UNKNOWN STEP 2026-08-14T15:11:03.3262450Z Aug 14 14:24:58 runnervmzvulz systemd[1]: /etc/systemd/system/agent.service:10: Standard output type syslog is obsolete, automatically updating to journal. Please update your unit file, and consider removing the setting altogether.
strix UNKNOWN STEP 2026-08-14T15:11:03.3263339Z Aug 14 14:24:58 runnervmzvulz systemd[1]: Started agent.service - Agent.
strix UNKNOWN STEP 2026-08-14T15:11:03.3264086Z Aug 14 14:24:59 runnervmzvulz sudo[2134]: root : *** ; USER=root ; COMMAND=/usr/bin/systemctl stop systemd-resolved
strix UNKNOWN STEP 2026-08-14T15:11:03.3264649Z Aug 14 14:24:59 runnervmzvulz sudo[2134]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3265155Z Aug 14 14:24:59 runnervmzvulz sudo[2134]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3266093Z Aug 14 14:24:59 runnervmzvulz sudo[2140]: root : *** ; USER=root ; COMMAND=/usr/bin/systemctl restart systemd-resolved
strix UNKNOWN STEP 2026-08-14T15:11:03.3266690Z Aug 14 14:24:59 runnervmzvulz sudo[2140]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3267229Z Aug 14 14:24:59 runnervmzvulz sudo[2140]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3267781Z Aug 14 14:24:59 runnervmzvulz sudo[2146]: root : *** ; USER=root ; COMMAND=/usr/bin/resolvectl flush-caches
strix UNKNOWN STEP 2026-08-14T15:11:03.3268288Z Aug 14 14:24:59 runnervmzvulz sudo[2146]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3268790Z Aug 14 14:24:59 runnervmzvulz sudo[2146]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3269328Z Aug 14 14:24:59 runnervmzvulz sudo[2149]: root : *** ; USER=root ; COMMAND=/usr/bin/systemctl reload docker
strix UNKNOWN STEP 2026-08-14T15:11:03.3269841Z Aug 14 14:24:59 runnervmzvulz sudo[2149]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3270313Z Aug 14 14:24:59 runnervmzvulz sudo[2149]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3270811Z Aug 14 14:24:59 runnervmzvulz sudo[2159]: root : *** ; USER=root ; COMMAND=/usr/bin/systemctl daemon-reload
strix UNKNOWN STEP 2026-08-14T15:11:03.3271304Z Aug 14 14:24:59 runnervmzvulz sudo[2159]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3272147Z Aug 14 14:24:59 runnervmzvulz systemd[1]: /etc/systemd/system/agent.service:9: Standard output type syslog is obsolete, automatically updating to journal. Please update your unit file, and consider removing the setting altogether.
strix UNKNOWN STEP 2026-08-14T15:11:03.3273268Z Aug 14 14:24:59 runnervmzvulz systemd[1]: /etc/systemd/system/agent.service:10: Standard output type syslog is obsolete, automatically updating to journal. Please update your unit file, and consider removing the setting altogether.
strix UNKNOWN STEP 2026-08-14T15:11:03.3274127Z Aug 14 14:24:59 runnervmzvulz sudo[2159]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3274668Z Aug 14 14:24:59 runnervmzvulz sudo[2225]: root : *** ; USER=root ; COMMAND=/usr/bin/systemctl restart docker
strix UNKNOWN STEP 2026-08-14T15:11:03.3275169Z Aug 14 14:24:59 runnervmzvulz sudo[2225]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
strix UNKNOWN STEP 2026-08-14T15:11:03.3275764Z Aug 14 14:25:00 runnervmzvulz sudo[2225]: pam_unix(sudo:session): session closed for user root
strix UNKNOWN STEP 2026-08-14T15:11:03.3276488Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Fetching custom detection rules module=armour api_url=https://[REDACTED].io/v1 repo=ContextualWisdomLab/.github
strix UNKNOWN STEP 2026-08-14T15:11:03.3277274Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Custom detection rules evaluator initialized module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3277960Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Detection manager started module=detection-manager workers=4 buffer_size=1000
strix UNKNOWN STEP 2026-08-14T15:11:03.3278639Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Selected Armour variant module=armour variant=fmod_ret
strix UNKNOWN STEP 2026-08-14T15:11:03.3279221Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Config module=armour ENFORCE_KILL_BLOCK=true
strix UNKNOWN STEP 2026-08-14T15:11:03.3279772Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Config module=armour AGENT_PID=2120
strix UNKNOWN STEP 2026-08-14T15:11:03.3280470Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Config module=armour ENFORCE_READ_BLOCK=false
strix UNKNOWN STEP 2026-08-14T15:11:03.3281041Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Config module=armour ENFORCE_WRITE_BLOCK=false
strix UNKNOWN STEP 2026-08-14T15:11:03.3281585Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour events=16384
strix UNKNOWN STEP 2026-08-14T15:11:03.3282229Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour protected_pids=1
strix UNKNOWN STEP 2026-08-14T15:11:03.3282775Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour protected_pid_inodes=1
strix UNKNOWN STEP 2026-08-14T15:11:03.3283351Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour protected_bpf_ids=9
strix UNKNOWN STEP 2026-08-14T15:11:03.3283938Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour protected_fs_inodes=6
strix UNKNOWN STEP 2026-08-14T15:11:03.3284519Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Map size module=armour protected_proc_fs_inodes=2
strix UNKNOWN STEP 2026-08-14T15:11:03.3285090Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO ProtectedPids module=armour pids=map[2121:2120]
strix UNKNOWN STEP 2026-08-14T15:11:03.3285865Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO ProtectedBPFIDs module=armour ids="[20 18 14 21 19]"
strix UNKNOWN STEP 2026-08-14T15:11:03.3286510Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:24 Inode:13889}" path=/proc/1999/mem
strix UNKNOWN STEP 2026-08-14T15:11:03.3287197Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:24 Inode:16245}" path=/proc/1980/mem
strix UNKNOWN STEP 2026-08-14T15:11:03.3287898Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:769 Inode:90277}" path=/etc/sudoers.d/runner
strix UNKNOWN STEP 2026-08-14T15:11:03.3289010Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:28 Inode:900}" path=/etc/resolv.conf
strix UNKNOWN STEP 2026-08-14T15:11:03.3289977Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:769 Inode:508}" path=/etc/systemd/resolved.conf
strix UNKNOWN STEP 2026-08-14T15:11:03.3291103Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO File Info module=armour inoKey="{Device:769 Inode:323628}" path=/etc/docker/daemon.json
strix UNKNOWN STEP 2026-08-14T15:11:03.3292161Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Protection maps populated module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3293054Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Protection maps are freezed module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3293831Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Linking completed module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3294387Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Armour engaged module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3295056Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO RingBuffer created module=armour size=16384
strix UNKNOWN STEP 2026-08-14T15:11:03.3295860Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO Listening for events module=armour
strix UNKNOWN STEP 2026-08-14T15:11:03.3296431Z Aug 14 14:25:01 runnervmzvulz agentservice[2120]: 2026/08/14 14:25:01 INFO [LOCKDOWN] Runner.Worker PID set module=armour pid=1999
strix UNKNOWN STEP 2026-08-14T15:11:03.3296773Z
strix UNKNOWN STEP 2026-08-14T15:11:03.5076695Z Cleaning up orphan processes
Failed check: Close Empty PR/close-empty
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805987919/job/94784913996
- Workflow run id:
31805987919 - Check run id:
94784913996
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for close-empty-pr-ContextualWisdomLab/.github-931 exists
Failed check: CodeQL PR/Detect CodeQL languages
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805990062/job/94784921219
- Workflow run id:
31805990062 - Check run id:
94784921219
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for codeql-pr-ContextualWisdomLab/.github-931 exists
Failed check: OSV-Scanner PR/osv-scan / osv-scan
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805990371/job/94784922100
- Workflow run id:
31805990371 - Check run id:
94784922100
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for osv-scanner-pr-ContextualWisdomLab/.github-931 exists
Failed check: Python Security/Detect Python
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989847/job/94784919826
- Workflow run id:
31805989847 - Check run id:
94784919826
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for python-security-ContextualWisdomLab/.github-931 exists
Failed check: SAST Semgrep/Semgrep (multi-language SAST)
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989820/job/94784919906
- Workflow run id:
31805989820 - Check run id:
94784919906
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for sast-semgrep-ContextualWisdomLab/.github-931 exists
Failed check: SBOM Generation/generate-sbom
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989871/job/94784919902
- Workflow run id:
31805989871 - Check run id:
94784919902
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for sbom-generation-ContextualWisdomLab/.github-931 exists
Failed check: Scorecard PR/Scorecard
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989867/job/94784920193
- Workflow run id:
31805989867 - Check run id:
94784920193
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for scorecard-pr-ContextualWisdomLab/.github-931 exists
Failed check: Secret Scan/gitleaks (secret scan)
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989946/job/94784920064
- Workflow run id:
31805989946 - Check run id:
94784920064
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for secret-scan-ContextualWisdomLab/.github-931 exists
Failed check: Security Scan/osv-scan
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989826/job/94784919543
- Workflow run id:
31805989826 - Check run id:
94784919543
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for security-scan-ContextualWisdomLab/.github-931 exists
Failed check: Strix Security Scan/strix
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805987786/job/94784914146
- Workflow run id:
31805987786 - Check run id:
94784914146
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for strix-pull_request_target-ContextualWisdomLab/.github-pr-931 exists
Failed check: Python Security/Bandit (Python SAST)
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989847/job/94785152167
- Workflow run id:
31805989847 - Check run id:
94785152167
Failed check: Security Scan/dependency-review
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989826/job/94784919605
- Workflow run id:
31805989826 - Check run id:
94784919605
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for security-scan-ContextualWisdomLab/.github-931 exists
Failed check: Strix Security Scan/publish-manual-pr-evidence-status
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805987786/job/94785153607
- Workflow run id:
31805987786 - Check run id:
94785153607
Failed check: Python Security/pip-audit (Python dependency audit)
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989847/job/94785152654
- Workflow run id:
31805989847 - Check run id:
94785152654
Failed check: Security Scan/trivy-fs
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989826/job/94784919677
- Workflow run id:
31805989826 - Check run id:
94784919677
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for security-scan-ContextualWisdomLab/.github-931 exists
Failed check: Security Scan/scorecard
- Type:
check_run - Conclusion:
CANCELLED - Details URL: https://github.com/ContextualWisdomLab/.github/actions/runs/31805989826/job/94784919534
- Workflow run id:
31805989826 - Check run id:
94784919534
Check annotations
- .github:1-1 [failure] Canceling since a higher priority waiting request for security-scan-ContextualWisdomLab/.github-931 exists
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (4 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (4 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
Evidence --> S3["CI script (3 files)"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script (3 files)"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (12 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (12 files)"]
R4 --> V4["targeted test run"]
|
Exact-current-head read-only review request for A non-destructive forward commit restored the exact previously bounded sandbox path/output tree; GitHub compare reports zero changed files from @opencode-agent review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
target='c2407e92d9f626bec76e0cb6c3e72a73f976648e'
base='6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba'
repo='ContextualWisdomLab/.github'
printf '%s\n' '== Identity and scope =='
printf 'checked-out HEAD: '; git rev-parse HEAD
printf 'target: '; git cat-file -t "$target"
printf 'base: '; git cat-file -t "$base"
printf 'merge-base: '; git merge-base "$target" "$base"
git diff --name-status "$base" "$target"
printf '%s\n' '== Compare with cited predecessor =='
git diff --name-status 'dd2132b5aedc56859ffa81568d42ab9e81e52b65' "$target" || true
printf '%s\n' '== Production outlines =='
for file in scripts/ci/bounded_subprocess.py scripts/ci/sandboxed_verify.py scripts/ci/sandboxed_web_e2e.py; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --view expanded
done
printf '%s\n' '== Boundary implementation =='
rg -n -C 5 \
'DEFAULT_COMMAND_OUTPUT_LIMIT_BYTES|DEFAULT_SERVICE_LOG_LIMIT_BYTES|RepositoryPathBoundaryError|validate_repository_symlinks|copy_workspace\(|PATH_BOUNDARY_EXIT_CODE|path_boundary_rejected|OutputLimitUnsupportedError|output_limit_unsupported|output_limited|run_bounded_command|kill_process_group|start_new_session|finalize|join\(|read_bounded_suffix|wait_for_url' \
scripts/ci/bounded_subprocess.py \
scripts/ci/sandboxed_verify.py \
scripts/ci/sandboxed_web_e2e.py
printf '%s\n' '== Focused test inventory and assertions =='
fd -t f '^test_(bounded_subprocess|sandboxed_verify|sandboxed_web_e2e|sandboxed_service_capture_startup|sandboxed_entrypoint_and_cleanup_coverage)' tests \
-x sh -c 'printf "\n-- %s --\n" "$1"; ast-grep outline "$1" --items all --view compact' sh {}
rg -n -C 3 \
'RepositoryPathBoundaryError|path_boundary_rejected|PATH_BOUNDARY_EXIT_CODE|output_limit_unsupported|output_limited|DEFAULT_COMMAND_OUTPUT_LIMIT_BYTES|DEFAULT_SERVICE_LOG_LIMIT_BYTES|read_bounded_suffix|join\(|kill_process_group|unsupported|timeout|readiness|symlink' \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_sandboxed_entrypoint_and_cleanup_coverage.py
printf '%s\n' '== Documentation limitations =='
rg -n -C 4 -i \
'pre-execution|runtime|limitation|does not|not.*contain|symlink|suffix|process group|reader|join|1 MiB|4 MiB|123|124|125|126' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.md
printf '%s\n' '== Current requested-head check state =='
gh api "repos/$repo/commits/$target/check-runs?per_page=100" \
--jq '.check_runs[] | [.name,.status,.conclusion,.head_sha] | `@tsv`' || trueLength of output: 64515 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Web E2E main control flow =='
nl -ba scripts/ci/sandboxed_web_e2e.py | sed -n '268,452p'
printf '%s\n' '== Focused test definitions =='
for file in \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_entrypoint_and_cleanup_coverage.py; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --view signatures
done
printf '%s\n' '== Required regression assertions =='
rg -n -C 4 \
'RepositoryPathBoundaryError|path_boundary_rejected|PATH_BOUNDARY_EXIT_CODE|output_limit_unsupported|OutputLimitUnsupportedError|output_limited|no.*command|start_service|run_shell|returncode.{0,20}(123|124|125|126)|exit_code.{0,20}(123|124|125|126)|read_bounded_suffix|DEFAULT_(COMMAND_OUTPUT|SERVICE_LOG)_LIMIT_BYTES|join\(' \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_entrypoint_and_cleanup_coverage.py
printf '%s\n' '== Documentation limitations =='
rg -n -C 4 -i \
'pre-execution|runtime|limitation|does not|not.*contain|symlink|suffix|process group|reader|join|1 MiB|4 MiB|123|124|125|126' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.md
printf '%s\n' '== Exact requested-head check state =='
gh api 'repos/ContextualWisdomLab/.github/commits/c2407e92d9f626bec76e0cb6c3e72a73f976648e/check-runs?per_page=100' \
--jq '.check_runs[] | [.name,.status,.conclusion,.head_sha] | `@tsv`' || trueLength of output: 2568 🏁 Script executed: #!/bin/bash
set -u
printf '%s\n' '== Web E2E main control flow =='
cat -n scripts/ci/sandboxed_web_e2e.py | sed -n '268,452p' || true
printf '%s\n' '== Focused test definitions =='
for file in \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_entrypoint_and_cleanup_coverage.py; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --view signatures || true
done
printf '%s\n' '== Required regression assertions =='
rg -n -C 4 \
'RepositoryPathBoundaryError|path_boundary_rejected|PATH_BOUNDARY_EXIT_CODE|output_limit_unsupported|OutputLimitUnsupportedError|output_limited|start_service|run_shell|returncode.{0,20}(123|124|125|126)|exit_code.{0,20}(123|124|125|126)|read_bounded_suffix|DEFAULT_(COMMAND_OUTPUT|SERVICE_LOG)_LIMIT_BYTES|join\(' \
tests/test_sandboxed_verify_symlink_boundary.py \
tests/test_sandboxed_verify_output_limits.py \
tests/test_sandboxed_web_e2e.py \
tests/test_sandboxed_web_e2e_branch_contract.py \
tests/test_sandboxed_web_e2e_output_limits.py \
tests/test_bounded_subprocess.py \
tests/test_bounded_subprocess_contract.py \
tests/test_bounded_subprocess_capture_startup.py \
tests/test_sandboxed_service_capture_startup.py \
tests/test_sandboxed_entrypoint_and_cleanup_coverage.py || true
printf '%s\n' '== Documentation limitations =='
rg -n -C 4 -i \
'pre-execution|runtime|limitation|does not|not.*contain|symlink|suffix|process group|reader|join|1 MiB|4 MiB|123|124|125|126' \
docs/doctoring/sandboxed-output-resource-bounds.md \
docs/doctoring/sandboxed-verification-symlink-boundary.md || true
printf '%s\n' '== Exact requested-head check state =='
gh api 'repos/ContextualWisdomLab/.github/commits/c2407e92d9f626bec76e0cb6c3e72a73f976648e/check-runs?per_page=100' \
--jq '.check_runs[] | [.name,.status,.conclusion,.head_sha] | `@tsv`' || trueLength of output: 91837
The requested head is identical to Semantic findings
Verified controls
Readiness statusThe exact-head checks are queued or in progress. The completed administrative checks are skipped or cancelled. This is not passing readiness evidence. This source review does not grant approval, merge authority, or independent human approval. You are interacting with an AI system. |
There was a problem hiding this comment.
Pull request overview
OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.
Findings
1. HIGH Current-head GitHub Checks - Fix failed required checks before approval
- Problem: Failed same-head checks remain for
c2407e92d9f626bec76e0cb6c3e72a73f976648e. - Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
- Fix: Read and fix the failed check logs below, then rerun the current-head checks.
- Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.
Failed checks:
- Strix Security Scan/strix: FAILURE (https://github.com/ContextualWisdomLab/.github/actions/runs/31886111940/job/95015544222)
- Strix Security Scan/strix: failure (https://github.com/ContextualWisdomLab/.github/actions/runs/31886111940/job/95015544222)
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: CHANGELOG.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
Evidence --> S3["CI script (3 files)"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script (3 files)"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (11 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (11 files)"]
R4 --> V4["targeted test run"]
There was a problem hiding this comment.
Pull request overview
OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.
Findings
1. HIGH Current-head GitHub Checks - Fix failed required checks before approval
- Problem: Failed same-head checks remain for
c2407e92d9f626bec76e0cb6c3e72a73f976648e. - Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
- Fix: Read and fix the failed check logs below, then rerun the current-head checks.
- Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.
Failed checks:
- Strix Security Scan/strix: FAILURE (https://github.com/ContextualWisdomLab/.github/actions/runs/31886111940/job/95015544222)
- Strix Security Scan/strix: failure (https://github.com/ContextualWisdomLab/.github/actions/runs/31886111940/job/95015544222)
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: CHANGELOG.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: CHANGELOG.md"]
R1 --> V1["required checks"]
Evidence --> S2["Docs (2 files)"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs (2 files)"]
R2 --> V2["docs review"]
Evidence --> S3["CI script (3 files)"]
S3 --> I3["review and security gate shell path"]
I3 --> R3["Review risk: CI script (3 files)"]
R3 --> V3["bash -n plus Strix self-test"]
Evidence --> S4["Test (11 files)"]
S4 --> I4["regression suite"]
I4 --> R4["Review risk: Test (11 files)"]
R4 --> V4["targeted test run"]
Replay the unique symlink-boundary and bounded-subprocess contract onto current main so copied workspaces cannot escape and evidence capture cannot exhaust parent resources.
c2407e9 to
19fa59f
Compare
Buyer and security outcome
This Ready change closes two repository-owned availability and filesystem boundaries in the central sandbox wrappers without weakening execution, review, or merge policy:
Issue #766 remains open until protected integration and protected-main operational acceptance. Credential-redaction work remains independently gated.
Exact identity and scope repair
main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba;dd2132b5aedc56859ffa81568d42ab9e81e52b65;c2407e92d9f626bec76e0cb6c3e72a73f976648e;After the bounded security tree, unrelated central AGENTS/Architecture/CLAUDE and trusted-lock installer-test changes entered this branch. A non-destructive forward commit now points to the exact previously bounded tree. GitHub compare reports zero changed files between
dd2132b5...and the current head. No force-push, rebase, history rewrite, predecessor evidence transfer, or gate weakening was used.Every predecessor check, review, approval, or generated merge result is historical only. Current-head evidence must regenerate.
Symlink containment
copy_workspacevalidates the copied tree after ignore rules are applied. Absolute links and relative links resolving outside the copied repository fail closed. Internal relative links remain links; ignored paths do not create false positives. This is filesystem containment, not an operating-system or network sandbox claim.The original RED commit was
faca1f145f237ce7b561218d707a40ae33471b88; the ignored-path regression was preserved at6f597306a7414e4ab027af42c8d8672f8da8de39.Output-resource boundary
The first failing boundary was retention: complete stdout/stderr streams were buffered in parent memory, service logs were unbounded, and tails read complete files before selecting final lines.
The bounded repair provides:
shell=False,start_new_session=True, and whole-process-group termination on first overflow;123resource,124timeout,125readiness, and126copied-workspace path rejection, with timeout precedence;Process-wide file-size limits, post-hoc truncation, prefix-only retention, and silent non-POSIX fallback were rejected because they do not change the causal boundary safely.
Test-first and quality evidence
The branch records RED heads for path containment and the absent bounded runner. The predecessor bounded tree completed focused flood/cleanup/path tests, the complete central suite, exact 100% owned production statement/branch coverage, complete changed public docstrings, compilation, and diff checks. Those results are lineage only.
The current head must regenerate every applicable exact-head quality, security, supply-chain, and semantic-review result. Pending, queued, skipped, cancelled, absent, stale, predecessor-head, local-only, author-only, status-only, synthetic, or model-only evidence is not acceptance.
Limitations and acceptance
This slice does not cap repository-copy size, application artifacts, CPU beyond existing timeouts, process count, address space, network traffic, or unrelated processes. A descendant creating a new session can escape process-group termination, but finite reader joins convert retained descriptors into deterministic failure rather than an unbounded wait.
Merge or auto-merge only after the unchanged current head has terminal-success required gates, zero valid unresolved findings, a qualifying current-head semantic verdict, two qualifying independent non-author approvals including last-push approval, compatible live-base evidence, and ordinary expected-head branch-protection authorization. After protected integration, run command and service flood canaries before closing #766. No self-approval, administrative bypass, synthetic approval, or protection weakening is requested.