Skip to content

Fix unordered server endpoint validation - #4029

Merged
marcschier merged 1 commit into
OPCFoundation:masterfrom
MrAlaskan:fix/session-server-endpoints-set-comparison
Jul 20, 2026
Merged

marcschier merged 1 commit into
OPCFoundation:masterfrom
MrAlaskan:fix/session-server-endpoints-set-comparison

Conversation

@MrAlaskan

Copy link
Copy Markdown
Contributor

Summary

This PR makes Session.ValidateServerEndpoints() compare ServerEndpoints and UserIdentityTokens as unordered sets and adds regression tests that verify OpenAsync() no longer rejects legal servers that return the same endpoint data in a different order.

Problem

According to OPC UA Part 4, the client validates the endpoint set returned by CreateSessionResponse.ServerEndpoints against the endpoint set observed during discovery. The specification describes these values as a set of endpoint descriptions filtered by the relevant transport profile, not as an ordered array that must preserve the exact discovery-time enumeration order.

Previously, Session.ValidateServerEndpoints() first checked the endpoint count and then compared m_discoveryServerEndpoints[ii] against serverEndpoints[ii] by index. It also compared UserIdentityTokens[jj] by index within each endpoint. As a result, a server that returned the same legal endpoints in a different order, or returned the same token policies in a different order within an endpoint, could be rejected with BadSecurityChecksFailed even though the endpoint data itself had not changed.

Changes

  • Replace index-based ServerEndpoints validation with unordered matching based on the same endpoint fields already validated by the client.
  • Compare UserIdentityTokens as an unordered multiset instead of requiring the server to preserve the original token enumeration order.
  • Extend the client session test scaffolding so discovery endpoints can be supplied explicitly.
  • Add regression tests that verify OpenAsync() accepts reordered ServerEndpoints and reordered UserIdentityTokens.

@marcschier marcschier added the ready Ready to merge once CI Passes label Jul 19, 2026
@codecov

codecov Bot commented Jul 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 67.44186% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.54%. Comparing base (84fa8e8) to head (a0241ff).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
src/Opc.Ua.Client/Session/Session.cs 67.44% 9 Missing and 5 partials ⚠️

