Skip to content

fix(config): expand environment variable references in YAML config#699

Open
kajirita2002 wants to merge 1 commit intoComposioHQ:mainfrom
kajirita2002:fix/config-env-var-expansion-clean
Open

fix(config): expand environment variable references in YAML config#699
kajirita2002 wants to merge 1 commit intoComposioHQ:mainfrom
kajirita2002:fix/config-env-var-expansion-clean

Conversation

@kajirita2002
Copy link

@kajirita2002 kajirita2002 commented Mar 26, 2026

Summary

  • loadConfig and loadConfigWithPath in packages/core/src/config.ts now substitute ${VAR} placeholders in the raw YAML string with process.env values before parsing
  • If the referenced env var is not set, the placeholder is left unchanged (e.g. ${UNSET_VAR} stays as-is)
  • Two new test cases added in packages/core/__tests__/config.test.ts covering successful substitution and the unset-variable fallback

Motivation

Users were forced to hardcode secrets (e.g. Slack webhook URLs) directly in agent-orchestrator.yaml because env var references like ${SLACK_WEBHOOK_URL} were passed through as literal strings to the YAML parser. This change unblocks the common pattern of keeping secrets in environment variables and referencing them from config files.

Usage after fix

# agent-orchestrator.yaml
notifiers:
  slack:
    plugin: slack
    webhookUrl: ${SLACK_WEBHOOK_URL}   # ← now properly resolved at load time
export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
ao start

Closes #701

Read the raw YAML content and substitute \${VAR} placeholders with
process.env values before parsing, so users can reference env vars
(e.g. Slack webhook URLs) in agent-orchestrator.yaml without hardcoding
secrets. Unset variables are left as-is. Added tests for both cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


const config = loadConfig(configPath);
expect(config.port).toBe(7000);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unset env var test contains no variable references

Medium Severity

The test "should leave unset environment variable references unchanged" writes a YAML config that contains zero ${...} placeholders. The ${testDir} on the path: line is a JavaScript template literal interpolated at write time, not a literal env var reference for the config loader. Since no \${UNSET_VAR_12345} or similar escaped reference appears in the YAML content, the substitution logic is never exercised. This test passes regardless of whether the feature works.

Fix in Cursor Fix in Web

expect(config.projects["env-project"]).toBeDefined();
// Verify the raw YAML was parsed after substitution by checking port
expect(config.port).toBe(6000);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expansion test never verifies substituted value exists

Medium Severity

The test "should expand environment variable references in config" places the \${TEST_SLACK_WEBHOOK_URL} reference inside a notifications.slack.webhookUrl field, but ProjectConfigSchema has no notifications property and doesn't use .passthrough(), so Zod silently strips it. The assertions only check that the project is defined and the port is 6000—both true even without any substitution. The test would pass if the substitution regex were completely broken.

Fix in Cursor Fix in Web


const raw = readFileSync(path, "utf-8");
const parsed = parseYaml(raw);
const substituted = raw.replace(/\$\{([^}]+)\}/g, (_, key) => process.env[key] ?? `\${${key}}`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Env var values with YAML metacharacters break parsing

Medium Severity

The raw.replace() injects env var values directly into the YAML string before parsing. If a value contains YAML metacharacters (colons followed by spaces, #, newlines, {, [, etc.), it can alter the document structure or cause parse errors. Since the PR encourages unquoted usage like webhookUrl: ${SLACK_WEBHOOK_URL}, values containing these characters will silently corrupt the config or throw cryptic YAML parse errors.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: ${VAR} references in agent-orchestrator.yaml are not expanded

1 participant