Skip to content

DynamoDS/DYN-8973: [SPIKE] Investigate why there is arbitrary network traffic even during Dynamo startup with no-network mode set to true#17158

Closed
edwin-vasquez-ucaldas wants to merge 2 commits into
masterfrom
8973-investigate-network-traffic-startup
Closed

DynamoDS/DYN-8973: [SPIKE] Investigate why there is arbitrary network traffic even during Dynamo startup with no-network mode set to true#17158
edwin-vasquez-ucaldas wants to merge 2 commits into
masterfrom
8973-investigate-network-traffic-startup

Conversation

@edwin-vasquez-ucaldas

@edwin-vasquez-ucaldas edwin-vasquez-ucaldas commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes https://autodesk.atlassian.net/browse/DYN-8973

h1. Audit and Tighten {{--NoNetworkMode}} Startup Traffic Implementation Plan

h2. Overview

This spike asks why network traffic still appears during Dynamo startup when {{--NoNetworkMode}} is on. Investigation shows the flag correctly silences every Dynamo-authored HTTP/REST client. The residual traffic comes from WebView2 / Microsoft Edge runtime background services invoked when Dynamo opens its WebView2 surfaces (SplashScreen, HomePage, Library, DocumentationBrowser). None of those surfaces currently pass {{CoreWebView2EnvironmentOptions.AdditionalBrowserArguments}} to suppress Edge component update, SmartScreen, domain reliability, etc. A secondary issue is that the SplashScreen is constructed before {{NoNetworkMode}} is propagated to any view-side surface, so even a properly configured no-network WebView2 profile is bypassed for the first window the user sees.

Plan: (1) capture an empirical baseline of what fires under {{--NoNetworkMode}}; (2) thread the flag into every WebView2 initialization path; (3) configure WebView2 environment options to disable Edge background networking when the flag is set; (4) guard a small set of unconditional helpers; (5) document and lock the behavior with a regression test.

h2. Current State Analysis

h3. Key Discoveries:

  • {{NoNetworkMode}} is a CLI-only flag ({{StartupUtils.cs:59-60}}), parsed at {{:107}}, stored at {{DynamoModel.cs:731}}.
  • Dynamo-authored sources correctly gated: feature flags ({{DynamoModel.cs:806}}), analytics ({{:802}}), IDSDK ({{StartupUtils.cs:443}}), Greg ({{PackageManagerExtension.cs:168-178}}), notifications ({{NotificationCenterController.cs:103}}), connectivity probe ({{DynamoViewModel.cs:282}}).
  • {{WebView2Utilities.cs:41-48}} calls {{EnsureCoreWebView2Async()}} with no {{CoreWebView2EnvironmentOptions}}, so Edge runtime defaults are active for every WebView2 instance.
  • Splash WebView2 created at {{DynamoCoreSetup.cs:76}} before model creation at {{:145}}, even though the flag is known at {{:62}}.
  • {{NetworkUtilities.InitInternetCheck()}} is called unconditionally at {{DynamoViewModel.cs:947}} (does not transmit but is a code-hygiene gap).
  • {{CrashReportTool.ShowCrashWindow}} ({{DynamoCoreSetup.cs:110}}) uploads crash dumps; not gated.
  • Existing {{--NoNetworkMode}} integration test ({{DynamoApplicationTests.cs:71-81}}) only verifies analytics is disabled — does not assert zero network traffic.

h2. Desired End State

When Dynamo launches with {{--NoNetworkMode}}, a packet capture of the Dynamo process tree during "launch → idle home workspace" shows:

  • Zero outbound TCP from {{Dynamo.exe}} / {{DynamoSandbox.exe}} / {{DynamoFeatureFlags.exe}} to any third-party host.
  • {{msedgewebview2.exe}} children spawned by Dynamo make at most platform-required calls (verified by passing {{--disable-background-networking --disable-component-update --disable-domain-reliability --disable-sync --disable-translate --disable-default-apps --no-pings --disable-features=NetworkService,OptimizationGuideModelDownloading}} to the WebView2 environment).
  • Crash-time CER upload is either gated or explicitly documented as out-of-scope with an in-product warning.
  • A developer-facing doc enumerates what is and is not blocked, with reproduction steps.

Verification: extend {{DynamoApplicationTests}} to launch {{DynamoCLI}} and {{DynamoWPFCLI}} with {{--NoNetworkMode}} while a global socket-creation hook fails the test on any non-loopback connection.

h2. What We're NOT Doing

  • Not changing the semantics of {{NoNetworkMode}} (still CLI-only, still process-lifetime, still bool).
  • Not adding a runtime-toggleable equivalent in {{PreferenceSettings}}. Separate ticket.
  • Not blocking package downloads triggered by explicit user action — already gated.
  • Not refactoring {{IDSDKManager}} to be lazily constructed. The current null-auth-provider pattern is fine.
  • Not modifying graph-execution-time HTTP nodes (already use {{ThrowIfNoNetworkMode}}).
  • Not pushing changes to Greg / Autodesk Analytics shared libraries.
  • Not investigating Revit / FormIt / Civil3D host-side traffic. Scope is Dynamo standalone.
  • Not disabling WebView2 entirely. Splash and HomePage still render, just without Edge background features.

h2. Implementation Approach

Sequenced as: (1) baseline measurement → (2) plumb flag to all WebView2 init sites → (3) build no-network WebView2 environment factory → (4) guard residual unconditional helpers → (5) regression test → (6) documentation. Each task ends with a single observable milestone.


h3. TASK 1: Capture an empirical baseline of all outbound traffic under {{--NoNetworkMode}} [HIGH PRIORITY]

Status: DONE
Milestone: A reproducible packet/process trace, committed as a markdown report under {{doc/}}, listing every observed remote endpoint and the process that initiated it, classified as (a) Dynamo first-party, (b) WebView2/Edge runtime, (c) OS-level (CER, IDSDK service, Edge updater).

  • Install Fiddler / Wireshark / Process Monitor on a clean Windows VM.
  • Launch {{DynamoSandbox.exe --NoNetworkMode}} and let it sit idle on the home workspace for 60 seconds.
  • Capture full process tree including child {{msedgewebview2.exe}}, {{DynamoFeatureFlags.exe}}, {{senddmp.exe}}, IDSDK service.
  • Tag each TCP connection with PID + parent + destination host.
  • Repeat with {{--NoNetworkMode}} off to produce a delta.
  • Commit summary to {{doc/no-network-mode-traffic-baseline.md}}.

Validation: Reviewer can rerun the procedure and reproduce the same endpoint set within tolerance.

Requirements from spec:

  • Identify why there is arbitrary network traffic at startup with {{--NoNetworkMode}} set.
  • Distinguish Dynamo-authored traffic from WebView2 platform traffic.

Files to Create:

  • {{doc/no-network-mode-traffic-baseline.md}} — Captured endpoints + classification table.

Files to Modify:

  • None.

Implementation Details:
Use {{npcap}} filter {{ip and not host 127.0.0.1}} and Wireshark display filter {{tcp.flags.syn == 1 and tcp.flags.ack == 0}}. Cross-reference with Process Monitor {{Network Activity}} view to attach PIDs.


h3. TASK 2: Add a no-network WebView2 environment factory [HIGH PRIORITY]

Status: NOT STARTED
Milestone: Every WebView2 surface in Dynamo can opt into a hardened Edge profile in one line, and a unit test verifies the configured {{AdditionalBrowserArguments}} contains the expected Edge flags.

  • Add an {{Initialize(CoreWebView2EnvironmentOptions environmentOptions, Action logFn = null)}} overload to {{DynamoWebView2}} ({{WebView2Utilities.cs:41-48}}).
  • Add static {{WebView2Utilities.CreateNoNetworkOptions()}} returning a {{CoreWebView2EnvironmentOptions}} with {{AdditionalBrowserArguments = "--disable-background-networking --disable-component-update --disable-domain-reliability --disable-sync --disable-translate --disable-default-apps --no-pings --disable-features=NetworkService,OptimizationGuideModelDownloading"}}.
  • Route through {{CoreWebView2Environment.CreateAsync(null, userDataFolder, environmentOptions)}} and pass the result to {{EnsureCoreWebView2Async(environment)}}.
  • Update {{PublicAPI.Unshipped.txt}} with new public surface.

