fix(blueprint): allowlist safe run plan output - #3674
Conversation
📝 WalkthroughWalkthroughRunPlan's public interface is tightened to exclude credential-bearing inference fields. New safe plan builders explicitly allowlist non-secret fields for public output, persistence, and status rendering. actionPlan, actionApply, and actionStatus are updated to use these builders instead of inline or ad-hoc credential exclusions. Comprehensive tests validate that no credential field names or secret values leak to stdout or persisted files. ChangesSecret field sanitization in run plans
Sequence DiagramsequenceDiagram
participant User
participant actionPlan
participant buildSafePublicRunPlan
participant stdout
participant actionApply
participant buildPersistedRunPlan
participant plan.json
participant actionStatus
participant buildStatusRunPlan
User->>actionPlan: nemoclaw plan
actionPlan->>buildSafePublicRunPlan: inferenceCfg, routerCfg, ...
buildSafePublicRunPlan-->>actionPlan: RunPlan (no credentials)
actionPlan->>stdout: JSON.stringify(safe plan)
User->>actionApply: nemoclaw apply
actionApply->>buildPersistedRunPlan: plan, inferenceCfg, ...
buildPersistedRunPlan-->>actionApply: PersistedRunPlan (allowlisted fields)
actionApply->>plan.json: writeFileSync(safe persisted plan)
User->>actionStatus: nemoclaw status
actionStatus->>plan.json: readFileSync()
plan.json-->>actionStatus: raw JSON (unknown)
actionStatus->>buildStatusRunPlan: unknown object
buildStatusRunPlan-->>actionStatus: StatusRunPlan (safe fields only)
actionStatus->>stdout: JSON.stringify(safe status)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Comment |
E2E Advisor RecommendationRequired E2E: Dispatch hint: Auto-dispatched E2E: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
Selective E2E Results — ✅ All requested jobs passedRun: 26009769049
|
Selective E2E Results — ✅ All requested jobs passedRun: 26010189361
|
Selective E2E Results — ✅ All requested jobs passedRun: 26072002555
|
Selective E2E Results — ✅ All requested jobs passedRun: 26103843685
|
…apes # Conflicts: # test/e2e/docs/parity-inventory.generated.json
Selective E2E Results — ✅ All requested jobs passedRun: 26116463793
|
There was a problem hiding this comment.
APPROVE.
Same direction as #3649 (explicit allowlist) but executed more thoroughly:
- Tightens
RunPlan.inferencetype itself (nemoclaw/src/blueprint/runner.ts:461-466) —credential_envis removed from the public interface, so it can't reappear by accident. - Single source of truth via four builders (
buildSafeInferencePlan,buildSafePublicRunPlan,buildPersistedRunPlan,buildStatusRunPlan) — no duplicate allowlists. actionStatusrecursively allowlists nestedsandbox.*androuter.*fields and falls back to{status: "unknown"}on malformedplan.json. Catches credentials in plans written by older versions.- +179 lines of regression tests covering credential names, env-var values, future-secret fields (
token,authorization), persisted schema shape, and the corrupt-JSON path. credential-sanitization-e2ePASSED in nightly (run 26103843685). Self-hosted sandbox/gateway/non-root smoke all green.
Summary
credential_envfrom public blueprint plan outputplan.jsonthrough an explicit allowlist builder instead of ad-hoc credential exclusionsstatusparseplan.jsonand re-render only safe allowlisted fieldsFixes #3648
Related contributor work
plan.json. This PR keeps that core approach while adding nested status sanitization, preserving the public plan/status fields requested in the issue, and adding regression tests.Validation
cd nemoclaw && npm test -- src/blueprint/runner.test.ts(91 passed)cd nemoclaw && npm run buildcd nemoclaw && npm run checkgit diff --checkSummary by CodeRabbit
Bug Fixes
Tests