@@ -90,11 +90,11 @@ fn merged_env_strips_reserved_keys_from_persona() {
9090 // persona data (e.g. older record from before validation existed),
9191 // it must be stripped before reaching the child process.
9292 let persona = map ( & [
93- ( "SPROUT_PRIVATE_KEY " , "nsec1evil" ) ,
93+ ( "BUZZ_PRIVATE_KEY " , "nsec1evil" ) ,
9494 ( "ANTHROPIC_API_KEY" , "ok" ) ,
9595 ] ) ;
9696 let merged = merged_user_env ( & persona, & BTreeMap :: new ( ) ) ;
97- assert ! ( !merged. contains_key( "SPROUT_PRIVATE_KEY " ) ) ;
97+ assert ! ( !merged. contains_key( "BUZZ_PRIVATE_KEY " ) ) ;
9898 assert_eq ! (
9999 merged. get( "ANTHROPIC_API_KEY" ) . map( String :: as_str) ,
100100 Some ( "ok" )
@@ -105,22 +105,22 @@ fn merged_env_strips_reserved_keys_from_persona() {
105105fn merged_env_strips_reserved_keys_from_agent ( ) {
106106 let agent = map ( & [
107107 ( "NOSTR_PRIVATE_KEY" , "nsec1evil" ) ,
108- ( "SPROUT_AUTH_TAG " , "{}" ) ,
108+ ( "BUZZ_AUTH_TAG " , "{}" ) ,
109109 ( "FOO" , "1" ) ,
110110 ] ) ;
111111 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
112112 assert ! ( !merged. contains_key( "NOSTR_PRIVATE_KEY" ) ) ;
113- assert ! ( !merged. contains_key( "SPROUT_AUTH_TAG " ) ) ;
113+ assert ! ( !merged. contains_key( "BUZZ_AUTH_TAG " ) ) ;
114114 assert_eq ! ( merged. get( "FOO" ) . map( String :: as_str) , Some ( "1" ) ) ;
115115 assert_eq ! ( merged. len( ) , 1 ) ;
116116}
117117
118118#[ test]
119119fn merged_env_strips_reserved_case_insensitive ( ) {
120120 // Unix env vars are case-sensitive at the syscall level, but we
121- // refuse close-typo variants too — a lowercase `sprout_private_key `
121+ // refuse close-typo variants too — a lowercase `buzz_private_key `
122122 // is almost certainly a footgun, not a legitimate use.
123- let agent = map ( & [ ( "sprout_private_key " , "x" ) , ( "Sprout_Auth_Tag " , "y" ) ] ) ;
123+ let agent = map ( & [ ( "buzz_private_key " , "x" ) , ( "Buzz_Auth_Tag " , "y" ) ] ) ;
124124 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
125125 assert ! ( merged. is_empty( ) ) ;
126126}
@@ -132,16 +132,16 @@ fn is_reserved_recognises_full_list() {
132132 }
133133 assert ! ( !is_reserved_env_key( "GOOSE_MODE" ) ) ;
134134 assert ! ( !is_reserved_env_key( "ANTHROPIC_API_KEY" ) ) ;
135- assert ! ( !is_reserved_env_key( "SPROUT_ACP_MODEL " ) ) ; // behavior knob
136- assert ! ( !is_reserved_env_key( "SPROUT_TOOLSETS " ) ) ;
135+ assert ! ( !is_reserved_env_key( "BUZZ_ACP_MODEL " ) ) ; // behavior knob
136+ assert ! ( !is_reserved_env_key( "BUZZ_TOOLSETS " ) ) ;
137137}
138138
139139#[ test]
140140fn reserved_keys_include_agent_owner_for_legacy_records ( ) {
141- // Legacy records without auth_tag fall back to SPROUT_ACP_AGENT_OWNER
141+ // Legacy records without auth_tag fall back to BUZZ_ACP_AGENT_OWNER
142142 // to enforce the respond-to gate. Must not be user-overridable.
143- assert ! ( is_reserved_env_key( "SPROUT_ACP_AGENT_OWNER " ) ) ;
144- let agent = map ( & [ ( "SPROUT_ACP_AGENT_OWNER " , "imposter" ) ] ) ;
143+ assert ! ( is_reserved_env_key( "BUZZ_ACP_AGENT_OWNER " ) ) ;
144+ let agent = map ( & [ ( "BUZZ_ACP_AGENT_OWNER " , "imposter" ) ] ) ;
145145 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
146146 assert ! ( merged. is_empty( ) ) ;
147147}
@@ -151,7 +151,7 @@ fn reserved_keys_include_respond_to_gate() {
151151 // Respond-to mode + allowlist control who the agent answers.
152152 // Overriding via env_vars would let the running agent answer
153153 // anyone even when the UI/record says owner-only.
154- for key in [ "SPROUT_ACP_RESPOND_TO " , "SPROUT_ACP_RESPOND_TO_ALLOWLIST " ] {
154+ for key in [ "BUZZ_ACP_RESPOND_TO " , "BUZZ_ACP_RESPOND_TO_ALLOWLIST " ] {
155155 assert ! ( is_reserved_env_key( key) , "{key} should be reserved" ) ;
156156 let agent = map ( & [ ( key, "anyone" ) ] ) ;
157157 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
@@ -164,9 +164,9 @@ fn reserved_keys_include_code_execution_surface() {
164164 // The agent/MCP command + args are what Sprout actually exec's.
165165 // Overriding lets the user run arbitrary code as the agent.
166166 for key in [
167- "SPROUT_ACP_AGENT_COMMAND " ,
168- "SPROUT_ACP_AGENT_ARGS " ,
169- "SPROUT_ACP_MCP_COMMAND " ,
167+ "BUZZ_ACP_AGENT_COMMAND " ,
168+ "BUZZ_ACP_AGENT_ARGS " ,
169+ "BUZZ_ACP_MCP_COMMAND " ,
170170 ] {
171171 assert ! ( is_reserved_env_key( key) , "{key} should be reserved" ) ;
172172 }
@@ -176,8 +176,8 @@ fn reserved_keys_include_code_execution_surface() {
176176fn reserved_keys_include_relay_url ( ) {
177177 // Overriding the relay URL could redirect the agent to an
178178 // attacker-controlled relay.
179- assert ! ( is_reserved_env_key( "SPROUT_RELAY_URL " ) ) ;
180- let agent = map ( & [ ( "SPROUT_RELAY_URL " , "ws://attacker.example" ) ] ) ;
179+ assert ! ( is_reserved_env_key( "BUZZ_RELAY_URL " ) ) ;
180+ let agent = map ( & [ ( "BUZZ_RELAY_URL " , "ws://attacker.example" ) ] ) ;
181181 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
182182 assert ! ( merged. is_empty( ) ) ;
183183}
@@ -192,21 +192,21 @@ fn validate_keys_accepts_normal_env() {
192192
193193#[ test]
194194fn validate_keys_rejects_reserved ( ) {
195- let env = map ( & [ ( "SPROUT_PRIVATE_KEY " , "nsec1evil" ) ] ) ;
195+ let env = map ( & [ ( "BUZZ_PRIVATE_KEY " , "nsec1evil" ) ] ) ;
196196 let err = validate_user_env_keys ( & env) . unwrap_err ( ) ;
197- assert ! ( err. contains( "SPROUT_PRIVATE_KEY " ) , "got: {err}" ) ;
197+ assert ! ( err. contains( "BUZZ_PRIVATE_KEY " ) , "got: {err}" ) ;
198198 assert ! ( err. contains( "reserved" ) , "got: {err}" ) ;
199199}
200200
201201#[ test]
202202fn validate_keys_lists_all_reserved_keys_found ( ) {
203203 let env = map ( & [
204- ( "SPROUT_PRIVATE_KEY " , "x" ) ,
204+ ( "BUZZ_PRIVATE_KEY " , "x" ) ,
205205 ( "NOSTR_PRIVATE_KEY" , "y" ) ,
206206 ( "ANTHROPIC_API_KEY" , "ok" ) ,
207207 ] ) ;
208208 let err = validate_user_env_keys ( & env) . unwrap_err ( ) ;
209- assert ! ( err. contains( "SPROUT_PRIVATE_KEY " ) ) ;
209+ assert ! ( err. contains( "BUZZ_PRIVATE_KEY " ) ) ;
210210 assert ! ( err. contains( "NOSTR_PRIVATE_KEY" ) ) ;
211211}
212212
@@ -228,8 +228,8 @@ fn validate_keys_accepts_empty_map() {
228228// Rust's `Command::env(k, v)` will accept a key containing `=` and
229229// pass it straight into the child's environ block, where
230230// `getenv("PREFIX")` matches anything after the first `=`. Concretely:
231- // `c.env("SPROUT_AUTH_TAG =x", "forged")` results in the child seeing
232- // `SPROUT_AUTH_TAG =x=forged` and `getenv("SPROUT_AUTH_TAG ") == "x=forged"`.
231+ // `c.env("BUZZ_AUTH_TAG =x", "forged")` results in the child seeing
232+ // `BUZZ_AUTH_TAG =x=forged` and `getenv("BUZZ_AUTH_TAG ") == "x=forged"`.
233233// That bypasses our reserved-key check, which compares strings.
234234// These tests pin the fix at the validator boundary.
235235
@@ -250,35 +250,35 @@ fn is_well_formed_accepts_posix_keys() {
250250#[ test]
251251fn is_well_formed_rejects_malformed_keys ( ) {
252252 for key in [
253- "" , // empty
254- "=" , // bare equals
255- "SPROUT_AUTH_TAG =x" , // =-in-key bypass
256- "SPROUT_PRIVATE_KEY =" , // trailing equals
257- "FOO BAR" , // space
258- " FOO" , // leading whitespace
259- "FOO\n BAR" , // newline
260- "FOO\0 BAR" , // NUL
261- "123_LEADING_DIGIT" , // POSIX forbids leading digit
262- "FOO-BAR" , // hyphen
263- "FOO.BAR" , // dot
264- "FOO/BAR" , // slash
265- "ünicode_key" , // non-ASCII
253+ "" , // empty
254+ "=" , // bare equals
255+ "BUZZ_AUTH_TAG =x" , // =-in-key bypass
256+ "BUZZ_PRIVATE_KEY =" , // trailing equals
257+ "FOO BAR" , // space
258+ " FOO" , // leading whitespace
259+ "FOO\n BAR" , // newline
260+ "FOO\0 BAR" , // NUL
261+ "123_LEADING_DIGIT" , // POSIX forbids leading digit
262+ "FOO-BAR" , // hyphen
263+ "FOO.BAR" , // dot
264+ "FOO/BAR" , // slash
265+ "ünicode_key" , // non-ASCII
266266 ] {
267267 assert ! ( !is_well_formed_env_key( key) , "{key:?} should be malformed" ) ;
268268 }
269269}
270270
271271#[ test]
272272fn validate_keys_rejects_equals_in_key_bypass ( ) {
273- // The actual exploit: `SPROUT_AUTH_TAG =x` smuggles a value past
273+ // The actual exploit: `BUZZ_AUTH_TAG =x` smuggles a value past
274274 // the reserved-key string compare and into the child's environ.
275- let env = map ( & [ ( "SPROUT_AUTH_TAG =x" , "forged" ) ] ) ;
275+ let env = map ( & [ ( "BUZZ_AUTH_TAG =x" , "forged" ) ] ) ;
276276 let err = validate_user_env_keys ( & env) . unwrap_err ( ) ;
277277 assert ! ( err. contains( "[A-Za-z_]" ) , "got: {err}" ) ;
278278 // After P2 fix the key is truncated at `=` in the error to avoid
279279 // surfacing pasted secrets — only the prefix should appear, with an
280280 // ellipsis marking that we elided trailing content.
281- assert ! ( err. contains( "SPROUT_AUTH_TAG " ) , "got: {err}" ) ;
281+ assert ! ( err. contains( "BUZZ_AUTH_TAG " ) , "got: {err}" ) ;
282282 assert ! ( err. contains( '…' ) , "expected ellipsis marker: {err}" ) ;
283283 assert ! ( !err. contains( "=x" ) , "leak of value past `=`: {err}" ) ;
284284}
@@ -296,7 +296,7 @@ fn validate_keys_reports_malformed_before_reserved() {
296296 // the way that other key is reserved" — they've got a typo to fix
297297 // first. Ordering is a UX detail but pinning it stops the message
298298 // from churning.
299- let env = map ( & [ ( "SPROUT_AUTH_TAG =x" , "v" ) , ( "SPROUT_PRIVATE_KEY " , "v" ) ] ) ;
299+ let env = map ( & [ ( "BUZZ_AUTH_TAG =x" , "v" ) , ( "BUZZ_PRIVATE_KEY " , "v" ) ] ) ;
300300 let err = validate_user_env_keys ( & env) . unwrap_err ( ) ;
301301 assert ! ( err. contains( "[A-Za-z_]" ) , "got: {err}" ) ;
302302 assert ! ( !err. contains( "reserved" ) , "got: {err}" ) ;
@@ -307,12 +307,12 @@ fn merged_env_drops_malformed_keys() {
307307 // Defense in depth: on-disk records written before the validator
308308 // tightened must not be able to smuggle reserved keys through.
309309 let agent = map ( & [
310- ( "SPROUT_AUTH_TAG =x" , "forged" ) ,
310+ ( "BUZZ_AUTH_TAG =x" , "forged" ) ,
311311 ( "FOO=bar" , "v" ) ,
312312 ( "LEGIT" , "ok" ) ,
313313 ] ) ;
314314 let merged = merged_user_env ( & BTreeMap :: new ( ) , & agent) ;
315- assert ! ( !merged. contains_key( "SPROUT_AUTH_TAG =x" ) ) ;
315+ assert ! ( !merged. contains_key( "BUZZ_AUTH_TAG =x" ) ) ;
316316 assert ! ( !merged. contains_key( "FOO=bar" ) ) ;
317317 assert_eq ! ( merged. get( "LEGIT" ) . map( String :: as_str) , Some ( "ok" ) ) ;
318318 assert_eq ! ( merged. len( ) , 1 ) ;
@@ -420,7 +420,7 @@ fn merged_env_drops_oversize_value() {
420420// ── derived provider/model key filter ──────────────────────────────
421421//
422422// Pack import must strip derived env keys (GOOSE_MODEL, GOOSE_PROVIDER,
423- // SPROUT_AGENT_MODEL, SPROUT_AGENT_PROVIDER ) so they don't shadow the
423+ // BUZZ_AGENT_MODEL, BUZZ_AGENT_PROVIDER ) so they don't shadow the
424424// structured PersonaRecord.model / PersonaRecord.provider fields after
425425// the user edits them in the UI.
426426
@@ -438,16 +438,16 @@ fn is_derived_key_matches_all_known_keys() {
438438fn is_derived_key_is_case_insensitive ( ) {
439439 assert ! ( is_derived_provider_model_key( "goose_model" ) ) ;
440440 assert ! ( is_derived_provider_model_key( "Goose_Provider" ) ) ;
441- assert ! ( is_derived_provider_model_key( "sprout_agent_model " ) ) ;
442- assert ! ( is_derived_provider_model_key( "SPROUT_AGENT_PROVIDER " ) ) ;
441+ assert ! ( is_derived_provider_model_key( "buzz_agent_model " ) ) ;
442+ assert ! ( is_derived_provider_model_key( "BUZZ_AGENT_PROVIDER " ) ) ;
443443}
444444
445445#[ test]
446446fn is_derived_key_does_not_match_unrelated_keys ( ) {
447447 assert ! ( !is_derived_provider_model_key( "GOOSE_TEMPERATURE" ) ) ;
448448 assert ! ( !is_derived_provider_model_key( "GOOSE_CONTEXT_LIMIT" ) ) ;
449449 assert ! ( !is_derived_provider_model_key( "ANTHROPIC_API_KEY" ) ) ;
450- assert ! ( !is_derived_provider_model_key( "SPROUT_PRIVATE_KEY " ) ) ;
450+ assert ! ( !is_derived_provider_model_key( "BUZZ_PRIVATE_KEY " ) ) ;
451451 assert ! ( !is_derived_provider_model_key( "MODEL" ) ) ;
452452 assert ! ( !is_derived_provider_model_key( "PROVIDER" ) ) ;
453453}
@@ -460,8 +460,8 @@ fn filter_derived_strips_provider_model_keys_preserves_rest() {
460460 "claude-sonnet-4-20250514" . to_string( ) ,
461461 ) ,
462462 ( "GOOSE_PROVIDER" . to_string( ) , "anthropic" . to_string( ) ) ,
463- ( "SPROUT_AGENT_MODEL " . to_string( ) , "gpt-4o" . to_string( ) ) ,
464- ( "SPROUT_AGENT_PROVIDER " . to_string( ) , "openai" . to_string( ) ) ,
463+ ( "BUZZ_AGENT_MODEL " . to_string( ) , "gpt-4o" . to_string( ) ) ,
464+ ( "BUZZ_AGENT_PROVIDER " . to_string( ) , "openai" . to_string( ) ) ,
465465 ( "GOOSE_TEMPERATURE" . to_string( ) , "0.7" . to_string( ) ) ,
466466 ( "ANTHROPIC_API_KEY" . to_string( ) , "sk-test" . to_string( ) ) ,
467467 ] ;
0 commit comments