Skip to content

fix: resolve repeated input references and user-file destination collisions - #220

Open
jacksonriding wants to merge 2 commits into
LibreChat-AI:mainfrom
jacksonriding:fix/deduplicate-authorized-inputs
Open

jacksonriding wants to merge 2 commits into
LibreChat-AI:mainfrom
jacksonriding:fix/deduplicate-authorized-inputs

Conversation

@jacksonriding

@jacksonriding jacksonriding commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Repeated input references and different user-file versions at the same destination can reject an entire execution. Authorize every reference, coalesce exact (storage_session_id, id, name) repeats, then select the last distinct user reference per path in request order. Distinct aliases remain available; skill/agent conflicts retain sandbox validation.

Validation: service build passed; 1,047 tests passed, 11 skipped, 0 failed. The new version-selection regression fails on the previous implementation. Existing typecheck diagnostics are unchanged. The squashed commit preserves the tested implementation and tests; subsequent edits only remove README text and shorten comments.

@jacksonriding
jacksonriding force-pushed the fix/deduplicate-authorized-inputs branch from b0da3e0 to 85d579f Compare September 16, 2026 04:21
@danny-avila

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85d579f543

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread service/src/service/file-authorization.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-16T05:16:47.233128Z 85d579f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jacksonriding jacksonriding changed the title fix: deduplicate authorized references to stored input objects fix: deduplicate repeated input destinations after authorization Sep 16, 2026
@jacksonriding jacksonriding changed the title fix: deduplicate repeated input destinations after authorization fix: resolve repeated input references and user-file destination collisions Sep 16, 2026
@jacksonriding
jacksonriding force-pushed the fix/deduplicate-authorized-inputs branch from 2a23da9 to 263c24c Compare September 16, 2026 21:37

@lia-by-librechat lia-by-librechat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed at 263c24c0649131332a2ade94b65a1db6640d0ddd. The core of this is right, and the two ordering decisions I checked hardest both hold up:

  • Authorization runs over every reference before coalescing, so a superseded or echoed reference cannot smuggle an unauthorized scope through. authorizes superseded user refs before selecting a destination and still rejects an unauthorized scope on a duplicate object pin that, and the loop above is untouched.
  • selectedUserFiles.get(file.name) === file is object identity over uniqueReferences, whose elements are the fresh objects validateRequestedFiles builds per input. Exact echoes are already gone by then, so an earlier echo cannot displace a later replacement. kind is validated against KNOWN_KINDS before this point, so file.kind === 'user' has no undefined-means-user hole, and validateFileRefName forces canonical relative paths, which makes raw string equality on name a sound proxy for the destination.

One finding, one note.

The workspace input-file cap still counts the repeats this PR removes

handleReplayInitial rejects on the raw request array, at service/src/service/programmatic-router.ts:512:

if (workspaceId != null && Array.isArray(files) && files.length > BRIDGE_WORKSPACE_PROGRAMMATIC_MAX_INPUT_FILES) {
  throw new Error(`Selected-workspace execution allows at most ${...} input files; ...`);
}

authorizeRequestedFiles does not run until line 591, so for selected-workspace execution the cap is measured before anything is coalesced. BRIDGE_WORKSPACE_PROGRAMMATIC_MAX_INPUT_FILES is 98 (packages/code/src/protocol.ts:26), so a request carrying 99 references that coalesce to, say, 40 distinct destinations is still rejected outright.

That is the same failure this PR sets out to remove, on the path the BYOM coding work depends on, so it seems in scope rather than a follow-up. Counting the cap against the authorized-and-coalesced list would need the cap check to move below line 591, which also changes which error wins when a request is both oversized and unauthorized. If you would rather keep the early rejection, deduplicating the count in place would do:

const distinct = new Set(files.map(f => `${f.storage_session_id}\0${f.id}\0${f.name}`)).size;

Either way a regression test at the boundary would be worth having, since nothing currently fails if the two limits drift apart.

Note: handleBlocking has no equivalent cap

The other callsite (line 1631) has no input-file ceiling, and router.ts:246 assigns the coalesced list straight back onto body.files. Both are consistent with this change; recording it only because it means the cap gap above is specific to the replay/workspace path and not a general pattern.

Nothing else in the diff concerns me. With the cap ordering addressed, this looks good to merge.

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