fix(security): gate GitHub access behind an opt-in policy preset (#1583)#1660
Conversation
The base sandbox policy hardcoded `network_policies.github` with github.com / api.github.com endpoints (access: full) plus the git and gh binaries. Because the entry lived in the base policy, every sandbox received unscoped GitHub access regardless of which policy presets the user picked during `nemoclaw onboard`. The `Available policy presets` list never showed a `github` option, so the permission was neither user-discoverable nor user-controllable — agents could `git clone`, `git push`, and call the GitHub API on behalf of any sandbox without consent. Move the entry into a new `presets/github.yaml` so it shows up in the onboard preset picker and is only granted when the user explicitly opts in (or applies it later via `openshell policy set`). The preset preserves the original semantics (access: full, git + gh binaries) so existing flows that opt in continue to work unchanged. Adds two regression tests in `test/validate-blueprint.test.ts`: - the base policy must not declare a `github` network_policies entry AND must not reference github.com / api.github.com under any endpoint key (catches a re-add under a renamed key) - the new `presets/github.yaml` file must exist, parse, and declare a github preset (catches a delete-by-mistake that would leave users unable to opt in at all) Refs: NVIDIA#1583
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughGitHub network policy and binary allowances were removed from the default sandbox policy and introduced as a new optional preset named Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
test/validate-blueprint.test.ts (2)
222-230: Strengthen preset regression to lock preserved semantics.This currently verifies presence only. To protect existing opt-in flows, also assert both endpoints remain
access: fulland binaries include/usr/bin/git+/usr/bin/gh.Suggested semantic assertions
it("regression `#1583`: github preset file exists and parses", () => { @@ const np = parsed.network_policies as Record<string, unknown> | undefined; expect(np && "github" in np).toBe(true); + + const gh = (np as Record<string, { endpoints?: Array<{ host?: string; access?: string }>; binaries?: Array<{ path?: string }> }>).github; + const hosts = new Map((gh?.endpoints ?? []).map((e) => [e.host, e.access])); + expect(hosts.get("github.com")).toBe("full"); + expect(hosts.get("api.github.com")).toBe("full"); + + const binPaths = new Set((gh?.binaries ?? []).map((b) => b.path)); + expect(binPaths.has("/usr/bin/git")).toBe(true); + expect(binPaths.has("/usr/bin/gh")).toBe(true); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/validate-blueprint.test.ts` around lines 222 - 230, The regression test "regression `#1583`: github preset file exists and parses" only checks presence; update the test (variables: PRESET_PATH, parsed, meta, np) to also assert preserved semantics by verifying that the github preset's endpoints configuration contains both expected endpoints with access: "full" and that the binaries list (under the preset or relevant service definition) includes both "/usr/bin/git" and "/usr/bin/gh"; locate where parsed.preset and parsed.network_policies (np) are read and add assertions that meta.name === "github", each relevant endpoint object's access === "full", and that the binaries array contains the required paths.
192-210: Also assert base policy does not whitelistgit/ghbinaries.Line 203+ blocks GitHub hosts, but this regression still allows accidental reintroduction of
/usr/bin/gitor/usr/bin/ghunder a different policy key. Add a binary-level assertion to fully enforce#1583intent.Suggested test hardening
it("regression `#1583`: base policy does not silently grant GitHub access", () => { @@ const githubHosts = findEndpoints( (h) => h === "github.com" || h === "api.github.com", ); expect(githubHosts).toEqual([]); + + // Also ensure git/gh binaries are not granted by default via any policy entry. + const blocked = new Set(["/usr/bin/git", "/usr/bin/gh"]); + const violatingBinaries: string[] = []; + for (const cfg of Object.values((np ?? {}) as Record<string, unknown>)) { + const bins = (cfg as { binaries?: Array<{ path?: string }> })?.binaries; + if (!Array.isArray(bins)) continue; + for (const bin of bins) { + if (bin?.path && blocked.has(bin.path)) violatingBinaries.push(bin.path); + } + } + expect(violatingBinaries).toEqual([]); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/validate-blueprint.test.ts` around lines 192 - 210, Add an assertion that the base policy does not whitelist the git/gh binaries by scanning the policy object for any "binaries" entries that include "/usr/bin/git" or "/usr/bin/gh"; locate the base policy via the existing policy variable (and its network_policies field) and either reuse the test traversal pattern (similar to findEndpoints) or add a small helper to collect all binary paths from base-policy entries, then expect that list not to contain those two paths (i.e., expect([...]).toEqual([])).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@test/validate-blueprint.test.ts`:
- Around line 222-230: The regression test "regression `#1583`: github preset file
exists and parses" only checks presence; update the test (variables:
PRESET_PATH, parsed, meta, np) to also assert preserved semantics by verifying
that the github preset's endpoints configuration contains both expected
endpoints with access: "full" and that the binaries list (under the preset or
relevant service definition) includes both "/usr/bin/git" and "/usr/bin/gh";
locate where parsed.preset and parsed.network_policies (np) are read and add
assertions that meta.name === "github", each relevant endpoint object's access
=== "full", and that the binaries array contains the required paths.
- Around line 192-210: Add an assertion that the base policy does not whitelist
the git/gh binaries by scanning the policy object for any "binaries" entries
that include "/usr/bin/git" or "/usr/bin/gh"; locate the base policy via the
existing policy variable (and its network_policies field) and either reuse the
test traversal pattern (similar to findEndpoints) or add a small helper to
collect all binary paths from base-policy entries, then expect that list not to
contain those two paths (i.e., expect([...]).toEqual([])).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6646df01-424d-40a2-922f-0f4d1095c808
📒 Files selected for processing (3)
nemoclaw-blueprint/policies/openclaw-sandbox.yamlnemoclaw-blueprint/policies/presets/github.yamltest/validate-blueprint.test.ts
The base sandbox policy hardcoded `network_policies.npm_registry` with read-only `registry.npmjs.org` access plus the npm and node binaries. Because the entry lived in the base policy, every sandbox received npm registry access regardless of which policy presets the user picked during `nemoclaw onboard`. That created the regression in NVIDIA#1458: a sandbox onboarded with ZERO policy presets could still successfully run `npm install`, while `pip install` was correctly rejected because PyPI is only declared in the `pypi` preset (`presets/pypi.yaml`). Two equivalent package-manager paths, one silently allowed, one correctly gated. This is the same shape as the GitHub leak fixed in NVIDIA#1583/NVIDIA#1660. Remove the `npm_registry` entry from the base policy. Users who need npm in the sandbox can select the existing `npm` preset (`presets/npm.yaml`) during onboard or apply it later via `openshell policy set`. Adds a regression test in test/validate-blueprint.test.ts asserting: - the base policy must not declare an `npm_registry` network_policies entry - no endpoint anywhere in the base policy may reference registry.npmjs.org (catches a re-add under a renamed key) Refs: NVIDIA#1458
|
✨ Thanks for submitting this PR, which proposes a way to improve security by restricting access to GitHub and may prevent unauthorized repository access. Possibly related open issues: |
) ## Summary The gate checker and triage scripts treated "all present checks green" as passing, even when only 2 of ~9 checks existed. This caused premature approvals on fork PRs where workflows hadn't been triggered yet. ### Root cause Fork PRs from first-time contributors need a maintainer to click "Approve and run" before `pull_request` workflows execute. Until then, only `pull_request_target` checks (`check-pr-limit`) and external bots (`CodeRabbit`) appear in `statusCheckRollup`. The scripts saw 2/2 green and reported CI as passing. A secondary bug: GitHub's `statusCheckRollup` returns two shapes — `CheckRun` (`name`/`status`/`conclusion`) and `StatusContext` (`context`/`state`). The scripts only read CheckRun fields, so CodeRabbit (a StatusContext) was always treated as "pending" even when `state` was `SUCCESS`. ### Changes - **`check-gates.ts`**: Add `REQUIRED_CHECK_NAMES` (`checks`, `commit-lint`, `dco-check`) validation. Add `StatusCheck` union type to correctly handle both `CheckRun` and `StatusContext` shapes. CI gate now fails with `"required check(s) not found — workflows may need approval"` when expected checks are absent. - **`triage.ts`**: Add same required-check validation so triage does not score unapproved-workflow PRs as `review-ready`. - **`MERGE-GATE.md`**: Add "Missing required checks" as first bullet in Step 2 interpretation guidance. ### Before / After | PR scenario | Before | After | |---|---|---| | Fork PR, workflows not approved (2 checks) | "All 2 checks green" ✅ | "3 required check(s) not found — workflows may need approval" ❌ | | Fork PR, workflows running, dco-check failing | "1 pending" (CodeRabbit misread) | "3 failing check(s): dco-check: FAILURE, ..." ❌ | | Internal PR, all 12 checks green | "1 pending" (CodeRabbit misread) | "All 12 checks green" ✅ | ### Test plan - [x] Verified against PR #1660 (fork, workflows not approved) — correctly reports missing checks - [x] Verified against PR #1663 (fork, workflows approved, dco-check failing) — correctly reports failures - [x] Verified against PR #1683 (internal, all green) — correctly reports all 12 green - [x] Triage script correctly classifies #1660 as `salvage-now` with `failing-checks` reason instead of `review-ready` Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enhanced merge gate to require specific CI checks be present and completed before a PR can be approved; missing required checks will block approval until workflows finish and validation is re-run. * Improved CI evaluation to better distinguish pending vs failed states across different check types. * PRs missing required check contexts are now classified as not-green. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cv
left a comment
There was a problem hiding this comment.
Maintainer review — ready for merge.
| Gate | Status |
|---|---|
| CI | ✅ green (latest runs all passing) |
| Conflicts | ✅ mergeable |
| CodeRabbit major/critical | ✅ none |
| Risky code tested | ✅ regression coverage present |
What I salvaged
- Merged latest into this branch.
- Added the missing preset-list test update in so the new preset is reflected in the expected count and names.
- Re-ran the fork workflow approvals and waited for the full suite to finish.
Security pass
- This correctly removes GitHub access from the baseline sandbox policy.
- Access is preserved behind an explicit opt-in preset (), which matches least-privilege intent.
- Regression tests cover both: GitHub is not silently granted by default, and the preset still exists.
One note: the raw still shows an older failed , but the latest rerun passes and CodeRabbit pass 0 Review completed
block edits to migrated legacy paths pass 23s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460727/job/70688052314
changes pass 4s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70688052581
checks pass 1m27s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70688052603
commit-lint pass 12s https://github.com/NVIDIA/NemoClaw/actions/runs/24213521609/job/70688368795
dco-check pass 4s https://github.com/NVIDIA/NemoClaw/actions/runs/24213521358/job/70688368861
sandbox-images-and-e2e / build-sandbox-images pass 5m53s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70688255195
sandbox-images-and-e2e / build-sandbox-images-arm64 pass 1m34s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70688255217
sandbox-images-and-e2e / test-e2e-gateway-isolation pass 1m16s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70689089004
sandbox-images-and-e2e / test-e2e-sandbox pass 1m46s https://github.com/NVIDIA/NemoClaw/actions/runs/24213460872/job/70689088995 is fully green.
Ready for merge.
cv
left a comment
There was a problem hiding this comment.
Maintainer review — ready for merge.
| Gate | Status |
|---|---|
| CI | ✅ green (latest runs all passing) |
| Conflicts | ✅ mergeable |
| CodeRabbit major/critical | ✅ none |
| Risky code tested | ✅ regression coverage present |
What I salvaged
- Merged latest main into this branch.
- Added the missing preset-list test update in
test/policies.test.tsso the newgithubpreset is reflected in the expected count and names. - Re-ran the fork workflow approvals and waited for the full suite to finish.
Security pass
- This correctly removes GitHub access from the baseline sandbox policy.
- Access is preserved behind an explicit opt-in preset (
presets/github.yaml), which matches least-privilege intent. - Regression tests cover both: GitHub is not silently granted by default, and the preset still exists.
One note: the raw statusCheckRollup still shows an older failed dco-check, but the latest rerun passes and gh pr checks is fully green.
Ready for merge.
…1719) ## Summary - Remove `github` and `github_rest_api` from baseline network policy docs (now opt-in preset, #1660) - Add `github` preset to presets tables in customize-network-policy.md and best-practices.md - Add `brave` and `brew` presets to best-practices.md - Update `huggingface` description (download-only + inference router, #1663) - Update `npm` and `pypi` descriptions (GET-only, publishing blocked, #1672) - Fix binary-scoping example to reference `github` as a preset, not baseline - Add `docs/.docs-skip` exclusion file for suppressing docs on experimental/unreleased features - Update `nemoclaw-contributor-update-docs` skill with skip-features, skip-terms, and agent matrix filtering rules - Regenerate `nemoclaw-user-*` skills from updated docs ## Test plan - [x] `make docs` builds without warnings - [x] All pre-commit and pre-push hooks pass - [x] Skip-term scan passes (zero violations in branch diff) - [ ] Verify rendered pages in docs site preview 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced skip-list configuration for controlling documentation generation based on commit patterns and excluded terminology. * **Documentation** * Updated network policy presets with new `github`, `brave`, and `brew` options. * Refined preset descriptions for `huggingface`, `npm`, and `pypi` to clarify access scopes. * Clarified that GitHub access is no longer baseline and requires applying the `github` preset during onboarding. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The base sandbox policy hardcoded `network_policies.npm_registry` with read-only `registry.npmjs.org` access plus the npm and node binaries. Because the entry lived in the base policy, every sandbox received npm registry access regardless of which policy presets the user picked during `nemoclaw onboard`. That created the regression in NVIDIA#1458: a sandbox onboarded with ZERO policy presets could still successfully run `npm install`, while `pip install` was correctly rejected because PyPI is only declared in the `pypi` preset (`presets/pypi.yaml`). Two equivalent package-manager paths, one silently allowed, one correctly gated. This is the same shape as the GitHub leak fixed in NVIDIA#1583/NVIDIA#1660. Remove the `npm_registry` entry from the base policy. Users who need npm in the sandbox can select the existing `npm` preset (`presets/npm.yaml`) during onboard or apply it later via `openshell policy set`. Adds a regression test in test/validate-blueprint.test.ts asserting: - the base policy must not declare an `npm_registry` network_policies entry - no endpoint anywhere in the base policy may reference registry.npmjs.org (catches a re-add under a renamed key) Refs: NVIDIA#1458
…IDIA#1707) ## Summary The gate checker and triage scripts treated "all present checks green" as passing, even when only 2 of ~9 checks existed. This caused premature approvals on fork PRs where workflows hadn't been triggered yet. ### Root cause Fork PRs from first-time contributors need a maintainer to click "Approve and run" before `pull_request` workflows execute. Until then, only `pull_request_target` checks (`check-pr-limit`) and external bots (`CodeRabbit`) appear in `statusCheckRollup`. The scripts saw 2/2 green and reported CI as passing. A secondary bug: GitHub's `statusCheckRollup` returns two shapes — `CheckRun` (`name`/`status`/`conclusion`) and `StatusContext` (`context`/`state`). The scripts only read CheckRun fields, so CodeRabbit (a StatusContext) was always treated as "pending" even when `state` was `SUCCESS`. ### Changes - **`check-gates.ts`**: Add `REQUIRED_CHECK_NAMES` (`checks`, `commit-lint`, `dco-check`) validation. Add `StatusCheck` union type to correctly handle both `CheckRun` and `StatusContext` shapes. CI gate now fails with `"required check(s) not found — workflows may need approval"` when expected checks are absent. - **`triage.ts`**: Add same required-check validation so triage does not score unapproved-workflow PRs as `review-ready`. - **`MERGE-GATE.md`**: Add "Missing required checks" as first bullet in Step 2 interpretation guidance. ### Before / After | PR scenario | Before | After | |---|---|---| | Fork PR, workflows not approved (2 checks) | "All 2 checks green" ✅ | "3 required check(s) not found — workflows may need approval" ❌ | | Fork PR, workflows running, dco-check failing | "1 pending" (CodeRabbit misread) | "3 failing check(s): dco-check: FAILURE, ..." ❌ | | Internal PR, all 12 checks green | "1 pending" (CodeRabbit misread) | "All 12 checks green" ✅ | ### Test plan - [x] Verified against PR NVIDIA#1660 (fork, workflows not approved) — correctly reports missing checks - [x] Verified against PR NVIDIA#1663 (fork, workflows approved, dco-check failing) — correctly reports failures - [x] Verified against PR NVIDIA#1683 (internal, all green) — correctly reports all 12 green - [x] Triage script correctly classifies NVIDIA#1660 as `salvage-now` with `failing-checks` reason instead of `review-ready` Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enhanced merge gate to require specific CI checks be present and completed before a PR can be approved; missing required checks will block approval until workflows finish and validation is re-run. * Improved CI evaluation to better distinguish pending vs failed states across different check types. * PRs missing required check contexts are now classified as not-green. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…DIA#1583) (NVIDIA#1660) ## Summary - Move the hardcoded `github` network_policies entry out of the base sandbox policy and into a new `presets/github.yaml` so GitHub access (github.com, api.github.com, `git`, `gh`) is only granted when the user explicitly opts in during `nemoclaw onboard`. - Add regression tests asserting (a) the base policy never re-declares a `github` entry or references github.com / api.github.com, and (b) the new preset file exists and parses. Fixes NVIDIA#1583. ## Why The base policy hardcoded `network_policies.github` with `access: full` plus the `git` and `gh` binaries. Because the entry lived in the base policy, every sandbox received unscoped GitHub access regardless of which policy presets the user picked. The `Available policy presets` list during onboard never showed a `github` option, so the permission was neither user-discoverable nor user-controllable — agents could `git clone`, `git push`, and call the GitHub API on behalf of any sandbox without consent. This violates least-privilege and is exactly the kind of silent capability creep the preset system exists to prevent. ## What changed - `nemoclaw-blueprint/policies/openclaw-sandbox.yaml` — remove the `github` entry, leave a comment pointing at the new preset and NVIDIA#1583. - `nemoclaw-blueprint/policies/presets/github.yaml` — new file. Same shape as `presets/brew.yaml`. Preserves the original `access: full` semantics so users who opt in keep the existing capability set. - `test/validate-blueprint.test.ts` — two new regression tests under `NVIDIA#1583`. ## Test plan - [x] `npx vitest run test/validate-blueprint.test.ts` → 29/29 passing. - [x] Negative-case verification: stash the base-policy edit and re-run — the new regression test fails as expected, then passes again after pop. - [ ] Maintainer should sanity-check that no internal flow inside the sandbox depends on `git`/`gh` being available out of the box. If something does (e.g., a skill that clones from GitHub), it should either declare the github preset as a dependency or be reworked to use the gateway. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an optional GitHub preset to enable GitHub.com and GitHub API access (including git/gh) when selected. * **Refactor** * Removed GitHub network/binary access from default sandbox; access now enabled only via the optional preset. * **Tests** * Added tests ensuring GitHub access is absent by default and the GitHub preset is correctly configured and listed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Colin McDonough <cmcdonough@50words.com> --------- Co-authored-by: Carlos Villela <cvillela@nvidia.com>
…VIDIA#1719) ## Summary - Remove `github` and `github_rest_api` from baseline network policy docs (now opt-in preset, NVIDIA#1660) - Add `github` preset to presets tables in customize-network-policy.md and best-practices.md - Add `brave` and `brew` presets to best-practices.md - Update `huggingface` description (download-only + inference router, NVIDIA#1663) - Update `npm` and `pypi` descriptions (GET-only, publishing blocked, NVIDIA#1672) - Fix binary-scoping example to reference `github` as a preset, not baseline - Add `docs/.docs-skip` exclusion file for suppressing docs on experimental/unreleased features - Update `nemoclaw-contributor-update-docs` skill with skip-features, skip-terms, and agent matrix filtering rules - Regenerate `nemoclaw-user-*` skills from updated docs ## Test plan - [x] `make docs` builds without warnings - [x] All pre-commit and pre-push hooks pass - [x] Skip-term scan passes (zero violations in branch diff) - [ ] Verify rendered pages in docs site preview 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced skip-list configuration for controlling documentation generation based on commit patterns and excluded terminology. * **Documentation** * Updated network policy presets with new `github`, `brave`, and `brew` options. * Refined preset descriptions for `huggingface`, `npm`, and `pypi` to clarify access scopes. * Clarified that GitHub access is no longer baseline and requires applying the `github` preset during onboarding. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…IDIA#1707) ## Summary The gate checker and triage scripts treated "all present checks green" as passing, even when only 2 of ~9 checks existed. This caused premature approvals on fork PRs where workflows hadn't been triggered yet. ### Root cause Fork PRs from first-time contributors need a maintainer to click "Approve and run" before `pull_request` workflows execute. Until then, only `pull_request_target` checks (`check-pr-limit`) and external bots (`CodeRabbit`) appear in `statusCheckRollup`. The scripts saw 2/2 green and reported CI as passing. A secondary bug: GitHub's `statusCheckRollup` returns two shapes — `CheckRun` (`name`/`status`/`conclusion`) and `StatusContext` (`context`/`state`). The scripts only read CheckRun fields, so CodeRabbit (a StatusContext) was always treated as "pending" even when `state` was `SUCCESS`. ### Changes - **`check-gates.ts`**: Add `REQUIRED_CHECK_NAMES` (`checks`, `commit-lint`, `dco-check`) validation. Add `StatusCheck` union type to correctly handle both `CheckRun` and `StatusContext` shapes. CI gate now fails with `"required check(s) not found — workflows may need approval"` when expected checks are absent. - **`triage.ts`**: Add same required-check validation so triage does not score unapproved-workflow PRs as `review-ready`. - **`MERGE-GATE.md`**: Add "Missing required checks" as first bullet in Step 2 interpretation guidance. ### Before / After | PR scenario | Before | After | |---|---|---| | Fork PR, workflows not approved (2 checks) | "All 2 checks green" ✅ | "3 required check(s) not found — workflows may need approval" ❌ | | Fork PR, workflows running, dco-check failing | "1 pending" (CodeRabbit misread) | "3 failing check(s): dco-check: FAILURE, ..." ❌ | | Internal PR, all 12 checks green | "1 pending" (CodeRabbit misread) | "All 12 checks green" ✅ | ### Test plan - [x] Verified against PR NVIDIA#1660 (fork, workflows not approved) — correctly reports missing checks - [x] Verified against PR NVIDIA#1663 (fork, workflows approved, dco-check failing) — correctly reports failures - [x] Verified against PR NVIDIA#1683 (internal, all green) — correctly reports all 12 green - [x] Triage script correctly classifies NVIDIA#1660 as `salvage-now` with `failing-checks` reason instead of `review-ready` Signed-off-by: Carlos Villela <cvillela@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enhanced merge gate to require specific CI checks be present and completed before a PR can be approved; missing required checks will block approval until workflows finish and validation is re-run. * Improved CI evaluation to better distinguish pending vs failed states across different check types. * PRs missing required check contexts are now classified as not-green. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…DIA#1583) (NVIDIA#1660) ## Summary - Move the hardcoded `github` network_policies entry out of the base sandbox policy and into a new `presets/github.yaml` so GitHub access (github.com, api.github.com, `git`, `gh`) is only granted when the user explicitly opts in during `nemoclaw onboard`. - Add regression tests asserting (a) the base policy never re-declares a `github` entry or references github.com / api.github.com, and (b) the new preset file exists and parses. Fixes NVIDIA#1583. ## Why The base policy hardcoded `network_policies.github` with `access: full` plus the `git` and `gh` binaries. Because the entry lived in the base policy, every sandbox received unscoped GitHub access regardless of which policy presets the user picked. The `Available policy presets` list during onboard never showed a `github` option, so the permission was neither user-discoverable nor user-controllable — agents could `git clone`, `git push`, and call the GitHub API on behalf of any sandbox without consent. This violates least-privilege and is exactly the kind of silent capability creep the preset system exists to prevent. ## What changed - `nemoclaw-blueprint/policies/openclaw-sandbox.yaml` — remove the `github` entry, leave a comment pointing at the new preset and NVIDIA#1583. - `nemoclaw-blueprint/policies/presets/github.yaml` — new file. Same shape as `presets/brew.yaml`. Preserves the original `access: full` semantics so users who opt in keep the existing capability set. - `test/validate-blueprint.test.ts` — two new regression tests under `NVIDIA#1583`. ## Test plan - [x] `npx vitest run test/validate-blueprint.test.ts` → 29/29 passing. - [x] Negative-case verification: stash the base-policy edit and re-run — the new regression test fails as expected, then passes again after pop. - [ ] Maintainer should sanity-check that no internal flow inside the sandbox depends on `git`/`gh` being available out of the box. If something does (e.g., a skill that clones from GitHub), it should either declare the github preset as a dependency or be reworked to use the gateway. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added an optional GitHub preset to enable GitHub.com and GitHub API access (including git/gh) when selected. * **Refactor** * Removed GitHub network/binary access from default sandbox; access now enabled only via the optional preset. * **Tests** * Added tests ensuring GitHub access is absent by default and the GitHub preset is correctly configured and listed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Colin McDonough <cmcdonough@50words.com> --------- Co-authored-by: Carlos Villela <cvillela@nvidia.com>
…VIDIA#1719) ## Summary - Remove `github` and `github_rest_api` from baseline network policy docs (now opt-in preset, NVIDIA#1660) - Add `github` preset to presets tables in customize-network-policy.md and best-practices.md - Add `brave` and `brew` presets to best-practices.md - Update `huggingface` description (download-only + inference router, NVIDIA#1663) - Update `npm` and `pypi` descriptions (GET-only, publishing blocked, NVIDIA#1672) - Fix binary-scoping example to reference `github` as a preset, not baseline - Add `docs/.docs-skip` exclusion file for suppressing docs on experimental/unreleased features - Update `nemoclaw-contributor-update-docs` skill with skip-features, skip-terms, and agent matrix filtering rules - Regenerate `nemoclaw-user-*` skills from updated docs ## Test plan - [x] `make docs` builds without warnings - [x] All pre-commit and pre-push hooks pass - [x] Skip-term scan passes (zero violations in branch diff) - [ ] Verify rendered pages in docs site preview 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced skip-list configuration for controlling documentation generation based on commit patterns and excluded terminology. * **Documentation** * Updated network policy presets with new `github`, `brave`, and `brew` options. * Refined preset descriptions for `huggingface`, `npm`, and `pypi` to clarify access scopes. * Clarified that GitHub access is no longer baseline and requires applying the `github` preset during onboarding. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
githubnetwork_policies entry out of the base sandbox policy and into a newpresets/github.yamlso GitHub access (github.com, api.github.com,git,gh) is only granted when the user explicitly opts in duringnemoclaw onboard.githubentry or references github.com / api.github.com, and (b) the new preset file exists and parses.Fixes #1583.
Why
The base policy hardcoded
network_policies.githubwithaccess: fullplus thegitandghbinaries. Because the entry lived in the base policy, every sandbox received unscoped GitHub access regardless of which policy presets the user picked. TheAvailable policy presetslist during onboard never showed agithuboption, so the permission was neither user-discoverable nor user-controllable — agents couldgit clone,git push, and call the GitHub API on behalf of any sandbox without consent. This violates least-privilege and is exactly the kind of silent capability creep the preset system exists to prevent.What changed
nemoclaw-blueprint/policies/openclaw-sandbox.yaml— remove thegithubentry, leave a comment pointing at the new preset and [All Platform] GitHub policy + binary is injected into sandbox runtime policy without user opt-in #1583.nemoclaw-blueprint/policies/presets/github.yaml— new file. Same shape aspresets/brew.yaml. Preserves the originalaccess: fullsemantics so users who opt in keep the existing capability set.test/validate-blueprint.test.ts— two new regression tests under#1583.Test plan
npx vitest run test/validate-blueprint.test.ts→ 29/29 passing.git/ghbeing available out of the box. If something does (e.g., a skill that clones from GitHub), it should either declare the github preset as a dependency or be reworked to use the gateway.Summary by CodeRabbit
New Features
Refactor
Tests
Signed-off-by: Colin McDonough cmcdonough@50words.com