Skip to content

[Server] Fix NRE in ActivateSession if Session times out before activation completes#3844

Merged
romanett merged 3 commits into
master378from
romanett/fixSession
Jun 21, 2026
Merged

[Server] Fix NRE in ActivateSession if Session times out before activation completes#3844
romanett merged 3 commits into
master378from
romanett/fixSession

Conversation

@romanett

@romanett romanett commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Fixes a NullReferenceException (NRE) in StandardServer.ActivateSessionAsync that could occur when a session times out between the completion of SessionManager.ActivateSessionAsync and the subsequent GetSession call. A null-guard (?? throw new ServiceResultException(StatusCodes.BadSessionIdInvalid)) is added to handle this race condition safely.

Related Issues

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which adds functionality)
  • Test enhancement (non-breaking change to increase test coverage)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected, requires version increase of Nuget packages)
  • Documentation Update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc.
  • I have signed the CLA.
  • I ran tests locally with my changes, all passed.
  • I fixed all failing tests in the CI pipelines.
  • I fixed all introduced issues with CodeQL and LGTM.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added necessary documentation (if appropriate).
  • Any dependent changes have been merged and published in downstream modules.

Further comments

The fix is a minimal, targeted change in StandardServer.cs. Earlier attempts to also modify SessionManager.ValidateRequest and Session.ValidateRequest were reverted because removing the ActivateSession bypass from SessionManager.ValidateRequest caused the secure channel ID check in Session.ValidateRequest to run for reconnect-on-alternate-channel scenarios — a valid OPC UA pattern — resulting in BadSecureChannelIdInvalid errors in the Client test suite (ReconnectJWTAsync, ReconnectSessionOnAlternateChannelAsync, etc.).

@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.14%. Comparing base (00519fa) to head (6b1ba92).

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##           master378    #3844      +/-   ##
=============================================
+ Coverage      60.11%   60.14%   +0.03%     
=============================================
  Files            378      378              
  Lines          79060    79061       +1     
  Branches       13837    13838       +1     
=============================================
+ Hits           47526    47552      +26     
+ Misses         27105    27090      -15     
+ Partials        4429     4419      -10     
Files with missing lines Coverage Δ
Libraries/Opc.Ua.Server/Server/StandardServer.cs 70.98% <100.00%> (-0.05%) ⬇️

... and 12 files with indirect coverage changes

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

@romanett

romanett commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@copilot create the same PR based of master branch with merge target master

Copilot AI commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

@romanett I've opened a new pull request, #3845, to work on those changes. Once the pull request is ready, I'll request review from you.

…done

Update ClientLastActiveTIme in activate session
Copilot AI added a commit that referenced this pull request Jun 5, 2026
@romanett

romanett commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Check why the Client Test CI is failing

@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 all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ romanett
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

@copilot Check why the Client Test CI is failing

The Client tests were failing because the SessionManager.cs change removed ActivateSession from the session-lookup bypass, causing session.ValidateRequest() to be called for ActivateSession requests. That method checks IsSecureChannelValid(), which compares the stored channel ID against the incoming channel ID — but OPC UA allows re-activation on a new channel, so reconnect tests like ReconnectJWTAsync and ReconnectSessionOnAlternateChannelAsync all failed with BadSecureChannelIdInvalid.

The actual NRE fix is the null check in StandardServer.cs (GetSession(...) ?? throw new ServiceResultException(StatusCodes.BadSessionIdInvalid)). I've reverted the SessionManager.cs and Session.cs changes so only that null check remains. Fixed in commit $(git rev-parse --short HEAD).

Copilot AI changed the title [Server] Fix NRE in activate Session if Session times out before activate was done & Update ClientLastActiveTIme in activate session [Server] Fix NRE in ActivateSession if Session times out before activation completes Jun 5, 2026
@romanett
romanett marked this pull request as draft June 5, 2026 11:11
@marcschier marcschier added the 1.5.378 Only affects 1.5.378 (pre 2.0) label Jun 9, 2026
marcschier added a commit that referenced this pull request Jun 14, 2026
…annelIdInvalid on reconnect

