Skip to content

Add OnBeforeFilterRemovedSourceRecords integration event in Email Impl (#8635)#8771

Open
Groenbech96 wants to merge 1 commit into
microsoft:mainfrom
Groenbech96:fix/8635-email-onbefore-filter-removed-source-records
Open

Add OnBeforeFilterRemovedSourceRecords integration event in Email Impl (#8635)#8771
Groenbech96 wants to merge 1 commit into
microsoft:mainfrom
Groenbech96:fix/8635-email-onbefore-filter-removed-source-records

Conversation

@Groenbech96

@Groenbech96 Groenbech96 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

What & why

Adds an OnBeforeFilterRemovedSourceRecords integration event to the FilterRemovedSourceRecords procedure in codeunit 8900 "Email Impl", published via the public facade codeunit 8901 Email.

FilterRemovedSourceRecords opens a RecordRef on each related source table with no filter applied and calls RecordRef.ReadPermission() to decide whether the related record is shown. As documented, ReadPermission() on an unfiltered RecordRef tests full, unrestricted read permission on the entire table. When a user has a security filter on the source table (e.g. Purchase Header), that check returns false even though the user can read the specific record, so the "Add file from source document" action reports "Did not find any attachments related to this email".

This new OnBefore/IsHandled event lets partners override the default filtering — for example applying SourceRecordRef.SecurityFiltering(SecurityFilter::Ignored) before the permission check — without forking the System Application.

Linked work

Fixes #8635

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome

  • The change is purely additive: a new internal [IntegrationEvent(false, false)] publisher on codeunit Email, raised at the start of FilterRemovedSourceRecords with an IsHandled guard. It mirrors the exact, already-shipping pattern used by the other events in the same #region Events of codeunit Email (e.g. OnShowSource), which are subscribed to elsewhere via Codeunit::Email.
  • No behavior change when no subscriber sets IsHandled — the original filtering loop runs unchanged.
  • No tests added: the event is an extensibility hook with no default behavior change. The existing FilterRemovedSourceRecords coverage remains valid.

Risk & compatibility

Low. Additive integration event only; no signature changes to existing procedures or events, no data/upgrade impact. Default code path is unchanged when the event is not handled.

microsoft#8635)

Adds an OnBefore integration event to the FilterRemovedSourceRecords procedure in codeunit 8900 "Email Impl", published via codeunit 8901 Email. This lets partners override the default filtering (which relies on RecordRef.ReadPermission against an unfiltered RecordRef) so they can, for example, apply SecurityFiltering::Ignored before the permission check. Without this, users with a security filter on a source table get 'Did not find any attachments related to this email' when adding files from the source document.

Fixes microsoft#8635

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Groenbech96 Groenbech96 requested a review from a team June 24, 2026 11:27
@github-actions github-actions Bot added AL: System Application From Fork Pull request is coming from a fork labels Jun 24, 2026
/// <param name="EmailRelatedRecord">The related source records to filter. Subscribers can apply their own filtering, for example to ignore security filtering when determining read permission.</param>
/// <param name="IsHandled">Out parameter to set if the event was handled. If set to true, the default filtering is skipped.</param>
[IntegrationEvent(false, false)]
internal procedure OnBeforeFilterRemovedSourceRecords(var EmailRelatedRecord: Record "Email Related Record"; var IsHandled: Boolean)

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.

$\textbf{🟠\ High\ Severity\ —\ Security} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

OnBeforeFilterRemovedSourceRecords declares 'var IsHandled: Boolean' and the caller does 'if IsHandled then exit', allowing any subscriber in the same app to skip the entire security-filtering loop.

The XML documentation makes the bypass intent explicit: "Subscribers can apply their own filtering, for example to ignore security filtering when determining read permission." This matches the article's anti-pattern exactly: a var Boolean guard parameter on an IntegrationEvent whose name signals a security decision, followed by an unconditional exit that drops the publisher's check. The recommended fix is to restructure so subscribers can only tighten the filter (e.g., an OnAfterFilterRemovedSourceRecords event fired after the default filtering, where subscribers can add additional SetRange calls or call Error to deny access), rather than providing a hook that bypasses the default security filter entirely.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

Copy link
Copy Markdown
Contributor

Copilot PR Review

Iteration 1 · Outcome: completed

Knowledge source: https://github.com/microsoft/BCQuality@822cae1b2771ac25f665f73369f69093bd4fd630

Findings by domain

Findings split into Knowledge-backed (cite a BCQuality article) and Agent (the agent's own judgement, no matching BCQuality rule).

Domain Findings Knowledge-backed Agent Inline Fallback
Security 1 1 0 1 0

Totals: 1 knowledge-backed · 0 agent findings.

Orchestrator pre-filter (13 file(s) excluded)

  • layer-disabled (knowledge) : 13 file(s)

Findings produced by the Copilot CLI agent against BCQuality at 822cae1b2771ac25f665f73369f69093bd4fd630. Reply 👎 on any inline comment to flag false positives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: System Application From Fork Pull request is coming from a fork

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: [W1][Codeunit][8900][Email Impl] Add OnBefore IntegrationEvent in FilterRemovedSourceRecords-procedure

1 participant