❌ Your patch check has failed because the patch coverage (67.44%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4029      +/-   ##
==========================================
- Coverage   73.85%   73.54%   -0.32%     
==========================================
  Files        1345     1345              
  Lines      179988   180056      +68     
  Branches    31668    31681      +13     
==========================================
- Hits       132938   132415     -523     
- Misses      36299    36928     +629     
+ Partials    10751    10713      -38     
Files with missing lines Coverage Δ
src/Opc.Ua.Client/Session/Session.cs 72.81% <67.44%> (+0.88%) ⬆️

... and 47 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@marcschier

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@marcschier
marcschier merged commit 8f40876 into OPCFoundation:master Jul 20, 2026
163 of 164 checks passed
marcschier pushed a commit that referenced this pull request Aug 18, 2026
…78] (#4269)

Backport of
8f40876
from `master` to `master378`.

### Summary
Makes `Session.ValidateServerEndpoints()` compare `ServerEndpoints` and
`UserIdentityTokens` as unordered sets and adds regression tests
verifying `OpenAsync()` no longer rejects legal servers that return the
same endpoint data in a different order.

### Problem
Per OPC UA Part 4, the client validates the endpoint set returned by
`CreateSessionResponse.ServerEndpoints` against the set observed during
discovery. The spec describes these as a *set* of endpoint descriptions
filtered by transport profile, not an ordered array. Previously the
validation compared `m_discoveryServerEndpoints[ii]` against
`serverEndpoints[ii]` by index, and `UserIdentityTokens[jj]` by index. A
server returning the same legal endpoints/token policies in a different
order could be wrongly rejected with `BadSecurityChecksFailed`.

### Changes
- Replace index-based `ServerEndpoints` validation with unordered
matching on the same endpoint fields already validated by the client.
- Compare `UserIdentityTokens` as an unordered multiset.
- Extend the client session test scaffolding so discovery endpoints can
be supplied explicitly.
- Add regression tests for reordered `ServerEndpoints` and reordered
`UserIdentityTokens`.

### Notes
Adapted to the `master378` API surface (`EndpointDescriptionCollection`
/ `UserTokenPolicyCollection` / `StringCollection` / `byte[]` server
nonce) and the `Libraries/`/`Tests/` layout. Client tests build and the
new tests pass.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
GoetzGoerisch pushed a commit to umati/connect that referenced this pull request Sep 23, 2026
…5.378.176 (#45)

This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [OPCFoundation.NetStandard.Opc.Ua](https://github.com/OPCFoundation/UA-.NETStandard) | `1.5.378.156` → `1.5.378.176` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/OPCFoundation.NetStandard.Opc.Ua/1.5.378.176?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/OPCFoundation.NetStandard.Opc.Ua/1.5.378.156/1.5.378.176?slim=true) |

---

### Release Notes

<details>
<summary>OPCFoundation/UA-.NETStandard (OPCFoundation.NetStandard.Opc.Ua)</summary>

### [`v1.5.378.176`](https://github.com/OPCFoundation/UA-.NETStandard/releases/tag/1.5.378.176): OPC UA 1.05 Maintenance Update

[Compare Source](OPCFoundation/UA-.NETStandard@1.5.378.156...1.5.378.176)

Maintenance Release for fixing bugs found on the main378 development branch.

#### Released packages

[OPCFoundation.NetStandard.Opc.Ua](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Core](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Security.Certificates](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Configuration](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Server](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Client](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.Bindings.Https](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Bindings.Https/1.5.378.176)
[OPCFoundation.NetStandard.Opc.Ua.PubSub](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.PubSub/1.5.378.176)

#### What's Changed

- Fix publish queue lost wake-up by [@&#8203;marcschier](https://github.com/marcschier) in [#&#8203;4017](OPCFoundation/UA-.NETStandard#4017)
- Obsolete legacy TraceConfiguration in favor of ITelemetryContext by [@&#8203;marcschier](https://github.com/marcschier) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;4090](OPCFoundation/UA-.NETStandard#4090)
- Preserve publish queue timestamp ordering by [@&#8203;marcschier](https://github.com/marcschier) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;4084](OPCFoundation/UA-.NETStandard#4084)
- Fix BadContinuationPointInvalid caused by empty continuation point in Browser.BrowseAsync by [@&#8203;marcschier](https://github.com/marcschier) in [#&#8203;4168](OPCFoundation/UA-.NETStandard#4168)
- Add documentation for custom NodeSet2 authoring workflow by [@&#8203;romanett](https://github.com/romanett) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;4170](OPCFoundation/UA-.NETStandard#4170)
- Fixed timer leaks in ChannelAsyncOperation.EndAsync ([#&#8203;3669](OPCFoundation/UA-.NETStandard#3669)) by [@&#8203;KarenKrill](https://github.com/KarenKrill) in [#&#8203;4166](OPCFoundation/UA-.NETStandard#4166)
- Treat zero MaxNotificationsPerPublish as unlimited (OPC 10000-4) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4263](OPCFoundation/UA-.NETStandard#4263)
- fix(server): enforce browse continuation point limit at capacity ([#&#8203;4036](OPCFoundation/UA-.NETStandard#4036)) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4270](OPCFoundation/UA-.NETStandard#4270)
- Fix unordered server endpoint validation ([#&#8203;4029](OPCFoundation/UA-.NETStandard#4029)) \[backport to master378] by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4269](OPCFoundation/UA-.NETStandard#4269)
- fix: don't return continuation points on BadNoContinuationPoints ([#&#8203;4022](OPCFoundation/UA-.NETStandard#4022)) \[backport to master378] by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4268](OPCFoundation/UA-.NETStandard#4268)
- fix: scope Cancel request matching to the current session ([#&#8203;4023](OPCFoundation/UA-.NETStandard#4023)) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4267](OPCFoundation/UA-.NETStandard#4267)
- Set ContinuationPoint to null when browse is finished (port of [#&#8203;4057](OPCFoundation/UA-.NETStandard#4057)) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4266](OPCFoundation/UA-.NETStandard#4266)
- Default TransportQuotas in ApplicationConfiguration.ValidateAsync to prevent server-start NullReferenceException (backport to master378) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4264](OPCFoundation/UA-.NETStandard#4264)
- Fix ServerTimestamp update on read of stored/static nodes ([#&#8203;4257](OPCFoundation/UA-.NETStandard#4257)) by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4260](OPCFoundation/UA-.NETStandard#4260)
- Fix reverse connect hold time when several Servers share one listener by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4341](OPCFoundation/UA-.NETStandard#4341)
- \[master378] Fix Publish with maximum TimeoutHint by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;4373](OPCFoundation/UA-.NETStandard#4373)
- \[master378] Send the filtered retain trailing event with a client specific Retain = false by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;4454](OPCFoundation/UA-.NETStandard#4454)
- Master378 backport ctt changes by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;4326](OPCFoundation/UA-.NETStandard#4326)
- Update Microsoft.SourceLink.GitHub and  Microsoft.SourceLink.AzureRepos.Git from 10.0.102 to 10.0.111 by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;4465](OPCFoundation/UA-.NETStandard#4465)

**Full Changelog**: <OPCFoundation/UA-.NETStandard@1.5.378.156...1.5.378.176>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC43Ny4wIiwidXBkYXRlZEluVmVyIjoiNDQuNzcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://codeberg.org/umati/connect/pulls/45
Signed-off-by: umati-bot <git-bot@umati.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready Ready to merge once CI Passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants