Merge pull request 'The bus state guard lets a provider reference under a provision named like a credential pass (L2's seed, issue 1126)' (#47) from fix/1126-state-guard into main

This commit was merged in pull request #47.
This commit is contained in:
2026-10-28 21:01:24 +00:00
2 changed files with 27 additions and 2 deletions
+19 -2
View File
@@ -391,7 +391,10 @@ func valueOf(raw []byte) json.RawMessage {
var credentialEndings = []string{"password", "passwd", "secret", "token", "credential", "credentials",
"authorization", "apikey", "privatekey", "accesskey", "cookie"}
// credentialField is the first field anywhere in a JSON value whose name says it is a credential, or "".
// credentialField is the first field anywhere in a JSON value whose name says it is a credential, or "". The one shape a
// credential-shaped name may hold is a provider reference, an object of exactly `node` and `module`, both strings: a
// placement's binding of the provision "secret" to the vault (issue 1126) names who provides it, never its value. Any
// other shape under such a name is refused.
func credentialField(value json.RawMessage) string {
var v any
if json.Unmarshal(value, &v) != nil {
@@ -409,7 +412,7 @@ func credentialField(value json.RawMessage) string {
for _, k := range keys {
norm := strings.NewReplacer("-", "", "_", "", " ", "").Replace(strings.ToLower(k))
for _, end := range credentialEndings {
if strings.HasSuffix(norm, end) {
if strings.HasSuffix(norm, end) && !providerReference(t[k]) {
return k
}
}
@@ -428,3 +431,17 @@ func credentialField(value json.RawMessage) string {
}
return walk(v)
}
// providerReference says whether v is exactly {"node": <name>, "module": <name>}, each a name as mesh-sdk names them.
func providerReference(v any) bool {
m, ok := v.(map[string]any)
if !ok || len(m) != 2 {
return false
}
node, okN := m["node"].(string)
module, okM := m["module"].(string)
return okN && okM && referenceName.MatchString(node) && referenceName.MatchString(module)
}
// referenceName is a node's or a module's name as mesh-sdk names them: lower case, digits and dashes.
var referenceName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
+8
View File
@@ -15,6 +15,14 @@ func TestACredentialNamedFieldIsFoundAnywhereInAValue(t *testing.T) {
`{"clientSecret":"s"}`: "clientSecret",
`{"maxTokens":4096,"name":"a","generation":3}`: "",
`"just a string"`: "",
// Issue 1126: a placement binds the provision "secret" to the vault; only an exact provider reference passes.
`{"bindings":{"secret":{"node":"anchor","module":"mesh-vault"}}}`: "",
`{"secret":{"value":"s"}}`: "secret",
`{"secret":{"node":"anchor","module":"mesh-vault","value":"s"}}`: "secret",
`{"secret":{"node":"anchor","module":7}}`: "secret",
`{"secret":{"node":"anchor","module":"hunter2 Bearer s3cr3t"}}`: "secret",
`{"secret":["s"]}`: "secret",
`{"bindings":{"secret":{"token":"s"}}}`: "secret",
} {
if got := credentialField(json.RawMessage(value)); got != want {
t.Errorf("%s: found %q, want %q", value, got, want)