PR #3844 explicitly warned that removing the ActivateSession bypass from SessionManager.ValidateRequestAsync (and the matching guard in Session.ValidateRequest) causes the secure channel id check in Session.ValidateRequest to run on reactivation, breaking valid OPC UA reconnect-on-alternate-channel scenarios (e.g. ApplicationCertificateRotationRehandshakesOpenManagedChannelsAsync, ReconnectJWTAsync, ReconnectSessionOnAlternateChannelAsync).

Keep only the StandardServer.cs null-guard from #3844, which is the actual race-condition fix.
marcschier added a commit that referenced this pull request Jun 15, 2026
…3846)

# Description

Fixes a null reference exception that occurs when a session expires
between `CreateSession` and `ActivateSession` requests. The issue stems
from a race condition where the server doesn't properly validate session
existence during activation when the session has already timed out.

The fix is a minimal, targeted change in
`StandardServer.ActivateSessionAsync`: a null-coalescing throw ensures
the session exists after lookup, returning `BadSessionIdInvalid` if it
has expired.

Example flow that previously failed:
```csharp
// Session created successfully
var createResp = await client.CreateSessionAsync(...);

// Session expires before activation
await Task.Delay(sessionTimeout);

// Previously: NRE from null session
// Now: BadSessionIdInvalid returned correctly
var activateResp = await client.ActivateSessionAsync(...);
```

## Note on scope

Earlier revisions of this port also modified
`SessionManager.ValidateRequestAsync` (removing `ActivateSession` from
the early-return bypass) and `Session.ValidateRequest` (allowing
`ActivateSession` on non-activated sessions). These changes were
reverted because they cause the secure channel id check in
`Session.ValidateRequest` to run on reactivation, breaking valid OPC UA
reconnect-on-alternate-channel scenarios — the same regression flagged
in the source PR #3844. Symptoms included `BadSecureChannelIdInvalid`
failures in tests such as
`ApplicationCertificateRotationRehandshakesOpenManagedChannelsAsync`,
`ReconnectJWTAsync`, and `ReconnectSessionOnAlternateChannelAsync`.

## Related Issues

Ports the fix from PR #3844 which addressed this issue on the master378
branch.

## Checklist

- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [x] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [x] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [x] I have addressed **all** PR feedback received.

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: Marc Schier <[email protected]>
Co-authored-by: Marc Schier <[email protected]>
@romanett
romanett marked this pull request as ready for review June 21, 2026 09:32
@romanett
romanett merged commit fa9364c into master378 Jun 21, 2026
51 of 92 checks passed
@romanett
romanett deleted the romanett/fixSession branch June 21, 2026 10:43
GoetzGoerisch pushed a commit to umati/connect that referenced this pull request Jul 2, 2026
…5.378.152 (#21)

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.145` → `1.5.378.152` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/OPCFoundation.NetStandard.Opc.Ua/1.5.378.152?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/OPCFoundation.NetStandard.Opc.Ua/1.5.378.145/1.5.378.152?slim=true) |

---

### Release Notes

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

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

[Compare Source](OPCFoundation/UA-.NETStandard@1.5.378.145...1.5.378.152)

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.152)
[OPCFoundation.NetStandard.Opc.Ua.Core](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Security.Certificates](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Configuration](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Server](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Client](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Bindings.Https](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Bindings.Https/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.PubSub](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.PubSub/1.5.378.152)

#### What's Changed

- Fix memory leak: dispose linked CancellationTokenSource in ChannelAsyncOperation.EndAsync by [@&#8203;romanett](https://github.com/romanett) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;3812](OPCFoundation/UA-.NETStandard#3812)
- Fix Race condition in OnPublishComplete by [@&#8203;markuswallen](https://github.com/markuswallen) in [#&#8203;3837](OPCFoundation/UA-.NETStandard#3837)
- \[master378] Use request.SessionId instead of request.Session.Id in the ReportAuditCancelEvent call from CancelRequests. by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3853](OPCFoundation/UA-.NETStandard#3853)
- Prune extra decoded children that should stay on the type definition only. by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3843](OPCFoundation/UA-.NETStandard#3843)
- \[Server] Fix NRE in ActivateSession if Session times out before activation completes by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;3844](OPCFoundation/UA-.NETStandard#3844)
- \[Server] Fix [#&#8203;3896](OPCFoundation/UA-.NETStandard#3896): send full certificate chain when CA is in the issuer store (1.5.x) by [@&#8203;marcschier](https://github.com/marcschier) in [#&#8203;3898](OPCFoundation/UA-.NETStandard#3898)
- Synchronize ConditionState branch collection access by [@&#8203;marcschier](https://github.com/marcschier) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;3895](OPCFoundation/UA-.NETStandard#3895)
- Prepare 1.5.378 maintenence release by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3893](OPCFoundation/UA-.NETStandard#3893)

**Full Changelog**: <OPCFoundation/UA-.NETStandard@1.5.378.145...1.5.378.152>

</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](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI0Mi4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://codeberg.org/umati/connect/pulls/21
GoetzGoerisch pushed a commit to umati/connect that referenced this pull request Jul 2, 2026
…r to 1.5.378.152 (#22)

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.Server](https://github.com/OPCFoundation/UA-.NETStandard) | `1.5.378.145` → `1.5.378.152` | ![age](https://developer.mend.io/api/mc/badges/age/nuget/OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.152?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/nuget/OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.145/1.5.378.152?slim=true) |

---

### Release Notes

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

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

[Compare Source](OPCFoundation/UA-.NETStandard@1.5.378.145...1.5.378.152)

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.152)
[OPCFoundation.NetStandard.Opc.Ua.Core](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Security.Certificates](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Configuration](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Server](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Client](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.Bindings.Https](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.Bindings.Https/1.5.378.152)
[OPCFoundation.NetStandard.Opc.Ua.PubSub](https://www.nuget.org/packages/OPCFoundation.NetStandard.Opc.Ua.PubSub/1.5.378.152)

#### What's Changed

- Fix memory leak: dispose linked CancellationTokenSource in ChannelAsyncOperation.EndAsync by [@&#8203;romanett](https://github.com/romanett) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;3812](OPCFoundation/UA-.NETStandard#3812)
- Fix Race condition in OnPublishComplete by [@&#8203;markuswallen](https://github.com/markuswallen) in [#&#8203;3837](OPCFoundation/UA-.NETStandard#3837)
- \[master378] Use request.SessionId instead of request.Session.Id in the ReportAuditCancelEvent call from CancelRequests. by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3853](OPCFoundation/UA-.NETStandard#3853)
- Prune extra decoded children that should stay on the type definition only. by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3843](OPCFoundation/UA-.NETStandard#3843)
- \[Server] Fix NRE in ActivateSession if Session times out before activation completes by [@&#8203;romanett](https://github.com/romanett) in [#&#8203;3844](OPCFoundation/UA-.NETStandard#3844)
- \[Server] Fix [#&#8203;3896](OPCFoundation/UA-.NETStandard#3896): send full certificate chain when CA is in the issuer store (1.5.x) by [@&#8203;marcschier](https://github.com/marcschier) in [#&#8203;3898](OPCFoundation/UA-.NETStandard#3898)
- Synchronize ConditionState branch collection access by [@&#8203;marcschier](https://github.com/marcschier) with [@&#8203;Copilot](https://github.com/Copilot) in [#&#8203;3895](OPCFoundation/UA-.NETStandard#3895)
- Prepare 1.5.378 maintenence release by [@&#8203;mrsuciu](https://github.com/mrsuciu) in [#&#8203;3893](OPCFoundation/UA-.NETStandard#3893)

**Full Changelog**: <OPCFoundation/UA-.NETStandard@1.5.378.145...1.5.378.152>

</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](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDIuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI0OS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://codeberg.org/umati/connect/pulls/22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.5.378 Only affects 1.5.378 (pre 2.0)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants