visual-artifacts: user-installed stack wins over bundled example (VA-STACK-001)#222
Merged
Merged
Conversation
VA-STACK-001 from the Visual Artifacts v1 Security Audit (architect review, 2026-05-11). Single P2 finding: named stack lookup checked examples/custom-stack-template/<name>/stack.json BEFORE $NANOSTACK_STORE/stacks/<name>/stack.json, so a user- installed `compliance-release` stack was silently shadowed by the repo-bundled example with the same name. Impact: not RCE or exfiltration. The render and manifest looked authoritative, but described the wrong workflow. Compliance and release reviews could approve against a DAG that was not the project's actual stack. The contract for visual artifacts as trustable local evidence required this gap to close. Fix: swap precedence in render_stack_body. 1. $NANOSTACK_STORE/stacks/<name>/stack.json (user-installed) 2. examples/custom-stack-template/<name>/stack.json (bundled fallback) 3. .nanostack/config.json only for `stack default` (unchanged) A user-installed stack with the same name as a bundled example always wins. Bundled fallback still applies when no user stack exists. The malformed-named-stack and stack-not-found paths are unchanged. reference/visual-artifact-contract.md updated to reflect the new order. The Stack invalid / Stack not found behavior is unchanged. Regression cells: - 24a: user-installed `compliance-release` with phase `user-gate` + display_name "User Compliance Override" wins. HTML shows the user phases, does NOT show the bundled license-audit phase, and the manifest first source is the user-installed stack file. - 24b: with no user stack, the bundled example still renders. Manifest first source is the examples/custom-stack-template file. Test count: 321 -> 330 e2e (+9). Template lint 38/38 unchanged. Local tests/run.sh 83/83 still green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes VA-STACK-001 from the Visual Artifacts v1 Security Audit (architect review, 2026-05-11). Single P2 finding: named stack lookup checked the repo-bundled example before the project's user-installed stack, so a customized
compliance-releasewas silently shadowed by the example with the same name. The render and manifest looked authoritative but described the wrong workflow.Fix
Swap precedence in
render_stack_body:$NANOSTACK_STORE/stacks/<name>/stack.json(user-installed)examples/custom-stack-template/<name>/stack.json(bundled fallback).nanostack/config.jsononly forstack default(unchanged)A user-installed stack with the same name as a bundled example always wins. Bundled fallback still applies when no user stack exists. Malformed-named-stack and stack-not-found paths are unchanged.
Files
bin/render-artifact.sh: swap the lookup order inrender_stack_body.reference/visual-artifact-contract.md: update thestack <name>row to reflect the new order.ci/e2e-visual-artifacts.sh: 2 new cells (24a, 24b) covering both directions.Regression coverage
compliance-releasewith phaseuser-gate+ display_name "User Compliance Override"license-audit; manifest first source is the user-installed stack fileCodex review trail (1 pass, clean)
Pass 1: clean.
Test plan
ci/check-visual-artifact-templates.sh38/38ci/e2e-visual-artifacts.sh330/330 (was 321; +9 from cells 24a + 24b)tests/run.sh83/83$NANOSTACK_STORE/stacks/compliance-release/stack.json