Skip to content

Add delegated signal handling support#932

Merged
sharvilshah merged 5 commits into
mainfrom
sbs/snt-404
May 4, 2026
Merged

Add delegated signal handling support#932
sharvilshah merged 5 commits into
mainfrom
sbs/snt-404

Conversation

@sharvilshah

@sharvilshah sharvilshah commented May 1, 2026

Copy link
Copy Markdown
Contributor

Fixes SNT-404

@sharvilshah sharvilshah requested a review from a team as a code owner May 1, 2026 15:54
@sharvilshah sharvilshah added this to the 2026.4 milestone May 1, 2026
@github-actions github-actions Bot added configurator Issues or PRs related to the configurator / Santa configuration comp/santad Issues or PRs related to the daemon lang/objc++ PRs modifying files in ObjC++ comp/common size/m Size: medium labels May 1, 2026
@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a boolean AllowDelegatedSignals configuration, exposes it via SNTConfigurator, threads it into Santad and the tamper-resistance client, updates AUTH_SIGNAL handling to validate launchd‑delegated signals (macOS 15.5+ instigator semantics), extends tests, and adds a macOS 15.5 compile guard.

Changes

AllowDelegatedSignals + AUTH_SIGNAL validation

Layer / File(s) Summary
Config Schema / Platform guard
docs/src/lib/santaconfig.ts, Source/common/Platform.h
Adds AllowDelegatedSignals boolean config entry (default false, not sync-configurable). Adds conditional HAVE_MACOS_15_5 macro definition/undefinition for SDK detection.
Configurator API / Data shape
Source/common/SNTConfigurator.h, Source/common/SNTConfigurator.mm
Adds readonly allowDelegatedSignals property, registers KVO dependency, and implements getter backed by AllowDelegatedSignals numeric config key (defaults to NO).
Tamper‑Resistance Surface
Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.h
Adds atomic allowDelegatedSignals property and updates initializer signature to accept the flag.
Tamper‑Resistance Core Logic
Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.mm
AUTH_SIGNAL handler: disables caching for signals, ignores signals not targeting current process and non-launchd senders, and (macOS 15.5+/ES v9 with instigator) authorizes only if instigator signing-id is in compile-time allowlist or instigator is a platform binary and allowDelegatedSignals is set; otherwise deny and log. Stores the new flag from initializer.
Santad Wiring / Runtime update
Source/santad/Santad.mm
Passes configurator value into tamper client at startup and adds KVO observer to call setAllowDelegatedSignals on updates.
Tests
Source/common/SNTConfiguratorTest.mm, Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm
Adds configurator tests for default and runtime updates of allowDelegatedSignals. Updates tamper tests to pass allowDelegatedSignals and adds macOS 15.5+ AUTH_SIGNAL instigator scenarios, plus assertions for cachability and expected auth outcomes.

Sequence Diagram(s)

sequenceDiagram
    participant Config as SNTConfigurator
    participant Santad as Santad
    participant Handler as SNTEndpointSecurityTamperResistance
    participant ES as EndpointSecurity
    participant LaunchD as launchd
    participant Inst as Instigator

    Config->>Santad: provide allowDelegatedSignals
    Santad->>Handler: init(..., allowDelegatedSignals)
    Handler->>Handler: store flag

    LaunchD->>ES: delegate signal for target
    ES->>Handler: AUTH_SIGNAL (may include instigator v9+)

    alt targetPid != getpid()
        Handler-->>ES: DENY
    else sourcePid != 1
        Handler-->>ES: DENY
    else macOS 15.5+ and instigator present
        Handler->>Handler: check instigator signing-id against allowlist
        alt signing-id trusted
            Handler-->>ES: ALLOW
        else instigator is platform binary and allowDelegatedSignals==YES
            Handler-->>ES: ALLOW
        else
            Handler-->>ES: DENY
        end
    else older macOS or no instigator
        Handler-->>ES: DENY
    end

    Config->>Santad: KVO notify on change
    Santad->>Handler: setAllowDelegatedSignals(BOOL)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add delegated signal handling support' accurately and concisely describes the main change in the changeset, which introduces new delegated signal handling functionality across multiple files.
Description check ✅ Passed The description 'Fixes SNT-404' is related to the changeset as it references a ticket/issue number, though it provides minimal detail about the actual changes being made.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sbs/snt-404

Review rate limit: 4/5 reviews remaining, refill in 12 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.mm (1)

288-337: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make delegated-signal AUTH decisions non-cacheable.

This branch now depends on mutable runtime config (allowDelegatedSignals) plus per-message instigator data, but successful AUTH_SIGNAL decisions still inherit cacheable = true. A delegated signal allowed while the flag is YES can therefore remain effective after the config is tightened back to NO.

🛡️ Suggested fix
     case ES_EVENT_TYPE_AUTH_SIGNAL: {
+      // This decision depends on mutable config and per-message instigator
+      // metadata, so stale ALLOW cache entries can outlive policy changes.
+      cacheable = false;
+
       if (esMsg->event.signal.sig == 0) {
         // Signal 0 doesn't actually get sent to the process, it is only used to
         // check if the process exists. Because of this, we don't need to block it.
         break;
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.mm` around
lines 288 - 337, The AUTH_SIGNAL branch must mark decisions involving delegated
signals as non-cacheable: when handling ES_EVENT_TYPE_AUTH_SIGNAL and
esMsg->event.signal.instigator != NULL (and/or when self.allowDelegatedSignals
is consulted) ensure the per-decision cacheable flag is set to false so
decisions that depended on mutable runtime config (allowDelegatedSignals) or
per-message instigator data are not reused; update the logic around the
instigator check (the block that computes isAllowlisted /
isPermittedPlatformBinary and sets result = ES_AUTH_RESULT_DENY) to also set
cacheable = false (or clear any existing cacheable=true) whenever instigator !=
NULL or when allowDelegatedSignals influenced the outcome.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.mm`:
- Around line 288-337: The AUTH_SIGNAL branch must mark decisions involving
delegated signals as non-cacheable: when handling ES_EVENT_TYPE_AUTH_SIGNAL and
esMsg->event.signal.instigator != NULL (and/or when self.allowDelegatedSignals
is consulted) ensure the per-decision cacheable flag is set to false so
decisions that depended on mutable runtime config (allowDelegatedSignals) or
per-message instigator data are not reused; update the logic around the
instigator check (the block that computes isAllowlisted /
isPermittedPlatformBinary and sets result = ES_AUTH_RESULT_DENY) to also set
cacheable = false (or clear any existing cacheable=true) whenever instigator !=
NULL or when allowDelegatedSignals influenced the outcome.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae74ae01-401f-4d45-98cc-25cb46b67aea

📥 Commits

Reviewing files that changed from the base of the PR and between 77745f4 and 5264efe.

📒 Files selected for processing (8)
  • Source/common/Platform.h
  • Source/common/SNTConfigurator.h
  • Source/common/SNTConfigurator.mm
  • Source/common/SNTConfiguratorTest.mm
  • Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.h
  • Source/santad/EventProviders/SNTEndpointSecurityTamperResistance.mm
  • Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm
  • Source/santad/Santad.mm

@sharvilshah sharvilshah changed the title fix snt-404 Add delegated signal handling support May 1, 2026
@github-actions github-actions Bot added the docs Improvements or additions to documentation label May 1, 2026

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm (1)

576-603: ⚡ Quick win

Add cacheable assertion in the v9 instigator matrix loop.

These new cases validate disposition/result, but not cacheability. Since AUTH_SIGNAL is always non-cacheable, this is worth asserting here too.

Suggested patch
@@
       XCTAssertSemaTrue(semaMetrics, 5, "Metrics not recorded within expected window");
       XCTAssertEqual(gotAuthResult, c.expected, @"%s", c.desc);
+      XCTAssertFalse(gotCachable, @"%s", c.desc);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm`
around lines 576 - 603, Add an assertion inside the v9 instigator matrix loop
(the for (const auto& c : cases) block) to validate cacheability for AUTH_SIGNAL
cases: after the handleMessage call and before signaling the semaphore/after
XCTAssertEqual(gotAuthResult,...), assert that the event was non-cacheable
(e.g., expect cacheable == false) since AUTH_SIGNAL should always be
non-cacheable; locate the check around mockTamperClient->handleMessage /
recordEventMetrics and add the cacheability assertion referencing the loop
variable c (or esMsg.event.signal) and the same c.desc for failure context.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm`:
- Around line 576-603: Add an assertion inside the v9 instigator matrix loop
(the for (const auto& c : cases) block) to validate cacheability for AUTH_SIGNAL
cases: after the handleMessage call and before signaling the semaphore/after
XCTAssertEqual(gotAuthResult,...), assert that the event was non-cacheable
(e.g., expect cacheable == false) since AUTH_SIGNAL should always be
non-cacheable; locate the check around mockTamperClient->handleMessage /
recordEventMetrics and add the cacheability assertion referencing the loop
variable c (or esMsg.event.signal) and the same c.desc for failure context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36bc34d0-0249-4f5f-b8fb-80cd9d45e954

📥 Commits

Reviewing files that changed from the base of the PR and between 0eb856b and 00749a1.

📒 Files selected for processing (1)
  • Source/santad/EventProviders/SNTEndpointSecurityTamperResistanceTest.mm

@sharvilshah sharvilshah merged commit d3cd14f into main May 4, 2026
9 checks passed
@sharvilshah sharvilshah deleted the sbs/snt-404 branch May 4, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/common comp/santad Issues or PRs related to the daemon configurator Issues or PRs related to the configurator / Santa configuration docs Improvements or additions to documentation lang/objc++ PRs modifying files in ObjC++ size/m Size: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants