Skip to content

๐Ÿ›ก๏ธ Sentinel: [MEDIUM] Fix stack trace exposure in CLI#27

Closed
seonghobae wants to merge 2 commits into
mainfrom
sentinel/fix-cli-error-handling-18110910922933163585
Closed

๐Ÿ›ก๏ธ Sentinel: [MEDIUM] Fix stack trace exposure in CLI#27
seonghobae wants to merge 2 commits into
mainfrom
sentinel/fix-cli-error-handling-18110910922933163585

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

๐Ÿšจ Severity: MEDIUM
๐Ÿ’ก Vulnerability: CLI ๋„๊ตฌ์—์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜(์˜ˆ: ํŒŒ์ผ ๋ฏธ์กด์žฌ, ๊ฒ€์ฆ ์‹คํŒจ) ๋ฐœ์ƒ ์‹œ ๋‚ด๋ถ€ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค๊ฐ€ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ๋˜๋Š” ์ทจ์•ฝ์  ์กด์žฌ (Stack trace leakage).
๐ŸŽฏ Impact: ๋‚ด๋ถ€ ์‹œ์Šคํ…œ ๊ฒฝ๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒํƒœ, ์ฝ”๋“œ ๊ตฌ์กฐ ๋“ฑ ๋ฏผ๊ฐํ•œ ์ •๋ณด๊ฐ€ ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์Œ.
๐Ÿ”ง Fix: python/fast_mlsirm/cli.py ํŒŒ์ผ ๋‚ด์˜ main ๋ช…๋ น ์‹คํ–‰ ๋กœ์ง์„ try...except Exception as e ๋ธ”๋ก์œผ๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ํฌ์ฐฉํ•˜๊ณ  ์•ˆ์ „ํ•œ ๋ฒ”์šฉ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ sys.stderr๋กœ ์ถœ๋ ฅํ•˜๊ฒŒ ์ˆ˜์ •ํ•จ.
โœ… Verification: python test_error_catch.py ๋ฐ fast-mlsirm fit --responses not_exist.npy ... ๋ช…๋ น์–ด๋กœ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ธ์ˆ˜๋ฅผ ์ฃผ์ž…ํ–ˆ์„ ๋•Œ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ๋Œ€์‹  ๊น”๋”ํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(โŒ Error: ...)๊ฐ€ ์ถœ๋ ฅ๋จ์„ ํ™•์ธ ์™„๋ฃŒํ•จ. ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ๋„ ์ •์ƒ ๋™์ž‘ ํ†ต๊ณผ(pytest tests/).


PR created automatically by Jules for task 18110910922933163585 started by @seonghobae

@google-labs-jules

Copy link
Copy Markdown

