fix(core): add goto variable substitution parity#2054
fix(core): add goto variable substitution parity#2054BABTUNA wants to merge 2 commits intobrowserbase:mainfrom
Conversation
|
|
This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run. |
There was a problem hiding this comment.
1 issue found across 8 files
Confidence score: 2/5
- There is a high-confidence security risk in
packages/core/lib/v3/agent/tools/goto.ts: rawpage.gotoerrors can include resolved URLs after variable substitution, which may expose secret values in error messages. - Because this is a concrete, user-impacting secret-leak path (severity 8/10, confidence 8/10), merge risk is elevated even though only one issue was identified.
- Pay close attention to
packages/core/lib/v3/agent/tools/goto.ts- ensure exceptions are sanitized/redacted so resolved URL variables and secrets are not returned in error text.
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="packages/core/lib/v3/agent/tools/goto.ts">
<violation number="1" location="packages/core/lib/v3/agent/tools/goto.ts:33">
P1: Custom agent: **Exception and error message sanitization**
goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Agent as Agent / LLM
participant Tool as gotoTool
participant Vars as Variable Utility
participant Page as Playwright/Page
participant Cache as AgentCache
Note over Agent, Cache: Live Execution Flow
Agent->>Tool: execute({ url: "https://%env%/home" })
Tool->>Vars: NEW: substituteVariables(url, variables)
Vars-->>Tool: "https://prod.com/home"
Tool->>Page: CHANGED: goto("https://prod.com/home")
Tool->>Cache: CHANGED: recordAgentReplayStep({ url: "https://%env%/home" })
Note right of Tool: Stores original template for portability
Note over Agent, Cache: Replay Execution Flow (AgentCache)
Cache->>Cache: Retrieve cached step
alt step.type == "goto"
Cache->>Vars: NEW: substituteVariables(step.url, variables)
Vars-->>Cache: "https://prod.com/home"
Cache->>Page: CHANGED: goto("https://prod.com/home")
end
Note over Agent, Page: V4 API Additions (Non-Agent)
participant API as V4 Click API
API->>Page: NEW: click(selector, { expectNavigation, expectPopup, expectDownload })
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| const resolvedUrl = substituteVariables(url, variables); | ||
| const page = await v3.context.awaitActivePage(); | ||
| await page.goto(url, { waitUntil: "load" }); | ||
| await page.goto(resolvedUrl, { waitUntil: "load" }); |
There was a problem hiding this comment.
P1: Custom agent: Exception and error message sanitization
goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/lib/v3/agent/tools/goto.ts, line 33:
<comment>goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.</comment>
<file context>
@@ -21,12 +28,14 @@ export const gotoTool = (v3: V3) =>
+ const resolvedUrl = substituteVariables(url, variables);
const page = await v3.context.awaitActivePage();
- await page.goto(url, { waitUntil: "load" });
+ await page.goto(resolvedUrl, { waitUntil: "load" });
v3.recordAgentReplayStep({ type: "goto", url, waitUntil: "load" });
return { success: true, url };
</file context>
why
gotodid not substitute%variableName%tokens in either live execution or AgentCache replay.That created parity drift with
keys(which already supports variable substitution in live + replay) and caused variable-driven navigation steps to replay incorrectly.Closes #2053.
what changed
gototool now resolves%variable%tokens before callingpage.goto(...).gototool replay recording still stores the original tokenized URL.createAgentToolsnow wiresvariablesintogotoTool.AgentCachereplay now resolves%variable%tokens for cachedgotosteps.tests
packages/core/tests/unit/goto-tool-variables.test.tsgotosubstitution + tokenized replay recording.packages/core/tests/unit/cache-llm-resolution.test.tsgotoreplay applies substitutions.validation run
npm.cmd exec prettier -- --writeon touched filesnpm.cmd exec eslint --on touched filesnode node_modules/vitest/vitest.mjs run --config .tmp-vitest-unit-config.mjs(targeting the two updated unit tests)Summary by cubic
Fixes
gotovariable substitution:%var%tokens now resolve in live runs and AgentCache replays, matchingkeysbehavior, and addsexpectNavigation,expectPopup, andexpectDownloadto the v4 click API. Closes #2053.Bug Fixes
gotoresolves%variable%beforepage.goto(...)and during AgentCache replay; replays keep the tokenized URL.createAgentToolsnow passesvariablesintogoto.New Features
POST /v4/page/clickacceptsexpectNavigation,expectPopup, andexpectDownload; OpenAPI and schema updated.Written for commit a24cb0a. Summary will update on new commits. Review in cubic