Relationships
#3826 method run masks a sensitive array from --input element by element, exposing its shape (regression from #3752)
Opened by skunk-ape · 10/23/2026· Shipped 10/23/2026
What happens
swamp model method run --json masks a sensitive array argument passed with --input element by element. Before swamp-club#3752 the whole value was masked.
A method argument declared as command: z.array(z.string()).meta({ sensitive: true }), run with:
swamp model method run sa exec --input '{"name":"visible-name","command":["curl","-H","Bearer <token>"]}' --jsonnow reports:
"methodArguments": { "name": "visible-name", "command": ["***", "***", "***"] }Expected (swamp-club#3555, and what the UAT asserts):
"methodArguments": { "name": "visible-name", "command": "***" }The token itself is not printed. But the output now shows the array's length and shape, which come from the operator's --input, not from the definition.
Why this looks unintended
#3752 (swamp PR #3309, da8bacdf) moved the completed event and method-summary report onto the cache's masking walk. Its notes say that only a sensitive container whose keys are the definition's own authored text is now masked leaf by leaf, and that "a container whose keys came from data is still masked whole". Since #3749, an --input value is the run's data. So an array typed through --input should still be masked whole, and it isn't. Either arrays from --input slip past the "came from data" check, or #3752 changed #3555's contract without saying so for this case.
Evidence
- UAT:
tests/cli/adversarial/sensitive_literal_args_test.ts, "swamp model method run masks a sensitive method argument passed with --input or --stdin as *** in --json methodArguments". - The last green scheduled adversarial Tier 6 run on swamp-uat main was 2026-10-22 18:13 UTC. It has failed on this test ever since, on stables
20261023.022020.0-sha.7bbeadcf,20261023.012247.0-sha.06b63974and20261023.123914.0-sha.8540c1e3. - Release UAT doesn't run the adversarial tiers, so this reached stable without failing a release gate.
- Not fixed on swamp main as of
45393d82.
Ask
Mask an array (or any container) that came from --input / --stdin whole in the completed event, the method-summary report and --json output, as #3555 specified. If per-element masking is intended, say so here, and swamp-uat will update the test.
Shipped
Click a lifecycle step above to view its details.
skunk-ape commented 10/23/2026, 8:55:18 PM
Per-element masking of a sensitive array is intended, and we are keeping it (decided by Seth and Zack).
A sensitive container is masked whole only where its keys could be data, because keys are operator text. Array indexes are not, so an array from --input or --stdin is masked element by element: "command": ["***", "***", "***"]. That matches what the evaluated cache stores. We accept that this shows the array length. An array holding an object, or one inside an object that came from data, is still masked whole. This replaces the whole-array expectation of #3555.
swamp-uat updated tests/cli/adversarial/sensitive_literal_args_test.ts to expect one mask per element (swamp-uat PR #779). The swamp change records the rule in design/primitives/vaults.md and pins it with unit and integration tests for --input and --stdin; PR to follow.
Sign in to post a ripple.