Skip to content

fix: route signed Harness log blobs through client#199

Draft
cursor[bot] wants to merge 7 commits into
mainfrom
cursor/mcp-v2-bug-resolution-10ff
Draft

fix: route signed Harness log blobs through client#199
cursor[bot] wants to merge 7 commits into
mainfrom
cursor/mcp-v2-bug-resolution-10ff

Conversation

@cursor
Copy link
Copy Markdown
Contributor

@cursor cursor Bot commented May 14, 2026

Description

Fixes log blob download routing for Harness-hosted signed URLs. Links on Harness hosts that include X-Amz-Signature or X-Goog-Signature now route through HarnessClient.requestStream() instead of direct fetch(), preserving proxy/auth routing for self-managed and proxied deployments.

The resolver now direct-fetches only recognized external storage hosts (S3/GCS), preserves signed non-storage path/query values with header-based scoping, normalizes relative blob paths before adding /gateway/log-service, preserves HarnessApiError details, and keeps path-style regional S3 URLs direct-fetchable.

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Other

Checklist

  • Tests pass
  • Typecheck passes
Open in Web View Automation 

cursoragent and others added 6 commits May 14, 2026 16:36
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

  1. Important: relative signed blob links are still rewritten as unsigned paths. The new isSignedBlobUrl check only runs when safeParseUrl(blobLink) succeeds, so links like /some/blob/path?X-Amz-Signature=sig or some/blob/path?... still fall through the unsigned branch. With the real HarnessClient, that becomes .../gateway/log-service/some/blob/path?accountIdentifier=...&routingId=...&accountID=...&X-Amz-Signature=sig, which mutates the signed URL and can recreate the download failure this PR is trying to fix. Detect signed relative links too (for example by parsing with a dummy base or inspecting the raw query string before URL parsing) and add a regression test for that shape.
Open in Web View Automation 

Sent by Cursor Automation: Sunil On Demand Architecture Review

Comment thread src/utils/log-resolver.ts
signal: AbortSignal,
): Promise<Response> {
const blobUrl = safeParseUrl(blobLink);
const isSignedBlobUrl = blobUrl ? isPresignedUrl(blobUrl) : false;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Relative signed links are still misclassified here. safeParseUrl() returns undefined for values like /some/blob/path?X-Amz-Signature=sig, so isSignedBlobUrl becomes false and the code later prepends /gateway/log-service and omits headerBasedScoping. Running that through the real HarnessClient produces a URL like https://<base>/gateway/log-service/some/blob/path?accountIdentifier=...&routingId=...&accountID=...&X-Amz-Signature=sig, which mutates the signed blob URL. Please detect signed relative paths too and add a regression test for that case.

Copy link
Copy Markdown
Contributor Author

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Found 1 important issue before this is architecture-safe to merge:

  1. src/utils/log-resolver.ts: relative signed blob links are still treated as unsigned. The new logic only checks isPresignedUrl() when new URL(blobLink) succeeds, but relative links like some/blob/path?X-Amz-Signature=sig&token=abc do not parse without a base. That means downloadPath is rewritten through /gateway/log-service, and HarnessClient.buildUrl() appends accountIdentifier, routingId, and accountID, mutating the signed query string that this PR is trying to preserve.

Assumption:
I am assuming the log-service can return relative signed links as well as absolute ones. If that invariant is impossible, please document it in code/tests; otherwise this needs a regression test and fix.

Verification:

  • pnpm test tests/utils/log-resolver.test.ts
  • pnpm typecheck
  • pnpm build
  • direct repro after build: some/blob/path?X-Amz-Signature=sig&token=abc became https://app.harness.io/gateway/log-service/some/blob/path?accountIdentifier=acct&routingId=acct&accountID=acct&X-Amz-Signature=sig&token=abc
Open in Web View Automation 

Sent by Cursor Automation: Sunil On Demand Architecture Review

Comment thread src/utils/log-resolver.ts
signal: AbortSignal,
): Promise<Response> {
const blobUrl = safeParseUrl(blobLink);
const isSignedBlobUrl = blobUrl ? isPresignedUrl(blobUrl) : false;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This still misses relative signed links. new URL(blobLink) returns undefined for inputs like some/blob/path?X-Amz-Signature=sig&token=abc, so isSignedBlobUrl becomes false here and the code falls into the /gateway/log-service rewrite below. With the real HarnessClient, that rewritten path then picks up accountIdentifier, routingId, and accountID, which mutates the signed query string and breaks the blob download. Please parse relative links against a dummy base or inspect the raw query string before deciding whether to preserve the path and enable headerBasedScoping.

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