Skip to content

feat: add {file:path} template support for skill MCP env values#2604

Open
sanoyphilippe wants to merge 3 commits intocode-yeongyu:devfrom
sanoyphilippe:feat/file-template-env-expander
Open

feat: add {file:path} template support for skill MCP env values#2604
sanoyphilippe wants to merge 3 commits intocode-yeongyu:devfrom
sanoyphilippe:feat/file-template-env-expander

Conversation

@sanoyphilippe
Copy link
Copy Markdown
Contributor

@sanoyphilippe sanoyphilippe commented Mar 16, 2026

Summary

  • Add {file:path} template support for skill MCP env values, enabling secrets to be read from files at MCP startup
  • Matches OpenCode's native {file:...} config capability for skill-embedded MCPs

Changes

  • Modified src/features/claude-code-mcp-loader/env-expander.ts to resolve {file:path} templates before ${VAR} expansion
  • Added expandFileTemplates function that reads file content with proper error handling
  • Updated expandEnvVars to call expandFileTemplates first, maintaining backward compatibility
  • Added comprehensive tests in env-expander.test.ts covering file template resolution, error cases, and integration with existing env var expansion

Testing

bun run typecheck
bun test src/features/claude-code-mcp-loader/

Related Issues

Enables skill-embedded MCPs to authenticate using file-based secrets (e.g., `{file:.secrets/api-token}`), bringing parity with OpenCode's native MCP config `environment` field.


Summary by cubic

Add {file:path} support for skill MCP env values so secrets load from files at startup, matching OpenCode’s native config. Uses sentinel-based expansion with a safe replacer so ${VAR} and file templates can mix without corrupting $ patterns; file contents are trimmed and never re-expanded.

  • New Features
    • Resolves {file:...} relative to optional baseDir (defaults to process.cwd()), with ~/ homedir support.
    • Works in nested objects and arrays via expandEnvVarsInObject(baseDir?).
    • Missing files now throw a clear error.

Written for commit c1b02e6. Summary will update on new commits.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 16, 2026

All contributors have signed the CLA. Thank you! ✅
Posted by the CLA Assistant Lite bot.

@gitguardian
Copy link
Copy Markdown

gitguardian bot commented Mar 16, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
- - Generic High Entropy Secret 6c89089 src/features/claude-code-mcp-loader/env-expander.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

5 issues found across 2 files

Confidence score: 2/5

  • There is high regression risk because src/features/claude-code-mcp-loader/env-expander.test.ts currently codifies behavior that diverges from OpenCode in core cases (~/ homedir expansion, config-directory-relative resolution, and missing {file:path} error handling), which can break real-world secret/file template usage.
  • src/features/claude-code-mcp-loader/env-expander.ts expands file content and then re-expands ${...} as env vars, so secret file contents may be unintentionally altered, creating concrete user-facing misconfiguration risk.
  • The /tmp test setup in src/features/claude-code-mcp-loader/env-expander.test.ts is less severe but can cause cross-platform failures and flaky parallel runs, adding uncertainty to validation.
  • Pay close attention to src/features/claude-code-mcp-loader/env-expander.ts and src/features/claude-code-mcp-loader/env-expander.test.ts - compatibility semantics and expansion order need alignment to avoid breaking OpenCode-style file/env resolution.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/claude-code-mcp-loader/env-expander.test.ts">

<violation number="1" location="src/features/claude-code-mcp-loader/env-expander.test.ts:7">
P2: Hardcoded `/tmp` directory breaks cross-platform compatibility and risks test interference during concurrent execution. Use `os.tmpdir()` with `fs.mkdtempSync()` to create isolated temporary directories.</violation>

<violation number="2" location="src/features/claude-code-mcp-loader/env-expander.test.ts:23">
P1: Custom agent: **Opencode Compatibility**

The implementation misses support for `~/` homedir expansion, which is standard in OpenCode's `{file:...}` resolution and its primary documented use case for secrets. Add `~/` support using `os.homedir()` to match OpenCode's native capability.</violation>

<violation number="3" location="src/features/claude-code-mcp-loader/env-expander.test.ts:38">
P1: Custom agent: **Opencode Compatibility**

OpenCode's native behavior throws an error when a `{file:path}` reference is missing. This test explicitly asserts that the original string is returned instead, which deviates from OpenCode and poses a security risk of leaking template literals (like `"{file:.secrets/token}"`) to external services. Update the implementation to throw an error for missing files to match OpenCode, and update this test accordingly.</violation>

<violation number="4" location="src/features/claude-code-mcp-loader/env-expander.test.ts:44">
P1: Custom agent: **Opencode Compatibility**

OpenCode resolves relative file templates against the configuration file's directory, not `process.cwd()`. Using `cwd` will break relative paths in global or project-level configs (e.g., `~/.claude.json`) if the user runs commands from a different directory. Update the implementation to accept the config file's directory as an argument and resolve relative paths against it instead of `cwd`.</violation>
</file>

<file name="src/features/claude-code-mcp-loader/env-expander.ts">

<violation number="1" location="src/features/claude-code-mcp-loader/env-expander.ts:19">
P1: Sequential expansion subjects file secrets to environment variable replacement, potentially corrupting them. File content containing `${...}` sequences will be incorrectly expanded as environment variables.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/claude-code-mcp-loader/env-expander.ts">

<violation number="1" location="src/features/claude-code-mcp-loader/env-expander.ts:47">
P1: JavaScript's `String.prototype.replace()` interprets special replacement patterns (e.g., `$$` → `$`, `$&` → matched substring) when the replacement is a string. File contents containing `$` characters (bcrypt hashes like `$2a$...` or tokens with `$$`) will be silently corrupted. Use a replacer function `result.replace(placeholder, () => content)` to prevent pattern evaluation and ensure literal string insertion.</violation>
</file>

<file name="src/features/claude-code-mcp-loader/env-expander.test.ts">

<violation number="1" location="src/features/claude-code-mcp-loader/env-expander.test.ts:84">
P1: Test writes to and deletes from the user's real home directory, risking data loss</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@sanoyphilippe
Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions bot added a commit that referenced this pull request Mar 16, 2026
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Auto-approved: The PR safely implements file template expansion using a multi-phase approach that preserves existing env var logic and prevents accidental re-expansion or interference.

@code-yeongyu code-yeongyu added the triage:feature-request Feature or enhancement request label Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:feature-request Feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants