You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
tl;dr: We need to remove our dependency on RapidJson in .NET 12. We should also strongly consider removing it from servicing branches after we stabilize its removal from .NET 12.
There's a coming compliance effort within MSFT to rid repos of out-of-date / unsupported dependencies. The first wave of this will almost certainly involve flagging usage of RapidJson, which is generally viewed as an abandoned project.
(Edit - we're already receiving alerts on this. What's being proposed is enforcement.)
To be clear: our own usage of RapidJson is secure, but the amount of paperwork and toil that's going to be required to keep this dependency around is almost certainly not going to be worth our time. Additionally, since RapidJson presumably shows up in our SBOMs, customers who run their own compliance scans (or who outsource such scans to third-party tooling) will start receiving similar alerts as the industry at large moves toward reducing stale dependencies. We've seen this before with complaints re: out-of-date versions of zlib; even though customers were never realistically exposed to any vulnerability, it simply caused too much pain for too many parties, and we changed our servicing policy to accommodate it.
@am11 also had the suggestion of trying to switch the components that use it (hostfxr, hostpolicy`) to Native AOT, so we'd be using System.Text.Json for JSON parsing. Aside from just the risk of a large rewrite, startup perf would probably be the deciding factor for whether or not that is really an option (we know size would increase). That wouldn't be something I'd want to put into servicing branches though.
We can ask copilot to grab main...am11:runtime:feature/managed-corehost and apply over to main branch (incorporating recent refactoring). I think we will get the startup numbers out in few hours. The idea is; apphost, nethost and singlefilehost remain in C while the rest of muxer etc. where RapidJSON is used can be converted to NativeAOT.
switch the components that use it (hostfxr, hostpolicy`) to Native AOT, so we'd be using System.Text.Json for JSON parsing. Aside from just the risk of a large rewrite, startup perf would probably be the deciding factor for whether or not that is really an option (we know size would increase).
I'd assume the permanent overhead from 2nd GC, threadpool and such would be the bigger problem with this.
Middle ground is to just offload JSON related interactions to an external lib. We can add something like src/native/managed/Microsoft.NET.HostActivationContext to produce libhostactivationcontext that fills out this contract:
#ifndefHOST_ACTIVATION_H#defineHOST_ACTIVATION_H#ifdef__cplusplusextern"C" {
#endif#include<stddef.h>#include<stdbool.h>typedefstructhost_activation_context {
// --- Activation Targets & Global Settings ---constchar*target_framework_moniker; // Points to string inside this block ("net8.0")constchar*dev_runtime_config_path; // Points to string inside this block if mergedintglobal_roll_forward; // Corehost fallback roll-forward policy enumintglobal_roll_forward_on_no_cand_fx; // Fallback policy on missing framework// --- Core Activation Flags ---boolis_self_contained; // Derived flag based on framework inclusionsboolcache_ready_to_run; // Maps runtimeOptions.cacheReadyToRunboolenable_exec_stack; // Maps runtimeOptions.enableExecutionStack// --- Array 1: Configuration Properties / AppContext Switches ---size_tprop_count;
constchar**prop_keys; // Points to an array of string pointers inside this blockconstchar**prop_vals; // Points to an array of string pointers inside this block// --- Array 2: Assembly Probing Paths ---size_tprobe_paths_count;
constchar**probe_paths; // Points to an array of string pointers inside this block// --- Array 3: Primary Framework Dependencies ---size_tfxr_count;
constchar**fxr_names; // Points to framework name string array inside this blockconstchar**fxr_versions; // Points to framework version string array inside this blockbool*fxr_apply_patches; // Points to array of apply_patches boolean state flagsint*fxr_roll_forwards; // Points to array of roll_forward enum integersint*fxr_rf_on_no_candidates; // Points to array of roll_forward_on_no_candidate_fx enumsbool*fxr_prefer_releases; // Points to array of prefer_release evaluation flags// --- Array 4: Included / Application-Local Frameworks ---size_tfxr_incl_count;
constchar**fxr_incl_names; // Points to included framework name string arrayconstchar**fxr_incl_versions; // Points to included framework version string arraybool*fxr_incl_apply_patches; // Points to array of apply_patches flags int*fxr_incl_roll_forwards; // Points to array of roll_forward enums int*fxr_incl_rf_on_no_cands; // Points to array of roll_forward_on_no_candidate_fx enumsbool*fxr_incl_prefer_releases;// Points to array of prefer_release flags
} host_activation_context_t;
/** * Parses the specified target runtimeconfig.json file path and automatically * handles companion .dev.json lookups, setting overrides, and flattening. * * @param config_path [in] The platform-specific path to the json configuration file. * @param out_bytes_allocated [out] Receives the absolute total memory size of the single chunk. * Can be passed to another process or used for diagnostics. * @return A single contiguous allocated block pointer, or NULL if parsing fails. */host_activation_context_t*host_activation_context_create(
constchar*config_path,
size_t*out_bytes_allocated
);
/** * Releases the continuous memory tracking block completely. * Because the allocation engine enforces zero-fragmentation, this can * also be directly cleared using standard system free(). * * @param context Handle to the active runtime configuration context. */voidhost_activation_context_free(host_activation_context_t*context);
#ifdef__cplusplus
}
#endif#endif// HOST_ACTIVATION_H
Today, all JSON related ops are handled before the runtime is initialized so we can concentrate them to a single call to a component "fill me this contract" then use that object for rest of the execution. To safely unload it after the call (and before initializing the runtime), here is a bit brittle (but working) solution: #64629 (comment).
Activity
dotnet-policy-service commentedon Jul 28, 2026
Tagging subscribers to this area: @dotnet/area-meta
See info in area-owners.md if you want to be subscribed.
jkoritzinsky commentedon Jul 28, 2026
@GrabYourPitchforks if I'm reading the SDL guidance correctly, the approved JSON serializer for C++ is https://github.com/nlohmann/json, correct?
JakeYallop commentedon Jul 29, 2026
I'm not suggesting I have a workaround here, but I've written a couple of apps where I've wanted fast start up.
Will this change slow down app startup, and do we know by how much it might regress for typical (primarily R2R'd if you want fast startup) apps?
elinor-fung commentedon Jul 29, 2026
@am11 also had the suggestion of trying to switch the components that use it (
hostfxr, hostpolicy`) to Native AOT, so we'd be using System.Text.Json for JSON parsing. Aside from just the risk of a large rewrite, startup perf would probably be the deciding factor for whether or not that is really an option (we know size would increase). That wouldn't be something I'd want to put into servicing branches though.We'll definitely want to measure any impact here.
am11 commentedon Jul 29, 2026
We can ask copilot to grab main...am11:runtime:feature/managed-corehost and apply over to main branch (incorporating recent refactoring). I think we will get the startup numbers out in few hours. The idea is; apphost, nethost and singlefilehost remain in C while the rest of muxer etc. where RapidJSON is used can be converted to NativeAOT.
MichalPetryka commentedon Jul 30, 2026
I'd assume the permanent overhead from 2nd GC, threadpool and such would be the bigger problem with this.
am11 commentedon Aug 2, 2026
Middle ground is to just offload JSON related interactions to an external lib. We can add something like
src/native/managed/Microsoft.NET.HostActivationContextto produce libhostactivationcontext that fills out this contract:Today, all JSON related ops are handled before the runtime is initialized so we can concentrate them to a single call to a component "fill me this contract" then use that object for rest of the execution. To safely unload it after the call (and before initializing the runtime), here is a bit brittle (but working) solution: #64629 (comment).