{"record":{"id":"7df51e83b274495f","repo":"FiloSottile/age","slug":"malformed-confirm-stanza-invalid-no-option-encodi","errorCode":null,"errorMessage":"malformed confirm stanza: invalid NO option encoding","messagePattern":"malformed confirm stanza: invalid NO option encoding","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/client.go","lineNumber":373,"sourceCode":"\t\t\treturn true, writeStanza(conn, \"fail\")\n\t\t}\n\t\treturn true, writeStanzaWithBody(conn, \"ok\", []byte(secret))\n\tcase \"confirm\":\n\t\tif len(s.Args) != 1 && len(s.Args) != 2 {\n\t\t\treturn true, fmt.Errorf(\"malformed confirm stanza: unexpected number of arguments\")\n\t\t}\n\t\tif c.Confirm == nil {\n\t\t\treturn true, writeStanza(conn, \"fail\")\n\t\t}\n\t\tyes, err := format.DecodeString(s.Args[0])\n\t\tif err != nil {\n\t\t\treturn true, fmt.Errorf(\"malformed confirm stanza: invalid YES option encoding\")\n\t\t}\n\t\tvar no []byte\n\t\tif len(s.Args) == 2 {\n\t\t\tno, err = format.DecodeString(s.Args[1])\n\t\t\tif err != nil {\n\t\t\t\treturn true, fmt.Errorf(\"malformed confirm stanza: invalid NO option encoding\")\n\t\t\t}\n\t\t}\n\t\tchoseYes, err := c.Confirm(name, string(s.Body), string(yes), string(no))\n\t\tif err != nil {\n\t\t\treturn true, writeStanza(conn, \"fail\")\n\t\t}\n\t\tresult := \"yes\"\n\t\tif !choseYes {\n\t\t\tresult = \"no\"\n\t\t}\n\t\treturn true, writeStanza(conn, \"ok\", result)\n\tdefault:\n\t\treturn false, nil\n\t}\n}\n\n// readStanza calls r.ReadStanza and, if set, invokes WaitTimer in a separate\n// goroutine if the call takes longer than 5 seconds.","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/client.go#L355-L391","documentation":"Same as the YES variant: the confirm stanza's optional second argument (the NO option) failed bech32 decoding. When a confirm stanza supplies two arguments, both must be valid bech32 strings.","triggerScenarios":"Plugin sends a two-argument \"confirm\" stanza whose NO option is not valid bech32 (plaintext, bad checksum, invalid characters) during Unwrap.","commonSituations":"Plugin encodes YES correctly but passes the NO label raw; typos in the encoding helper applied to only one of the two options.","solutions":["Bech32-encode the NO option the same way as YES: bech32.Encode(\"\", []byte(\"no\"))","Alternatively send a one-argument confirm stanza if there is no NO option","Update the plugin binary to a fixed version"],"exampleFix":"// before (plugin side)\nargs := []string{bech32Yes, \"no\"}\n// after\nargs := []string{bech32Yes, bech32No}","handlingStrategy":"validation","validationCode":"// Plugin-side: encode both options identically\nyes, _ := bech32.Encode(\"\", []byte(\"yes\"))\nno, _ := bech32.Encode(\"\", []byte(\"no\"))","typeGuard":null,"tryCatchPattern":"if err := unwrap(); err != nil && strings.Contains(err.Error(), \"invalid NO option encoding\") {\n    return fmt.Errorf(\"plugin confirm NO label is not bech32; upgrade plugin\")\n}","preventionTips":["Apply the same encoding helper to YES and NO","Send a one-argument confirm when NO is not needed","Add unit tests for stanza argument encoding"],"tags":["go","age","plugin-protocol","bech32","confirm-stanza"],"backgroundTag":"plugin-protocol-violation","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}