Skip to content

fix: claude-lane/task_1780281408931_wl61hi99e-20260602145932 - #31

Closed
nehraa wants to merge 1 commit into
mainfrom
claude-lane/task_1780281408931_wl61hi99e-20260602145932
Closed

fix: claude-lane/task_1780281408931_wl61hi99e-20260602145932#31
nehraa wants to merge 1 commit into
mainfrom
claude-lane/task_1780281408931_wl61hi99e-20260602145932

Conversation

@nehraa

@nehraa nehraa commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Automated DevPulse recovery — see commit history.


Recovered by recover_unprd_tasks.py

Copilot AI review requested due to automatic review settings June 3, 2026 11:43
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@nehraa has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 57 minutes and 10 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 96c63e42-b4d0-43a4-bbb2-2a29d570ae11

📥 Commits

Reviewing files that changed from the base of the PR and between a896899 and 1e5457e.

📒 Files selected for processing (1)
  • src/lib/opencode/config.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude-lane/task_1780281408931_wl61hi99e-20260602145932

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Secure OpenCode API key from child process exposure

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Prevent API key exposure via environment variables to child processes
• Write API key to temporary file with restrictive permissions (0600)
• Use mkdtempSync to create secure, unguessable temp directory
• Pass file path instead of key value in environment variable
Diagram
flowchart LR
  A["API Key in Config"] --> B["Write to Temp File<br/>mode 0600"]
  B --> C["chmod 0600<br/>Belt-and-suspenders"]
  C --> D["Pass File Path<br/>in Env Var"]
  D --> E["Child Process<br/>Reads from File"]
  F["Prevents /proc/pid/environ<br/>Exposure"] -.-> D

Loading

Grey Divider

File Changes

1. src/lib/opencode/config.ts 🐞 Bug fix +22/-2

Secure API key handling with temp file storage

• Added imports for file system operations (writeFileSync, mkdtempSync, chmodSync) and path
 utilities
• Enhanced security documentation explaining API key protection mechanism
• Modified configToEnv function to write API key to secure temp file instead of environment
 variable
• Implemented dual chmod calls to ensure restrictive permissions despite umask interference

src/lib/opencode/config.ts


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 3, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0)

Grey Divider


Action required

1. API key still in env 🐞 Bug ⛨ Security
Description
Despite the new claim that the API key is never placed in environment variables,
OpencodeServer.start() still sets OPENCODE_CONFIG_CONTENT to JSON.stringify(config), which includes
config.apiKey and therefore exposes the key in the child process environment.
Code

src/lib/opencode/config.ts[R55-63]

Evidence
The PR-added comment asserts the API key is never put into environment variables, but the server
startup code explicitly places the entire config object (which includes apiKey) into an
environment variable passed to the child process.

src/lib/opencode/config.ts[54-90]
src/lib/opencode/server.ts[40-45]
src/lib/opencode/types.ts[19-28]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`OPENCODE_CONFIG_CONTENT` is set to `JSON.stringify(config)` and `config` includes `apiKey`, so the spawned `opencode` process still receives the API key via environment variables, contradicting the new security guarantee.

### Issue Context
The PR moved provider API key env vars to a temp file, but `OPENCODE_CONFIG_CONTENT` continues to serialize and export the entire config object.

### Fix Focus Areas
- src/lib/opencode/server.ts[40-45]
- src/lib/opencode/types.ts[19-28]

### Suggested fix
- Build a sanitized config for `OPENCODE_CONFIG_CONTENT` that omits `apiKey` (or replaces it with a non-secret reference if truly required).
 - Example: `const { apiKey, ...safeConfig } = config; OPENCODE_CONFIG_CONTENT: JSON.stringify(safeConfig)`
- Ensure any other env var or logging path does not include the raw key.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Temp key file not cleaned 🐞 Bug ☼ Reliability
Description
configToEnv() writes the API key into a newly created temp directory but provides no cleanup path,
so API keys persist on disk and repeated starts/restarts will accumulate secret-bearing files under
the system temp directory.
Code

src/lib/opencode/config.ts[R73-79]

Evidence
The new code creates a temp dir and writes the API key to a file, but no other code references these
paths for deletion; the server stop path only kills the process and clears internal state.

src/lib/opencode/config.ts[65-90]
src/lib/opencode/server.ts[91-118]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
A temp directory and key file are created for every `configToEnv()` call, but nothing deletes them. This leaves API keys at rest on disk indefinitely and can also create unbounded growth in the temp directory across restarts.

### Issue Context
`configToEnv()` is used by `OpencodeServer.start()` to construct the environment for the spawned `opencode` process. `OpencodeServer.stop()` kills the process but does not remove any temp files.

### Fix Focus Areas
- src/lib/opencode/config.ts[65-90]
- src/lib/opencode/server.ts[29-86]
- src/lib/opencode/server.ts[88-118]

