Skip to content

Fix replay issues - #14

Merged
amrelsagaei merged 14 commits into
mainfrom
ae-replay-sdk
Jun 24, 2026
Merged

Fix replay issues#14
amrelsagaei merged 14 commits into
mainfrom
ae-replay-sdk

Conversation

@amrelsagaei

@amrelsagaei amrelsagaei commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

This PR fixes:

  • send to replay from the attacker tab
  • View mode graphql detection and draft requests.
  • Enhances the view mode ui

Summary by CodeRabbit

  • Chores
    • Updated Caido configuration to 1.0.5 and aligned frontend/backend SDK versions to 0.57.x.
    • Raised the README minimum supported Caido version to v0.57.0.
    • Centralized the GraphQL introspection query in shared code.
  • Bug Fixes
    • Improved replay creation by validating inputs and using the target URL for session setup and naming.
    • Refreshed GraphQL request detection and the GraphQL view experience, including persisted query handling.
  • Tests
    • Added unit tests for GraphQL HTTP parsing and request classification.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@amrelsagaei, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 21 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2767eac8-7b32-45e8-8e86-a277109c715a

📥 Commits

Reviewing files that changed from the base of the PR and between a089372 and 0883514.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/frontend/package.json
  • packages/frontend/src/components/common/CodeEditor.vue
  • packages/frontend/src/components/common/graphqlHighlight.ts
📝 Walkthrough

Walkthrough

This PR adds shared GraphQL parsing utilities, refactors replay creation to use target URLs and direct replay SDK calls, rebuilds GraphQL view-mode parsing and editing, updates view-mode registration, and pins config and package versions.

Changes

GraphQL parsing, replay, and UI flow

Layer / File(s) Summary
GraphQL parsing utilities
packages/frontend/src/utils/graphql.ts, packages/frontend/src/utils/graphql.test.ts
Exports updated HTTP and GraphQL types, parses raw HTTP with HttpForge, detects GraphQL text with heuristics, validates JSON payloads with zod, and tests request detection, operation extraction, and raw HTTP parsing.
Replay service and shared introspection
packages/shared/src/index.ts, packages/backend/src/services/graphql/client.ts, packages/frontend/src/services/replay.ts, packages/frontend/src/components/attacks/Container.vue
Moves INTROSPECTION_QUERY into shared, updates the backend client import, refactors replay creation around targetUrl parsing and direct sdk.replay calls, and updates the Container caller to pass targetUrl and handle the result.
Request view-mode registration
packages/frontend/src/index.ts
Imports shared GraphQL request detection and registers the GraphQL view mode directly on the supported SDK surfaces with a marked raw component.
GraphQLViewMode parsing and editing
packages/frontend/src/views/GraphQLViewMode.vue
Updates component props, parsing, initialization, reconstruction, debounced editing, and the tabbed UI to use the new GraphQL and HTTP helpers.

Configuration and version updates

Layer / File(s) Summary
Config, manifests, and README
caido.config.ts, packages/backend/package.json, packages/frontend/package.json, README.md
Bumps the Caido config version, reformats config strings and arrays, updates the README minimum version, pins SDK package versions, and adds frontend runtime dependencies.

Sequence Diagram(s)

sequenceDiagram
  participant Container as Container.vue
  participant Service as GraphQLReplayService
  participant ReplaySDK as sdk.replay

  Container->>Service: createReplayFromRequest(rawRequest, targetUrl)
  Service->>Service: parseConnection(targetUrl)
  Service->>ReplaySDK: getCollections()
  Service->>ReplaySDK: createCollection() or reuse existing
  Service->>ReplaySDK: createSession({ raw, connectionInfo })
  Service->>ReplaySDK: renameSession()
  Service-->>Container: Result
Loading
sequenceDiagram
  participant View as GraphQLViewMode.vue
  participant Parser as parseHttpMessage / extractGraphQLOperation
  participant HttpForge as HttpForge
  participant Editor as CodeMirror

  View->>Parser: parse raw request
  Parser-->>View: HTTP + GraphQL data
  View->>View: initializeData()
  View->>HttpForge: reconstruct raw request
  View->>Editor: dispatch updated content
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • f8thl3ss

Poem

🐇 I hop through queries, raw and bright,
With tabs and helpers set just right.
Replay flows and GraphQL gleam,
In neat little paths, like a rabbit dream.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and directly reflects the replay-related fixes that make up a major part of the change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ae-replay-sdk

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/frontend/src/services/replay.ts`:
- Around line 13-22: The parseConnection function currently accepts any valid
URL including non-HTTP schemes like request: or mailto: which produce empty
hostnames, allowing invalid targets through. After calling URL.canParse and
creating the url object, add validation to ensure the url.protocol is either
http: or https: (exact match), and verify that url.hostname is not empty. Return
undefined if either validation fails, so only legitimate HTTP/HTTPS targets with
valid hostnames are accepted and processed into the ConnectionInfo object.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df1e360c-3996-47f2-a35c-d8f24ba6a380

📥 Commits

Reviewing files that changed from the base of the PR and between 173477e and 4386b99.

📒 Files selected for processing (3)
  • caido.config.ts
  • packages/frontend/src/components/attacks/Container.vue
  • packages/frontend/src/services/replay.ts

Comment thread packages/frontend/src/services/replay.ts
@socket-security

socket-security Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​caido/​sdk-frontend@​0.57.1-beta.6781008599100
Addedts-http-forge@​0.1.7781009692100
Added@​caido/​sdk-backend@​0.57.0100100100100100

View full report

@socket-security

socket-security Bot commented Jun 23, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm json-schema is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/@caido/sdk-frontend@0.57.1-beta.6npm/json-schema@0.4.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/json-schema@0.4.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@amrelsagaei
amrelsagaei requested a review from f8thl3ss June 23, 2026 17:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/frontend/src/utils/graphql.test.ts (1)

45-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression test for persistedQuery without sha256Hash.

Please add a negative case where extensions.persistedQuery exists but lacks a valid hash, and assert it is not treated as GraphQL. This will lock behavior for the parser guard.

Suggested test additions
 describe("isGraphQLRequest", () => {
+  it("rejects persistedQuery payloads without a sha256Hash", () => {
+    const body = JSON.stringify({
+      extensions: { persistedQuery: { version: 1 } },
+    });
+    expect(isGraphQLRequest(rawRequest("POST", body))).toBe(false);
+  });
 describe("extractGraphQLOperation", () => {
+  it("returns undefined when persistedQuery exists without a valid hash", () => {
+    const op = extractGraphQLOperation(
+      JSON.stringify({ extensions: { persistedQuery: {} } }),
+    );
+    expect(op).toBeUndefined();
+  });

Also applies to: 91-102

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/utils/graphql.test.ts` around lines 45 - 52, Add a new
regression test case after the existing persisted query test to handle the
negative scenario where extensions.persistedQuery exists but lacks the
sha256Hash field. Create a test that constructs a request body with
operationName, variables, and extensions.persistedQuery (but without the
sha256Hash property), then call isGraphQLRequest with rawRequest and assert it
returns false. This ensures the parser correctly rejects incomplete persisted
query structures.
packages/frontend/src/views/GraphQLViewMode.vue (1)

377-377: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

HTTP version is hardcoded to HTTP/1.1 on reconstruction.

parseHttpMessage only preserves the method, so the rebuilt request line forces HTTP/1.1 regardless of the original (e.g., HTTP/2) request line. For replay flows this is usually acceptable, but consider preserving the original version/request-line if downstream tooling relies on it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/frontend/src/views/GraphQLViewMode.vue` at line 377, The headerLines
array construction in GraphQLViewMode.vue hardcodes HTTP/1.1 in the request
line, ignoring the original HTTP version from the parsed request. Modify the
headerLines assignment to extract and preserve the original HTTP version from
the parsed message (accessed via the parsed object) instead of hardcoding
HTTP/1.1, so that if the original request was HTTP/2 or another version, it will
be reconstructed with the same version string. This ensures downstream tooling
receives requests with the correct HTTP version that matches the original.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/frontend/src/utils/graphql.ts`:
- Around line 82-86: The condition checking `persistedQuery !== undefined` in
the query validation logic is too permissive and allows empty objects to pass as
valid, potentially causing false GraphQL positives. Instead of only checking
that persistedQuery is not undefined, add validation to ensure it contains a
valid hash value or other required properties. Modify the condition to check not
just for existence of persistedQuery but also verify that it has actual content
before marking the request as a valid GraphQLOperation.

In `@packages/frontend/src/views/GraphQLViewMode.vue`:
- Around line 141-148: The watch with immediate: true on getRawData is executing
synchronously during setup and calling initializeData(), which in turn calls
validateQuery() before validateQuery is declared later in the file, causing a
temporal dead zone error. Move the validateQuery function declaration (and any
other functions or helpers that initializeData depends on) to occur before the
watch definition, then remove the original validateQuery declaration that
appears later in the file. This ensures all dependencies are available when the
immediate watch callback executes.
- Around line 65-67: The isActuallyGraphQL computed property performs an exact
string match on parsedHttp.value?.method === "POST", which fails for HTTP
methods with lowercase values like "post" or "Post". The registration predicate
isGraphQLRequest normalizes the method using toUpperCase(), allowing lowercase
methods to pass registration but then failing this check, causing a mismatch.
Fix this by normalizing the method comparison in isActuallyGraphQL to use
parsedHttp.value?.method?.toUpperCase() === "POST" to ensure consistency with
how isGraphQLRequest validates the method.

---

Nitpick comments:
In `@packages/frontend/src/utils/graphql.test.ts`:
- Around line 45-52: Add a new regression test case after the existing persisted
query test to handle the negative scenario where extensions.persistedQuery
exists but lacks the sha256Hash field. Create a test that constructs a request
body with operationName, variables, and extensions.persistedQuery (but without
the sha256Hash property), then call isGraphQLRequest with rawRequest and assert
it returns false. This ensures the parser correctly rejects incomplete persisted
query structures.

In `@packages/frontend/src/views/GraphQLViewMode.vue`:
- Line 377: The headerLines array construction in GraphQLViewMode.vue hardcodes
HTTP/1.1 in the request line, ignoring the original HTTP version from the parsed
request. Modify the headerLines assignment to extract and preserve the original
HTTP version from the parsed message (accessed via the parsed object) instead of
hardcoding HTTP/1.1, so that if the original request was HTTP/2 or another
version, it will be reconstructed with the same version string. This ensures
downstream tooling receives requests with the correct HTTP version that matches
the original.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 011fa418-f0d1-44f0-815d-52b40d9fe25f

📥 Commits

Reviewing files that changed from the base of the PR and between 4386b99 and 983d69a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • README.md
  • packages/backend/package.json
  • packages/frontend/package.json
  • packages/frontend/src/index.ts
  • packages/frontend/src/services/replay.ts
  • packages/frontend/src/utils/graphql.test.ts
  • packages/frontend/src/utils/graphql.ts
  • packages/frontend/src/views/GraphQLViewMode.vue
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/frontend/src/services/replay.ts

Comment thread packages/frontend/src/utils/graphql.ts Outdated
Comment thread packages/frontend/src/views/GraphQLViewMode.vue
Comment thread packages/frontend/src/views/GraphQLViewMode.vue
@bebiksior
bebiksior self-requested a review June 23, 2026 22:16
Comment thread packages/frontend/src/utils/graphql.ts
Comment thread packages/frontend/src/utils/graphql.ts
…-query

add introspection query in view mode
coderabbitai[bot]

This comment was marked as off-topic.

@amrelsagaei
amrelsagaei requested a review from bebiksior June 24, 2026 12:18
@amrelsagaei
amrelsagaei merged commit b1aebdc into main Jun 24, 2026
4 checks passed
@amrelsagaei
amrelsagaei deleted the ae-replay-sdk branch June 24, 2026 16:12
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