mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-17 23:30:09 +02:00
fix(gstack-paths): guard CLAUDE_PLUGIN_DATA against cross-plugin contamination (#1569)
gstack-paths previously trusted CLAUDE_PLUGIN_DATA as a fallback for GSTACK_STATE_ROOT whenever GSTACK_HOME was unset. When another plugin (e.g. Codex) persists its own CLAUDE_PLUGIN_DATA into the session env via CLAUDE_ENV_FILE, gstack picked it up and wrote checkpoints, analytics, and learnings into that plugin's directory. Anyone with the Codex plugin installed alongside gstack hit this silently. Fix: guard the CLAUDE_PLUGIN_DATA branch so it only fires when CLAUDE_PLUGIN_ROOT confirms we're running as the gstack plugin (path contains "gstack"). Skill installs fall through to \$HOME/.gstack. Contributed by @ElliotDrel via #1570. Closes #1569. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,12 +41,28 @@ describe('gstack-paths', () => {
|
||||
expect(got.GSTACK_STATE_ROOT).toBe('/tmp/explicit-state');
|
||||
});
|
||||
|
||||
test('CLAUDE_PLUGIN_DATA wins over HOME when GSTACK_HOME unset', () => {
|
||||
const got = run({
|
||||
CLAUDE_PLUGIN_DATA: '/tmp/plugin-data',
|
||||
test('CLAUDE_PLUGIN_DATA ignored when CLAUDE_PLUGIN_ROOT is absent or non-gstack', () => {
|
||||
// Without CLAUDE_PLUGIN_ROOT, falls through to HOME path.
|
||||
const noRoot = run({ CLAUDE_PLUGIN_DATA: '/tmp/plugin-data', HOME: '/tmp/home' });
|
||||
expect(noRoot.GSTACK_STATE_ROOT).toBe('/tmp/home/.gstack');
|
||||
|
||||
// With a CLAUDE_PLUGIN_ROOT that doesn't contain "gstack" (e.g. the codex plugin),
|
||||
// still falls through to HOME path — this is the cross-plugin contamination scenario.
|
||||
const wrongRoot = run({
|
||||
CLAUDE_PLUGIN_DATA: '/tmp/codex-data',
|
||||
CLAUDE_PLUGIN_ROOT: '/tmp/openai-codex',
|
||||
HOME: '/tmp/home',
|
||||
});
|
||||
expect(got.GSTACK_STATE_ROOT).toBe('/tmp/plugin-data');
|
||||
expect(wrongRoot.GSTACK_STATE_ROOT).toBe('/tmp/home/.gstack');
|
||||
});
|
||||
|
||||
test('CLAUDE_PLUGIN_DATA respected when CLAUDE_PLUGIN_ROOT identifies gstack', () => {
|
||||
const got = run({
|
||||
CLAUDE_PLUGIN_DATA: '/tmp/gstack-plugin-data',
|
||||
CLAUDE_PLUGIN_ROOT: '/tmp/gstack-garrytan',
|
||||
HOME: '/tmp/home',
|
||||
});
|
||||
expect(got.GSTACK_STATE_ROOT).toBe('/tmp/gstack-plugin-data');
|
||||
});
|
||||
|
||||
test('HOME-derived state root when GSTACK_HOME and CLAUDE_PLUGIN_DATA unset', () => {
|
||||
|
||||
Reference in New Issue
Block a user