๐Ÿ‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a ๐Ÿ‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@opencode-agent

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: df4580b7f9a112ab1c8ab43e8adcf976e49199e8
  • Workflow run: 28425993960
  • Workflow attempt: 1
  • Gate result: CHECK_FAILED (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Check outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The OpenCode approval path reached an APPROVE control result while the separate coverage-evidence job result was failure.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, but leave the PR review unchanged for coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence.

  • Result: CHECK_FAILED

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head df4580b7f9a112ab1c8ab43e8adcf976e49199e8.

  • Head SHA: df4580b7f9a112ab1c8ab43e8adcf976e49199e8

  • Workflow run: 28425993960

  • Workflow attempt: 1

Coverage evidence

Coverage Evidence

  • Head SHA: df4580b7f9a112ab1c8ab43e8adcf976e49199e8
  • Required test evidence: supported repository test suites must pass.
  • Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.

Python project dependencies (.)

Using CPython 3.12.3 interpreter at: /usr/bin/python3
Creating virtual environment at: .venv
Resolved 13 packages in 442ms
   Building fast-mlsirm @ file:///home/runner/work/fast-mlsirm/fast-mlsirm/pr-head
Downloading numpy (15.9MiB)
Downloading pygments (1.2MiB)
 Downloaded pygments
 Downloaded numpy
      Built fast-mlsirm @ file:///home/runner/work/fast-mlsirm/fast-mlsirm/pr-head
Prepared 7 packages in 1.18s
Installed 7 packages in 17ms
 + fast-mlsirm==0.1.0 (from file:///home/runner/work/fast-mlsirm/fast-mlsirm/pr-head)
 + iniconfig==2.3.0
 + numpy==2.5.0
 + packaging==26.2
 + pluggy==1.6.0
 + pygments==2.20.0
 + pytest==9.1.1
  • Result: PASS

Python coverage with missing-line report (.)

Installed 6 packages in 9ms
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.1.1, pluggy-1.6.0
rootdir: /home/runner/work/fast-mlsirm/fast-mlsirm/pr-head
configfile: pyproject.toml
collected 36 items

tests/test_config.py ..................                                  [ 50%]
tests/test_diagnostics.py ....                                           [ 61%]
tests/test_fit_pipeline.py ..                                            [ 66%]
tests/test_math.py .......                                               [ 86%]
tests/test_objective.py ...                                              [ 94%]
tests/test_simulation.py ..                                              [100%]

============================== 36 passed in 0.47s ==============================
Installed 1 package in 3ms
Name                                Stmts   Miss  Cover   Missing
-----------------------------------------------------------------
python/fast_mlsirm/__init__.py          6      0   100%
python/fast_mlsirm/config.py           78      0   100%
python/fast_mlsirm/diagnostics.py      54      2    96%   33, 104
python/fast_mlsirm/fit.py             200     70    65%   28, 38, 70-74, 139, 168, 208, 212-213, 227-275, 284-299
python/fast_mlsirm/math.py             36      0   100%
python/fast_mlsirm/objective.py       109      7    94%   13, 19, 24, 26, 28, 30, 92
python/fast_mlsirm/simulation.py       29      0   100%
python/fast_mlsirm/types.py            42      0   100%
tests/test_config.py                   57      0   100%
tests/test_diagnostics.py              23      0   100%
tests/test_fit_pipeline.py             16      0   100%
tests/test_math.py                     63      0   100%
tests/test_objective.py                38      0   100%
tests/test_simulation.py               18      0   100%
-----------------------------------------------------------------
TOTAL                                 769     79    90%
Coverage failure: total of 90 is less than fail-under=100
  • Result: FAIL (exit 2)

Python docstring coverage advisory

RESULT: FAILED (minimum: 80.0%, actual: 2.0%)
  • Result: PASS

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Change Flow DAG

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (2 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (2 files)"]
  R1 --> V1["required checks"]
Loading

@seonghobae

Copy link
Copy Markdown
Contributor Author

๐Ÿค– Rebased onto latest main to clear the merge conflict.

Conflict resolution summary

  • python/fast_mlsirm/cli.py: conflicted because main (via ๐ŸŽจ Palette: [CLI DX ๊ฐœ์„ ] simulate ๋ช…๋ น์–ด ์—๋Ÿฌ ํ•ธ๋“ค๋ง ์ถ”๊ฐ€ย #93 and related work) refactored the CLI into _main() + a main() wrapper with a top-level try/except (โŒ Error: Unexpected failure - {exc}, gated by FAST_MLSIRM_DEBUG, plus KeyboardInterrupt handling) and granular per-command handlers. This already implements this PR's exact remediation (no stack-trace leakage on bad args / missing files) โ€” more comprehensively than the single whole-body try/except proposed here. To avoid forcing a duplicate, the rebase keeps main's version of cli.py verbatim; the security intent is fully preserved.
  • .jules/sentinel.md: append-only governance log โ€” both entries kept in date order (this PR's 2026-06-30 stack-trace entry + main's 2026-07-06 DoS entry).

Net effect: after rebase the only remaining diff vs main is the .jules/sentinel.md log entry; the code fix is now redundant.

Verification: python -m py_compile cli.py OK; manual bad-input run prints โŒ Error: Could not find file - ... with no traceback (exit 1); pytest tests/test_cli.py โ†’ 18 passed.

Recommendation: since main already ships this fix, consider closing this PR as redundant (or merging just for the sentinel.md learning entry). Not merging per task scope.

@google-labs-jules

Copy link
Copy Markdown

๐Ÿค– Rebased onto latest main to clear the merge conflict.

Conflict resolution summary

  • python/fast_mlsirm/cli.py: conflicted because main (via ๐ŸŽจ Palette: [CLI DX ๊ฐœ์„ ] simulate ๋ช…๋ น์–ด ์—๋Ÿฌ ํ•ธ๋“ค๋ง ์ถ”๊ฐ€ย #93 and related work) refactored the CLI into _main() + a main() wrapper with a top-level try/except (โŒ Error: Unexpected failure - {exc}, gated by FAST_MLSIRM_DEBUG, plus KeyboardInterrupt handling) and granular per-command handlers. This already implements this PR's exact remediation (no stack-trace leakage on bad args / missing files) โ€” more comprehensively than the single whole-body try/except proposed here. To avoid forcing a duplicate, the rebase keeps main's version of cli.py verbatim; the security intent is fully preserved.
  • .jules/sentinel.md: append-only governance log โ€” both entries kept in date order (this PR's 2026-06-30 stack-trace entry + main's 2026-07-06 DoS entry).

Net effect: after rebase the only remaining diff vs main is the .jules/sentinel.md log entry; the code fix is now redundant.

Verification: python -m py_compile cli.py OK; manual bad-input run prints โŒ Error: Could not find file - ... with no traceback (exit 1); pytest tests/test_cli.py โ†’ 18 passed.

Recommendation: since main already ships this fix, consider closing this PR as redundant (or merging just for the sentinel.md learning entry). Not merging per task scope.

Acknowledged. Since the fix is now redundant due to the rebased main branch, I will stop work on the code change itself but will submit the updated .jules/sentinel.md learning entry as proposed.

@seonghobae seonghobae force-pushed the sentinel/fix-cli-error-handling-18110910922933163585 branch from d51eef4 to a3ba298 Compare July 9, 2026 10:56
@seonghobae

Copy link
Copy Markdown
Contributor Author

Cleaned this PR back to its surviving scope after verifying the code remediation is already present on current main.

Current head: a3ba298
Current diff: .jules/sentinel.md only
Resolution: latest main + one security-learning entry for CLI stack trace exposure. No CLI code is changed because current main already implements the safe error-handling path.

Local verification: git diff --check reported only the existing Windows CRLF warning for .jules/sentinel.md; no generated files or lock/coverage artifacts remain in the PR diff.

Merge order note: this remains queued behind lower-numbered PR #18. I will not merge this before #18 is approved and merged.

@google-labs-jules

Copy link
Copy Markdown

๏ปฟCleaned this PR back to its surviving scope after verifying the code remediation is already present on current main.

Current head: a3ba298
Current diff: .jules/sentinel.md only
Resolution: latest main + one security-learning entry for CLI stack trace exposure. No CLI code is changed because current main already implements the safe error-handling path.

Local verification: git diff --check reported only the existing Windows CRLF warning for .jules/sentinel.md; no generated files or lock/coverage artifacts remain in the PR diff.

Merge order note: this remains queued behind lower-numbered PR #18. I will not merge this before #18 is approved and merged.

Acknowledged. I understand this PR is now clean and queued behind PR #18.

์ด ์ปค๋ฐ‹์€ ๋ฉ”์ธ ๋ธŒ๋žœ์น˜์˜ CLI ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ณ€๊ฒฝ ์‚ฌํ•ญ(์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๋‚ด๋ถ€ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ๋…ธ์ถœ ๋ฐฉ์ง€)๊ณผ ๊ด€๋ จ๋œ ๊ตํ›ˆ์„ `.jules/sentinel.md` ๋กœ๊ทธ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ ์ˆ˜์ • ์‚ฌํ•ญ ์ž์ฒด๋Š” main ๋ธŒ๋žœ์น˜์™€ ๋ณ‘ํ•ฉ ๊ณผ์ •์—์„œ ์ค‘๋ณต๋˜์–ด ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
@seonghobae

Copy link
Copy Markdown
Contributor Author

Closing instead of merging. Current main already contains the CLI stack-trace remediation, and this branch is no longer a harmless sentinel-only diff: against current main it would remove AGENTS.md governance guidance and drop the PR governance URL sanitizer helper from scripts/build_pr_queue_governance.py. Keeping the PR open would risk merging stale reverts for a fix that is already present.

@seonghobae seonghobae closed this Jul 9, 2026
@google-labs-jules

Copy link
Copy Markdown

Closing instead of merging. Current main already contains the CLI stack-trace remediation, and this branch is no longer a harmless sentinel-only diff: against current main it would remove AGENTS.md governance guidance and drop the PR governance URL sanitizer helper from scripts/build_pr_queue_governance.py. Keeping the PR open would risk merging stale reverts for a fix that is already present.

Understood. Acknowledging that this work is now obsolete and stopping work on this task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant