Skip to content

fix(env): shell-quote values written to env.sh to prevent injection#40

Open
hobostay wants to merge 1 commit into
Tencent:mainfrom
hobostay:fix/env-sh-shell-quoting
Open

fix(env): shell-quote values written to env.sh to prevent injection#40
hobostay wants to merge 1 commit into
Tencent:mainfrom
hobostay:fix/env-sh-shell-quoting

Conversation

@hobostay

Copy link
Copy Markdown

Summary

EnvHandler.generateEnvFile writes ~/.teamai/env.sh with export KEY="VALUE" lines and no escaping of the value. This file is sourced from every team member's shell profile (see pullItemgenerateShellBlock / injectShellProfile), and the values originate from the team repo's env/env.yaml. A value that contains ", $, a backtick, or \ will either break the sourced script or run injected commands.

Problem

src/resources/env.ts:

generateEnvFile(variables: EnvVariable[]): string {
  const lines = variables.map(v => `export ${v.key}="${v.value}"`);
  return lines.join('\n') + '\n';
}

Concrete example — a value x"; echo PWNED # produces:

export INJECT="x"; echo PWNED #"

When any member runs teamai pull and later opens a shell, sourcing env.sh executes echo PWNED. Less maliciously, a perfectly normal value containing $ (e.g. a connection string) gets variable-expanded, and a value containing " truncates the line and yields a broken/unclosed quote that errors on source.

Fix

Single-quote each value so shell metacharacters are taken literally, encoding an embedded single quote as the standard '\'' sequence (works in bash/zsh/sh):

function shellQuoteValue(value: string): string {
  return `'${value.replace(/'/g, "'\\''")}'`;
}

generateEnvFile(variables: EnvVariable[]): string {
  const lines = variables.map(v => `export ${v.key}=${shellQuoteValue(v.value)}`);
  return lines.join('\n') + '\n';
}

Verified end-to-end — sourcing the generated file stores every value literally with no injection:

CONN=[a"b$c]
GREETING=[it's a test]
INJECT=[x"; echo PWNED #]
OK: no injection, all metacharacters stored literally

Tests

  • Updated the existing generateEnvFile / pullItem assertions to the single-quote output format.
  • Added a regression test (should shell-quote values containing shell metacharacters) covering ", $, and an embedded single quote.
  • npm test → 1436 passed | 4 skipped; tsc --noEmit → clean.

Notes

  • Only the value is quoted; keys are env-var names from env.yaml and are left as-is (unchanged behavior).
  • The separate ~/.teamai/env KEY=VALUE backup file (loadEnvFile compatibility) is a different code path and intentionally untouched.

generateEnvFile built `export KEY="VALUE"` with no escaping. env.sh is
sourced from every team member's shell profile, and its values come from
the team repo's env/env.yaml — so a value containing `"`, `$`, a backtick,
or `\` either breaks the sourced script or runs injected commands.

Example: value `x"; echo PWNED #` produced
  export INJECT="x"; echo PWNED #"
which executes `echo PWNED` on source.

Single-quote each value (encoding embedded single quotes as `'\''`) so all
metacharacters are taken literally. Added a regression test covering quotes,
`$`, and embedded single quotes; updated existing assertions to the new
format. `npm test` (1436 tests) and `tsc --noEmit` pass.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

1 participant