Validation: New NUnit test {{DynamoWebView2Tests.WhenNoNetworkModeEnabledThenAdditionalBrowserArgumentsContainsDisableBackgroundNetworking}} asserts the configured command line includes the expected flags.

Requirements from spec:

  • Provide a single switch that disables WebView2 platform background networking.

Files to Modify:

  • {{src/DynamoCoreWpf/Utilities/WebView2Utilities.cs}} — Add overload + factory.
  • {{src/DynamoCoreWpf/PublicAPI.Unshipped.txt}} — Declare new public API.
  • {{test/DynamoCoreWpfTests/...}} — New test class.

Implementation Details:
Edge command-line arguments are documented in Chromium switches; WebView2 inherits the Chromium command-line surface. {{OptimizationGuideModelDownloading}} suppresses Edge ML model downloads.


h3. TASK 3: Thread {{NoNetworkMode}} into SplashScreen and pass hardened options [HIGH PRIORITY]

Status: NOT STARTED
Milestone: With {{--NoNetworkMode}} set, splash WebView2 starts with Edge background networking disabled before any frame is rendered.

  • Add {{bool noNetworkMode}} parameter to {{SplashScreen(...)}} constructor ({{SplashScreen.xaml.cs:167}}) — prefer a new constructor overload to preserve the existing public API.
  • Store the value on the splash instance.
  • In {{OnContentRendered}} ({{SplashScreen.xaml.cs:390-447}}), if {{noNetworkMode}} is true, call {{WebView2Utilities.CreateNoNetworkOptions()}} and pass to the new {{webView.Initialize(options)}} overload.
  • Update {{DynamoCoreSetup.RunApplication}} ({{DynamoCoreSetup.cs:76}}) to pass {{noNetworkMode}}.
  • Search for other {{new SplashScreen}} call sites and update.

Validation: Run {{DynamoSandbox.exe --NoNetworkMode}}, take a Process Monitor capture of the splash {{msedgewebview2.exe}} child, confirm zero outbound connections to {{.msedge.net}}, {{.bing.com}}, {{*.googleapis.com}}, {{dl.delivery.mp.microsoft.com}}.

Requirements from spec:

  • Ensure SplashScreen honors the no-network flag (currently constructed before the model).

Files to Modify:

  • {{src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs}} — Constructor + {{OnContentRendered}}.
  • {{src/DynamoSandbox/DynamoCoreSetup.cs}} — Constructor call.
  • {{src/DynamoCoreWpf/PublicAPI.Unshipped.txt}} — New constructor overload.

Implementation Details:
Add a second constructor overload rather than changing the default-valued single ctor — public API hygiene per {{dynamo-core-rules.md}}.


h3. TASK 4: Thread {{NoNetworkMode}} into HomePage / Library / DocumentationBrowser [HIGH PRIORITY]

Status: NOT STARTED
Milestone: Every WebView2 surface created after the model exists initializes with the hardened Edge profile when {{NoNetworkMode}} is true.

  • {{HomePage.UserControl_Loaded}} ({{HomePage.xaml.cs:144}}): read {{startPage.DynamoViewModel.Model.NoNetworkMode}} before {{Initialize}} at {{:162}}.
  • {{LibraryViewController}} WebView2 init: thread {{NoNetworkMode}} via the existing {{ViewLoadedParams}} or a new field populated during {{ViewExtension.cs:39}}.
  • {{DocumentationBrowserView.xaml.cs:177}}: same pattern.
  • {{PackageManagerWizard.xaml.cs:238}}: defense in depth, even though this only runs on user action.
  • {{NotificationCenterController.cs:105}}: already gated, no change.

Validation: With {{--NoNetworkMode}}, only splash and home WebView2 children should be running, with zero non-local connections.

Requirements from spec:

  • Eliminate WebView2 platform traffic from all surfaces created during normal startup.

Files to Modify:

  • {{src/DynamoCoreWpf/Views/HomePage/HomePage.xaml.cs}}
  • {{src/LibraryViewExtensionWebView2/LibraryViewController.cs}}, {{ViewExtension.cs}}
  • {{src/DocumentationBrowserViewExtension/DocumentationBrowserView.xaml.cs}}
  • {{src/DynamoCoreWpf/Views/PackageManager/Components/PackageManagerWizard/PackageManagerWizard.xaml.cs}}

Implementation Details:
For view extensions, prefer the {{StartupParams.NoNetworkMode}} path since it's already in the contract.


h3. TASK 5: Guard residual unconditional helpers [MEDIUM PRIORITY]

Status: NOT STARTED
Milestone: No code path allocates network plumbing when {{NoNetworkMode}} is true.

  • Guard the call at {{DynamoViewModel.cs:947}} so {{NetworkUtilities.InitInternetCheck()}} is only invoked when {{!Model.NoNetworkMode}}.
  • Decide CER policy: gate {{CrashReportTool.ShowCrashWindow}} on {{Model.NoNetworkMode}} (write a local-only dump with a {{Logger.LogWarning}}), or document that crashes still upload. Recommended: gate it.
  • In {{DynamoMLDataPipelineExtension.Startup}} ({{:23-37}}), if {{sp.NoNetworkMode}} is true, do not wire token / user-id providers (symmetry; the pipeline never transmits without user action).

Validation: Re-run Process Monitor; confirm no {{HttpClient}} is allocated by {{NetworkUtilities}}.

Requirements from spec:

  • Close remaining ambiguous code paths an auditor would flag.

Files to Modify:

  • {{src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs}} (line 947)
  • {{src/DynamoCoreWpf/Utilities/CrashReportTool.cs}}
  • {{src/DynamoMLDataPipeline/DynamoMLDataPipelineExtension.cs}}

Implementation Details:
For CER, the path is {{DynamoCoreSetup.cs:110 → viewModel.Model.OnRequestsCrashPrompt → CrashReportTool.ShowCrashWindow}}. Add a guard inside {{ShowCrashWindow}} reading {{args?.Model?.NoNetworkMode}}, or expose {{NoNetworkMode}} on {{CrashErrorReportArgs}}.


h3. TASK 6: Add a regression test that fails on any unexpected outbound socket [HIGH PRIORITY]

Status: NOT STARTED
Milestone: NUnit test in {{DynamoApplicationTests.cs}} launches DynamoCLI (and DynamoWPFCLI) with {{--NoNetworkMode}} and asserts no non-loopback TCP socket is opened by the process tree during a 30-second idle window.

  • Add {{WhenDynamoStartsWithNoNetworkModeThenNoOutboundConnectionsAreOpened}} test.
  • Spawn {{DynamoCLI.exe --NoNetworkMode --KeepAlive -n}} and capture child process tree.
  • Snapshot active TCP connections per PID at t=5s and t=30s via {{IPGlobalProperties.GetActiveTcpConnections()}}.
  • Filter loopback (127.0.0.1, ::1) and link-local addresses.
  • Assert no remote endpoints remain.
  • Mark {{[Category("NetworkAudit")]}} and {{[Explicit]}} with a comment explaining why.
  • Run locally; confirm it passes after prior tasks merge.

Validation: {{dotnet test test/System/IntegrationTests --filter Name~NoNetworkMode}} passes.

Requirements from spec:

  • Lock the no-network guarantee against regression.

Files to Modify:

  • {{test/System/IntegrationTests/DynamoApplicationTests.cs}}

Implementation Details:
WebView2 children appear under the same parent PID; iterate {{Process.GetProcesses()}} and filter by {{Parent.Id == cliProcess.Id}} plus a name allow-list. Use NUnit {{Assert.That(..., Is.Empty)}}. Test should run on a clean dev machine or isolated CI agent to avoid Defender/proxy noise.


h3. TASK 7: Document the contract [MEDIUM PRIORITY]

Status: NOT STARTED
Milestone: Developer-facing doc lists every gated and ungated network surface, with rationale and the WebView2 caveat made explicit.

  • Create {{doc/distrib/no-network-mode.md}}.
  • Enumerate the matrix: surface → endpoint → gate location → behavior under {{--NoNetworkMode}}.
  • Add "Known limitations" section: WebView2 platform updates configured at the OS level, Microsoft Edge component-update service, Autodesk IDSDK service, SmartScreen.
  • Cross-link from {{AGENTS.md}} and {{.claude/rules/dynamo-core-rules.md}}.

Validation: Reviewer reads the doc and can predict what a Wireshark capture will show.

Requirements from spec:

  • Communicate what {{--NoNetworkMode}} guarantees and what it cannot.

Files to Create:

  • {{doc/distrib/no-network-mode.md}}

Files to Modify:

  • {{AGENTS.md}} (cross-link)
  • {{.claude/rules/dynamo-core-rules.md}} (cross-link)

Implementation Details:
Follow the structure of existing docs in {{doc/distrib/}}. Include the endpoint inventory verbatim from research.


h2. Testing Strategy

h3. Unit Tests:

  • {{DynamoWebView2Tests}} — assert {{CreateNoNetworkOptions}} produces expected {{AdditionalBrowserArguments}}.
  • Verify {{Initialize(options)}} overload is the path used when {{noNetworkMode}} is true.
  • Verify {{NetworkUtilities.InitInternetCheck}} is not invoked when {{Model.NoNetworkMode}} is true.

h3. Integration Tests:

  • Extend {{DynamoApplicationTests}}:
    ** Verify analytics, feature flags, IDSDK, Greg, notifications all skip startup work.
    ** Verify zero outbound TCP from Dynamo process tree (Task 6).
    ** Verify splash and home WebView2 children inherit the hardened Edge command line ({{Process.GetCommandLine()}} of {{msedgewebview2.exe}} children).

h3. Manual Testing Steps:

{{DynamoSandbox.exe}} (no flag) + Wireshark filter {{tcp.flags.syn == 1 and not ip.dst == 127.0.0.1}}. Confirm baseline traffic.

{{DynamoSandbox.exe --NoNetworkMode}}. Confirm zero first-party and zero WebView2 platform traffic.

{{DynamoCLI.exe --NoNetworkMode -o some.dyn -k}}. Confirm zero traffic.

Click around the home page; verify no YouTube embed fires a request.

Verify "Open Package Manager" is disabled.

Trigger a deliberate crash and confirm CER does not upload, or an in-product message warns.

Run Task 6 integration test.

h2. Performance Considerations

  • {{AdditionalBrowserArguments}} evaluation is a one-time string at {{CoreWebView2Environment.CreateAsync}} — negligible cost.
  • Skipping {{NetworkUtilities.InitInternetCheck()}} shaves a one-time {{HttpClient}} allocation.
  • Gating CER avoids spawning the external tool on crash paths.
  • No impact on happy-path startup time when {{--NoNetworkMode}} is off.

h2. Migration Notes

  • {{SplashScreen}} gains a new constructor overload; existing zero-arg ctor remains, so integrators are unaffected.
  • {{DynamoWebView2.Initialize}} gains an overload; existing one keeps its behavior.
  • {{WebView2Utilities.CreateNoNetworkOptions()}} is new public static; add to {{PublicAPI.Unshipped.txt}}.
  • No change to {{NoNetworkMode}} semantics, {{PreferenceSettings}} schema, or CLI flags.
  • Hosts (Revit, FormIt, Civil3D, Alias, Advance Steel) constructing {{DynamoModel}} directly are unaffected — they already pass {{noNetworkMode}} through {{IStartConfiguration.NoNetworkMode}} and the additional plumbing only touches standalone Sandbox view stack.

@edwin-vasquez-ucaldas edwin-vasquez-ucaldas added the kiln Created by kiln label Jun 10, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-8973

Adds doc/no-network-mode-traffic-baseline.md with the reproduction
procedure, expected first-party endpoints (derived from App.config files
and code inspection), and the WebView2 / OS-level surfaces that are out
of Dynamo's first-party control. Empirical capture tables are left as
TODO sections to be filled in from a manual Wireshark / Process Monitor
run on a clean Windows VM.
@edwin-vasquez-ucaldas edwin-vasquez-ucaldas deleted the 8973-investigate-network-traffic-startup branch June 10, 2026 18:52
@sonarqubecloud

Copy link
Copy Markdown

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

Labels

kiln Created by kiln

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant