Make login default to production, not stored env#205
Conversation
| # the profile to. The browser OAuth + AMS flow reads environments.active(), so | ||
| # re-set the process global here, not just the stored/reported name. | ||
| env_obj = environments.resolve(state.env, None) | ||
| environments.set_active(env_obj) |
There was a problem hiding this comment.
environments.set_active(env_obj) mutates process-global active environment, risking cross-request/session state leakage; avoid or gate process-global mutation (e.g., use request-scoped context) or clearly document/serialize access.
Details
✨ AI Reasoning
The new code resolves an environment and then calls environments.set_active(env_obj), which mutates a process-global active environment. Module-level or process-global state mutations in server/CLI contexts can cause state to persist across invocations, leaking user-specific context or causing race conditions. The previous behavior only read environments.active(), so this change worsens the global-state mutation risk by writing into it. This is introduced in the current diff where the set_active call was added.
🔧 How do I fix it?
Avoid storing request-specific data in module-level variables. Use request-scoped variables or explicitly mark shared caches as intentional.
Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info
There was a problem hiding this comment.
@AikidoSec ignore: This is the established, intentional pattern in this codebase, not a leak. The active environment is a process-global set once per CLI invocation (main.py calls environments.set_active(...) at startup; see aai_cli/core/environments.py and the architecture note in AGENTS.md). assembly runs as a single-shot process per command — there is no shared server request scope to leak across. The test suite already guards against cross-test bleed via the autouse reset_active_environment fixture in tests/conftest.py. The browser OAuth + AMS flow reads environments.active(), so login must re-set it to the resolved environment for the flow to target the right hosts; a request-scoped rewrite would be a repo-wide refactor against the documented design.
Generated by Claude Code
There was a problem hiding this comment.
✅ Based on your feedback, we ignored this issue because of the following reason:
This is the established, intentional pattern in this codebase, not a leak. The active environment is a process-global set once per CLI invocation (
main.pycallsenvironments.set_active(...)at startup; seeaai_cli/core/environments.pyand the architecture note inAGENTS.md).assemblyruns as a single-shot process per command — there is no shared server request scope to leak across. The test suite already guards against cross-test bleed via the autousereset_active_environmentfixture intests/conftest.py. The browser OAuth + AMS flow readsenvironments.active(), so login must re-set it to the resolved environment for the flow to target the right hosts; a request-scoped rewrite would be a repo-wide refactor against the documented design.
Generated by Claude Code
…d env A bare `assembly login` resolved its target environment via `environments.active()`, which inherits the profile's previously-stored env. So re-signing-in on a profile that was once bound to the sandbox silently re-targeted the sandbox. Resolve login's environment ignoring the profile's stored env so it defaults to production; an explicit --env/--sandbox (or AAI_ENV) still selects the environment and becomes the one the profile binds to. Re-set the active environment too, since the browser OAuth + AMS flow reads environments.active(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYvBVVNW1FdpLDxTdmUya3
7037f59 to
2a3ed01
Compare
Summary
Change the
assembly logincommand to always default to production, rather than inheriting the profile's previously-stored environment. This prevents a bare re-login from silently re-targeting a sandbox environment the profile happened to be bound to.Changes
Login command behavior: Modified
aai_cli/commands/login.pyto explicitly resolve and set the active environment to production (or the explicitly-provided--env/--sandbox/AAI_ENV) before running the OAuth flow, rather than reading the profile's stored environment binding.environments.active(), so the process global is now set here to ensure the flow runs against the correct environment.--env,--sandbox, orAAI_ENVstill takes precedence and becomes the environment the profile is bound to.Documentation: Updated
aai_cli/skills/aai-cli/references/account.mdto clarify that login defaults to production and explain the rationale (preventing silent re-targeting of sandboxes on re-login).Test coverage: Added two new tests in
tests/test_login.py:test_login_defaults_to_production_ignoring_stored_sandbox_env: Verifies that a bareassembly logindefaults to production even when the profile was previously bound to a sandbox.test_login_explicit_sandbox_still_overrides_production_default: Verifies that an explicit--sandboxflag still overrides the production default.Implementation Details
The key change is in the login command's
body()function: instead of readingenvironments.active().namedirectly (which would inherit the profile's stored env), we now:environments.resolve(state.env, None)to get the environment object (respecting explicit flags/env vars, defaulting to None)environments.set_active(env_obj)to set the process globalThis ensures the OAuth flow sees the correct active environment and the profile is bound to the intended target.
https://claude.ai/code/session_01JYvBVVNW1FdpLDxTdmUya3