### Suggested fix
- Change `configToEnv()` (or its caller) to return both:
 1) the env object, and
 2) a cleanup function (or list of created paths) that removes the temp directory.
- In `OpencodeServer.start()`, register cleanup on:
 - normal stop (`stop()`), and
 - child process `exit`/`error` handlers.
- Use best-effort removal: `rmSync(dir, { recursive: true, force: true })` (or async equivalent) and ignore errors.
- (Optional hardening) explicitly ensure the temp directory permissions are owner-only before writing the key file.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request enhances security by writing the API key to a temporary file with restrictive permissions (0600) instead of passing it directly via environment variables. The review feedback highlights critical improvements: explicitly setting the temporary directory permissions to 0700 to prevent local traversal, implementing a cleanup mechanism on process exit to avoid leaking sensitive files, and addressing a security bypass in server.ts where the raw API key is still exposed in the environment through a stringified config object.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +73 to +79
const dir = mkdtempSync(join(tmpdir(), "codeflow-opencode-"));
const keyFile = join(dir, "api_key");
writeFileSync(keyFile, config.apiKey, { mode: 0o600 });
// Belt-and-suspenders: explicitly chmod in case the umask interfered
// with the mode option (writeFileSync's mode is masked by process.umask).
chmodSync(keyFile, 0o600);
env[providerConfig.apiKeyEnvVar] = keyFile;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

There are two important security/robustness improvements here:

  1. Directory Permissions: While the API key file itself is written with 0o600 permissions, the parent directory created by mkdtempSync is subject to the process's umask (often resulting in 0o755 or 0o700). To ensure other local users cannot traverse or list the directory, we should explicitly set the directory permissions to 0o700 using chmodSync(dir, 0o700).
  2. Cleanup Tracking: Push the created directory to createdTempDirs so it can be cleaned up on process exit.

⚠️ Critical Security Warning

While this function goes to great lengths to avoid placing the API key directly in the environment, this protection is completely bypassed in src/lib/opencode/server.ts.

In server.ts (line 44), the entire config object is stringified and placed in the environment:

OPENCODE_CONFIG_CONTENT: JSON.stringify(config),

Since config contains the raw apiKey, the API key is still exposed in the environment variables of the spawned child process. To fix this, you should sanitize the config object in server.ts before stringifying it (e.g., by deleting or replacing the apiKey property).

    const dir = mkdtempSync(join(tmpdir(), "codeflow-opencode-"));
    chmodSync(dir, 0o700);
    createdTempDirs.push(dir);
    const keyFile = join(dir, "api_key");
    writeFileSync(keyFile, config.apiKey, { mode: 0o600 });
    // Belt-and-suspenders: explicitly chmod in case the umask interfered
    // with the mode option (writeFileSync's mode is masked by process.umask).
    chmodSync(keyFile, 0o600);
    env[providerConfig.apiKeyEnvVar] = keyFile;

Comment on lines +5 to +7
import { writeFileSync, mkdtempSync, chmodSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To prevent leaking temporary directories and sensitive API key files on disk indefinitely, we should track the created temporary directories and clean them up when the process exits.

We can import rmSync and register a synchronous process.on('exit') handler to delete these directories.

import { writeFileSync, mkdtempSync, chmodSync, rmSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";

const createdTempDirs: string[] = [];

if (typeof process !== "undefined") {
  process.on("exit", () => {
    for (const dir of createdTempDirs) {
      try {
        rmSync(dir, { recursive: true, force: true });
      } catch {}
    }
  });
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1e5457e44c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Belt-and-suspenders: explicitly chmod in case the umask interfered
// with the mode option (writeFileSync's mode is masked by process.umask).
chmodSync(keyFile, 0o600);
env[providerConfig.apiKeyEnvVar] = keyFile;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore API key values for OpenCode env vars

When starting OpenCode with a hosted provider, this now sets ANTHROPIC_API_KEY/OPENAI_API_KEY/etc. to a temp-file path instead of the API key itself. OpenCode’s config docs distinguish {env:ANTHROPIC_API_KEY} as substituting the environment variable value from {file:...} as reading file contents, so a provider launched through src/lib/opencode/server.ts will receive /tmp/codeflow-opencode-.../api_key as the credential and authentication will fail rather than reading the file.

Useful? React with 👍 / 👎.

Comment on lines +55 to +63
* Convert OpencodeConfig to environment variables for OpenCode CLI.
*
* SECURITY: The API key is NEVER placed directly in the environment.
* Environment variables are readable via `/proc/<pid>/environ` on Linux
* by any local user, which would expose the key to local privilege
* escalation. Instead, the key is written to a temp file with mode
* 0600 (readable/writable only by the owner) and the file path is
* passed as the env var value. The child process is expected to read
* the key from the file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Api key still in env 🐞 Bug ⛨ Security

Despite the new claim that the API key is never placed in environment variables,
OpencodeServer.start() still sets OPENCODE_CONFIG_CONTENT to JSON.stringify(config), which includes
config.apiKey and therefore exposes the key in the child process environment.
Agent Prompt
### Issue description
`OPENCODE_CONFIG_CONTENT` is set to `JSON.stringify(config)` and `config` includes `apiKey`, so the spawned `opencode` process still receives the API key via environment variables, contradicting the new security guarantee.

### Issue Context
The PR moved provider API key env vars to a temp file, but `OPENCODE_CONFIG_CONTENT` continues to serialize and export the entire config object.

### Fix Focus Areas
- src/lib/opencode/server.ts[40-45]
- src/lib/opencode/types.ts[19-28]

### Suggested fix
- Build a sanitized config for `OPENCODE_CONFIG_CONTENT` that omits `apiKey` (or replaces it with a non-secret reference if truly required).
  - Example: `const { apiKey, ...safeConfig } = config; OPENCODE_CONFIG_CONTENT: JSON.stringify(safeConfig)`
- Ensure any other env var or logging path does not include the raw key.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +73 to +79
const dir = mkdtempSync(join(tmpdir(), "codeflow-opencode-"));
const keyFile = join(dir, "api_key");
writeFileSync(keyFile, config.apiKey, { mode: 0o600 });
// Belt-and-suspenders: explicitly chmod in case the umask interfered
// with the mode option (writeFileSync's mode is masked by process.umask).
chmodSync(keyFile, 0o600);
env[providerConfig.apiKeyEnvVar] = keyFile;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Temp key file not cleaned 🐞 Bug ☼ Reliability

configToEnv() writes the API key into a newly created temp directory but provides no cleanup path,
so API keys persist on disk and repeated starts/restarts will accumulate secret-bearing files under
the system temp directory.
Agent Prompt
### Issue description
A temp directory and key file are created for every `configToEnv()` call, but nothing deletes them. This leaves API keys at rest on disk indefinitely and can also create unbounded growth in the temp directory across restarts.

### Issue Context
`configToEnv()` is used by `OpencodeServer.start()` to construct the environment for the spawned `opencode` process. `OpencodeServer.stop()` kills the process but does not remove any temp files.

### Fix Focus Areas
- src/lib/opencode/config.ts[65-90]
- src/lib/opencode/server.ts[29-86]
- src/lib/opencode/server.ts[88-118]

### Suggested fix
- Change `configToEnv()` (or its caller) to return both:
  1) the env object, and
  2) a cleanup function (or list of created paths) that removes the temp directory.
- In `OpencodeServer.start()`, register cleanup on:
  - normal stop (`stop()`), and
  - child process `exit`/`error` handlers.
- Use best-effort removal: `rmSync(dir, { recursive: true, force: true })` (or async equivalent) and ignore errors.
- (Optional hardening) explicitly ensure the temp directory permissions are owner-only before writing the key file.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR modifies the OpenCode configuration helper to change how OpencodeConfig is converted into environment variables for the spawned OpenCode CLI process, with the intent of avoiding placing API keys directly in env vars.

Changes:

  • Added Node.js filesystem/path/os usage to write the API key into a temp file with restrictive permissions.
  • Updated configToEnv to set the provider API key env var to the temp file path instead of the API key string.
  • Expanded the function’s doc comment with security rationale for the change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +7
import { writeFileSync, mkdtempSync, chmodSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
Comment on lines +70 to +74
// Write the API key to a unique temp file with restrictive permissions.
// Using mkdtempSync guarantees an unguessable, exclusive directory name,
// avoiding symlink attacks in the shared /tmp directory.
const dir = mkdtempSync(join(tmpdir(), "codeflow-opencode-"));
const keyFile = join(dir, "api_key");
Comment on lines +55 to +63
* Convert OpencodeConfig to environment variables for OpenCode CLI.
*
* SECURITY: The API key is NEVER placed directly in the environment.
* Environment variables are readable via `/proc/<pid>/environ` on Linux
* by any local user, which would expose the key to local privilege
* escalation. Instead, the key is written to a temp file with mode
* 0600 (readable/writable only by the owner) and the file path is
* passed as the env var value. The child process is expected to read
* the key from the file.
@nehraa

nehraa commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

Closing as superseded. The cleanup commit a896899 removed the entire src/ tree (now reorganized as a pnpm monorepo at packages/). The target file src/lib/opencode/config.ts no longer exists — the env-var API key handling it contained was removed during the cleanup. Only minimal OpencodeProvider / OpencodeServerInfo types remain in packages/codeflow-canvas/src/lib/types.ts and packages/codeflow-agent/src/ai/opencode-client.ts, and the original leak issue no longer applies.

No action needed on this branch.

@nehraa nehraa closed this Jun 11, 2026
@nehraa
nehraa deleted the claude-lane/task_1780281408931_wl61hi99e-20260602145932 branch June 11, 2026 06:03
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.

2 participants