Skip to content

PC-5090: don't let a packaged .env override job-injected env vars - #1965

Draft
al3xanndru wants to merge 1 commit into
mainfrom
wabbit-dri/PC-5090_1
Draft

al3xanndru wants to merge 1 commit into
mainfrom
wabbit-dri/PC-5090_1

Conversation

@al3xanndru

@al3xanndru al3xanndru commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

PC-5090: the uipath CLI loads <cwd>/.env with
load_dotenv(..., override=True) (packages/uipath/src/uipath/_cli/__init__.py,
load_environment_variables). When a coded package ships a developer's content/.env, that file
replaces the identity Serverless/the robot injects for the job (UIPATH_URL,
UIPATH_ACCESS_TOKEN, …).

Seen on EU staging (DRI triages SRE-669104, SRE-673154, SRE-673289, SRE-674307, SRE-679241,
SRE-688965): Invoice.processing.Agent.update-invoice-status (1.0.0 / 1.0.2 / 1.0.14) in 4 tenants
across 2 orgs ships a .env. The job's environment had the right
UIPATH_URL=https://staging.uipath.com/<job-org>/<job-tenant>, but every SDK call went to
staging.uipath.com/invoiceprocessing/{dennis,WilcoAP,E2ePR618R} with a developer JWT that had
expired in June. The result was elements_ 401/404 and llmopstenant_ 401. These processes have never
succeeded (one has 14,222 faults since 2026-06-30). The error looks like a wrong-tenant 404/401, not
like a configuration problem. With a live token, the job would have authenticated in another
organization as that developer.

Root cause

override=True is right on a developer machine: after uipath auth rewrites .env, it wins over
stale values exported in the shell. In a job it is wrong. The platform-injected environment is the
source of truth there, and the .env comes from whoever built the package.

Change

  • load_environment_variables() checks UIPATH_JOB_KEY in the process environment before it reads
    the .env. The robot and Serverless set that variable for every job.
    • In a job: it calls load_dotenv(override=False). Injected variables win, and .env keys the
      job did not inject still load, so package settings like MY_SETTING keep working.
    • Outside a job: nothing changes (override=True).
  • In a job, if the .env sets a key to a value that differs from the injected one, the CLI logs one
    warning (logger uipath._cli, to stderr). The warning names the keys but not the values, so
    no token reaches the job logs: Ignoring 2 values in /…/.env that differ from the job's environment: UIPATH_ACCESS_TOKEN, UIPATH_URL. Remove the .env from the package.
  • The uipath version goes from 2.14.44 to 2.14.45 (pyproject.toml and uv.lock).

The job check uses the environment as it was before the .env loads. A UIPATH_JOB_KEY written
into a .env (for example for remote debugging) therefore does not switch a local run into job
mode.

Tests

New file: packages/uipath/tests/cli/test_load_environment_variables.py.

Test What it checks
local run the .env still overrides the shell
job with conflicting .env injected UIPATH_URL and token are kept; non-conflicting .env keys still load; one warning lists the keys and contains no values
job, .env agrees no warning, and missing keys are still filled
job, no .env no warning, environment unchanged

Results:

  • pytest tests/cli (packages/uipath): 1535 passed, 1 xfailed (pre-existing, unrelated marker in test_server_job_core.py); the 4 new tests pass alone and in the suite
  • ruff check ., ruff format --check ., mypy on the changed files: all clean (All checks passed!, 345 files already formatted, mypy no issues found, scripts/lint_httpx_client.py no violations)

Risks and open questions

  • A job that relied on its packaged .env to replace an injected variable will now get the
    platform value. That is the intent of this change. Anyone who really needs a different value
    should set it through the process/job environment variables, not a packaged .env.
  • uipath server (pooled mode): the .env is read once at import time, from the server's
    working directory. This PR does not change that path.
  • Follow-up, not in this PR: refuse or warn at uipath pack time when .env or
    .uipath/.auth.json would be packaged. The triage tracks that separately (PC-5091).

Drafted by the wabbit-dri draft-fixes loop for PC-5090 (draft #1), for a human to review: not ready to merge as is.

🤖 Generated with Claude Code

In a robot/Serverless job (UIPATH_JOB_KEY set), load the project .env with
override=False so a .env shipped in the package cannot replace the injected
UIPATH_URL / access token, and warn naming the conflicting keys. Local runs
keep override=True.
@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-runtime test:uipath-integrations labels Oct 30, 2026
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

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

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-runtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant