Repository navigation
Fix dspace-customers 1083 V4: bind vocabulary node id as an XPath variable - #1556
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
A moderate active finding remains because the security-sensitive getParentChoice path lacks regression coverage for valid nested parent resolution and rejection of an injected child ID.
1 open issue
What changed in this PR
This pull request fixes XPath injection in controlled-vocabulary node lookups by binding request-provided IDs as XPath variables instead of interpolating them into expressions.
Changes:
- Replaces interpolated node-ID predicates with the
$nodeIdXPath variable. - Adds shared XPath variable-resolver handling, including safe handling of
nullIDs. - Adds regression coverage for valid and injected IDs in choice and child lookups.
- Adds a moderate test-coverage follow-up:
getParentChoiceshould be tested with both valid and injected child IDs using a nested vocabulary fixture.
| File | Summary |
|---|---|
dspace-api/src/test/java/org/dspace/content/authority/DSpaceControlledVocabularyTest.java |
Adds regression coverage confirming that valid IDs resolve and XPath-injection payloads do not select unintended entries. Parent lookup coverage remains incomplete. |
dspace-api/src/main/java/org/dspace/content/authority/DSpaceControlledVocabulary.java |
Binds node IDs through an XPath variable resolver for node, parent, and child lookups. |
Review effort: Lite
(cherry picked from commit ceab952) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit aa419b9) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers the upstream DURACOM-447 change in getChoice, getChoicesByParent and getParentChoice. A 'pond' node under 's40' gives the parent and children lookups a real target. dspace-customers issue 1083, finding V4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milanmajchrak
force-pushed
the
fix/v4-vocabulary-xpath-entryid
branch
from
October 28, 2026 13:27
76d5415 to
b8b3e8d
Compare
Kasinhou
pushed a commit
that referenced
this pull request
Oct 29, 2026
Resolve overlap with #1556 (XPath variable-binding already landed on dtq-dev): take the dtq-dev implementation of DSpaceControlledVocabulary and keep this branch's CSV metadata.hide / formula-injection hardening. farm.xml keeps both the nested s40>pond fixture and the o'reilly node so the combined test suite passes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


References
dspace-customers issue 1083, finding V4.
Two upstream commits, cherry-picked:
ceab9526c4: DSpace PR 11075 ported todspace-7_x(label search).aa419b904f: DURACOM-447, part of DSpace PR 11964. It is only onmain, not indspace-7_xordspace-9_x.Description
DSpaceControlledVocabularyput the node id from the request straight into an XPath expression, so a'in the id could change the query. This PR cherry-picks the two upstream commits that pass the id and the search text as XPath variables instead.Instructions for Reviewers
List of changes in this PR:
ceab9526c4, clean cherry-pick.getMatchesandgetBestMatchbind the search text as XPath variables. The quoted id template is renamed toidTemplateQuoted.aa419b904f, cherry-pick.getChoice,getChoicesByParentandgetParentChoicebind the id as$nodeId. Only context lines differ from upstream (init()instead ofinit(locale)). Every changed line is the same.testNodeIdIsNotEvaluatedAsXPath. The testfarm.xmlgets apondnode unders40, so the parent and children lookups have a real target.After this PR the class matches upstream
dspace-7_xexcept for two things: DURACOM-447 (not in 7_x yet) and the accented-letter label search from 7_x (a feature, not included).Like upstream,
getLabel(null)now throws. The only production caller, discovery indexing, checks that the authority is set first.How to test:
mvn -pl dspace-api test -DskipUnitTests=false -Dtest=DSpaceControlledVocabularyTest -DfailIfNoTests=false -Dsurefire.failIfNoSpecifiedTests=falseAI Disclosure (REQUIRED)
Were AI tools used in the creation of this PR?
Claude Code cherry-picked the upstream commits, resolved the context conflicts and adapted the test. The changed lines were compared with the upstream commits line by line.
DSpaceControlledVocabularyTestpasses locally (2/2), and the new test fails when the DURACOM-447 commit is left out.Checklist
mainbranch of code (unless it is a backport or is fixing an issue specific to an older branch).pom.xml), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.🤖 Generated with Claude Code