fix(bridge): close GLOB blocked-pattern fail-open via RE2-compatible translation#3166
fix(bridge): close GLOB blocked-pattern fail-open via RE2-compatible translation#3166Haruka-Kaya wants to merge 1 commit into
Conversation
🤖 AI Agent: docs-sync-checker — Docs Sync
Docs Sync
|
🤖 AI Agent: breaking-change-detector — API Compatibility
API Compatibility
|
🤖 AI Agent: code-reviewer — Action Items:
TL;DR: 0 blockers, 1 warning. The PR improves robustness and fixes critical fail-open issues but introduces a minor test dependency concern.
Action Items:
Warnings (fine as follow-up PRs):
|
🤖 AI Agent: contributor-guide — Actionable Items:
Welcome, and thank you for your detailed contribution! Great job on the comprehensive explanation and adding robust test coverage. Actionable Items:
For more guidance, see CONTRIBUTING.md. Let us know if you need help! |
🤖 AI Agent: security-scanner — View details
No security issues found. |
🤖 AI Agent: test-generator — `agent-governance-python/agt-policies/src/agt/policies/bridge.py`
|
PR Review Summary
Verdict: AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims. |
AI レビュー警告(テストカバレッジ)対応。_glob_to_re2 の出力を Python の 参照実装 fnmatch.fnmatchcase と突き合わせる cross-check を追加: 否定文字クラス [!ab]、メタ文字のリテラル扱い(. + のエスケープ)、未閉じ '[' のリテラル化、複数 * / ? を含むケース。挙動が glob セマンティクスを 保ったまま RE2 安全であることを保証。 Refs microsoft#3137 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VT2CfGX3tmPsQaofuuWwED
imran-siddique
left a comment
There was a problem hiding this comment.
This PR fixes three real bugs in bridge.py: a security-relevant fail-open in GLOB pattern matching, invalid Rego/JSON emission for non-finite confidence thresholds, and orphaned temp directories on failure. The fixes are correct and the new tests are thorough.\n\nCore fix - _glob_to_re2: The implementation is correct. I traced every branch manually and ran all the edge cases (unclosed brackets, negated classes, ranges, escaped chars, [^...]). All results agree with fnmatch.fnmatchcase semantics, which is the right reference. The RE2-safe output ((?s)^...$) is confirmed to avoid \Z and (?s:...).\n\nNon-finite threshold guard: math.isfinite correctly rejects inf, -inf, and nan before they reach _render_rego. The allow_nan=False backstop in _render_rego is correctly described as a defensive measure for direct callers, not redundant.\n\nTemp dir cleanup: The created_bundle_dir flag logic is sound. The mkdir call sits outside the try block, but that is safe because mkdtemp already created the directory, so mkdir(exist_ok=True) cannot fail on it.\n\nOne minor observation (no action needed): Python's re module treats $ as matching end-of-string OR before a trailing \n, while Go RE2's $ without (?m) matches end-of-text only. This means the Python-only unit tests using re.match have a slight semantic gap vs. OPA for inputs with trailing newlines. In practice this is not exploitable (policy text does not end with \n) and the OPA-backed regression test covers the real runtime. Worth knowing about but not blocking.\n\nAll required CI gates pass. The OPA regression test correctly skips when the opa binary is absent rather than failing. The test coverage for the cleanup path (test_created_bundle_dir_cleaned_up_on_failure) properly exercises the monkeypatched mkdtemp path.
|
@Haruka-Kaya thanks a lot for making this change. One request is to translate the commit message to English so others can read it easily. Otherwise the change itself looks good! |
ec04889 to
5bd8042
Compare
|
@MohammadHaroonAbuomar done — the commit message is now in English (squashed to a single commit). Heads-up: while doing that I force-pushed and my push raced with your |
MohammadHaroonAbuomar
left a comment
There was a problem hiding this comment.
CI is green and the new test_glob_to_re2_agrees_with_fnmatchcase is a good cross-check. The PR title still says "(fail-open)", which reads as if the change introduces fail-open behaviour; it eliminates one. Please retitle to e.g. fix(bridge): close GLOB blocked-pattern fail-open via RE2-compatible translation. The optional [[:posix:]] hardening (inner.replace("[", r"\[")) is still open if you want to take it; non-blocking.
…dle robustness Addresses the policies/bridge.py findings from review microsoft#3137. - GLOB fail-open: _pattern_to_regex translated GLOB patterns with fnmatch.translate, whose output (e.g. "(?s:.*\.exe)\Z") uses Python-only syntax that Go RE2 (OPA) rejects, leaving regex.match undefined so the GLOB deny silently failed open. Add _glob_to_re2 (translates * / ? / [seq] / [!seq] to RE2-safe syntax, anchored whole-string with (?s)^...$). - Reject non-finite confidence_threshold up front (inf rendered invalid Rego; nan was silently dropped); json.dumps uses allow_nan=False. - Clean up a self-created temp bundle dir if materialization fails. Adds tests/test_bridge_pattern.py (no agent_os dependency) including an OPA-backed regression test that compiles the GLOB regex under real RE2 and a fnmatchcase cross-check across edge cases. Verified with OPA 0.70.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VT2CfGX3tmPsQaofuuWwED Signed-off-by: Himanaraba <kayaharuka@hotmail.com>
5834c6e to
4a70053
Compare
|
@MohammadHaroonAbuomar good point — retitled to "fix(bridge): close GLOB blocked-pattern fail-open via RE2-compatible translation" so it reads as eliminating the fail-open, not introducing one. I'll leave the optional |
Addresses the
policies/bridge.pyfindings from the robustness review #3137 (per @imran-siddique's request to track fixes as separate per-file PRs).Fail-open: GLOB blocked patterns never matched
_pattern_to_regextranslated a v4GLOBblocked pattern withfnmatch.translate, whose output ((?s:.*\.exe)\Z) is Python-only regexsyntax. Go RE2 — the engine behind OPA's
agt.patterns— rejects the\Zanchor and the inline
(?s:...)flag group, soregex.matchwent undefinedand the deny rule silently failed open. This contradicts the
_pattern_to_regexdocstring ("emits a Go RE2 regex literal in every case") and fails open in a
policy-enforcement layer (ADR-0013).
Empirically confirmed under OPA 0.70.0 / Go RE2:
Fix
_glob_to_re2: translates*/?/[seq]/[!seq]to RE2-safesyntax, anchored whole-string with
(?s)^...$. Whole-string anchoringpreserves v4 glob semantics under
agt.patterns' unanchoredregex.match.Two smaller robustness fixes in the same file
confidence_threshold.infslipped past the> 0guard andrendered
deny_if_low_confidence(Infinity)— invalid Rego/JSON that fails tocompile;
nanwas silently dropped (a threshold the caller set but got nodeny for). Now rejected up front in
governance_to_acs_manifest, withjson.dumps(..., allow_nan=False)as a backstop in_render_rego.wrapped so a failure removes a self-created
agt_bridge_*temp dir insteadof leaving a half-built bundle (stock libs copied, generated module missing).
A caller-supplied
bundle_diris left untouched.Why the existing suite missed this
test_bridge.pyincludes a("*.exe", PatternType.GLOB)entry but onlystring-checks the generated Rego body; the OPA-running test used a
SUBSTRINGpattern. No test ever compiled a GLOB pattern under OPA, so the fail-open went
undetected.
Tests
Adds
tests/test_bridge_pattern.py(noagent_osdependency): RE2-safety of thetranslation, an OPA-backed regression test that compiles the GLOB regex under
real Go RE2 (skips if
opais absent), non-finite-threshold rejection, andtemp-dir cleanup on failure.
Verified locally against the real ACS native runtime (built from
policy-engine/sdk/python) + OPA 0.70.0:Refs #3137
🤖 Generated with Claude Code