Can Windows Filtering Platform independently verify outbound firewall blocking without network traffic?

אסף מנגוני 0 Reputation points
2026-10-25T09:54:06.01+00:00

We are investigating a supported, read-only method to independently verify Windows Defender Firewall's effective outbound policy for a specific executable.

We understand that Get-NetFirewallRule -PolicyStore ActiveStore provides the applicable firewall policy, but we need to understand what can be verified independently through Windows Filtering Platform (WFP).

Our questions are:

Can the WFP management API enumerate all active filters potentially affecting outbound traffic from a particular executable, without generating network traffic or starting a capture?

Is there a documented way to map WFP filters back to their originating Windows Defender Firewall rules, including rule identifiers and policy sources such as local policy or Group Policy?

Can read-only WFP filter enumeration establish that all outbound connections from an executable would be blocked, or is observing an actual classification decision necessary?

What limitations must be considered, including third-party callouts, filter arbitration, sublayers, profile changes, and permissions required for read-only enumeration?

We are not seeking to modify firewall settings or bypass security controls.

We would appreciate guidance on supported Windows APIs, official documentation, and the strongest verification claim that can legitimately be made without generating traffic.

Thank you.

Windows development | Windows API - Win32

2 answers

Sort by: Most helpful
  1. Tony Thach (WICLOUD CORPORATION) 1,445 Reputation points Microsoft External Staff Moderator
    2026-10-26T05:37:28.5633333+00:00

    Hi @אסף מנגוני , and thanks for posting your question.

    Thank you also for making it clear that you are looking for a read-only approach. Below is what can be verified through Windows Filtering Platform (WFP) without generating traffic, and where the documented limits are.

    Summary

    1. Filter enumeration without traffic: Yes. Read-only enumeration of the filters that may affect an executable is supported and does not require traffic or a capture, within the limits of the caller's access and a point-in-time snapshot.
    2. Filter-to-rule mapping: I could not find public Microsoft documentation that provides a one-to-one mapping from a WFP filter (filterId or filterKey) back to a Windows Defender Firewall rule ID and policy source. Rule identity and origin should come from the firewall's ActiveStore.
    3. Proving that everything is blocked: Enumeration can support a scoped, point-in-time policy conclusion. It cannot prove that every outbound connection from the executable will be blocked. Direct evidence of an enforcement decision requires an actual classification result, such as a WFP drop event.
    4. Limitations: sublayer arbitration, callouts, runtime conditions, profile changes, snapshot timing, and object permissions. Details are below.
    5. Enumerating filters without traffic

    Option A: netsh (read-only)

    Run from an elevated Command Prompt:

    netsh wfp show appid file="C:\Path\To\App.exe"
    netsh wfp show filters file=app-filters.xml appid="C:\Path\To\App.exe" dir=out verbose=on
    netsh wfp show state file=wfpstate.xml
    
    • show appid displays the device path that WFP uses for the executable.
    • show filters displays the filters matching the specified traffic parameters. Please keep verbose=on, because the default (off) suppresses filters considered unlikely to affect connectivity. The appid path must exist.
    • show state exports the current WFP state, which you can use to resolve the layers, sublayers, providers, and callouts referenced by each filter.

    Reference: netsh wfp

    Option B: WFP management API

    1. Open a session with FwpmEngineOpen0.
    2. Begin a read-only transaction with FwpmTransactionBegin0(engine, FWPM_TXN_READ_ONLY). Filter enumerators are not live, so create and read the enumerator inside the same explicit transaction if you need a consistent view.
    3. Convert the executable path with FwpmGetAppIdFromFileName0 for the FWPM_CONDITION_ALE_APP_ID condition.
    4. Enumerate with FwpmFilterCreateEnumHandle0 and FwpmFilterEnum0, at minimum for FWPM_LAYER_ALE_AUTH_CONNECT_V4 and FWPM_LAYER_ALE_AUTH_CONNECT_V6. These layers authorize TCP connect(), the first UDP packet to a unique remote address and port, and the first outbound non-error ICMP message.
    5. Enumerate the related sublayers, providers, and callouts so that each filter's sublayer priority and callout can be resolved.
    6. End the transaction and close the session.

    The enumeration type is important for your third question:

    • FWP_FILTER_ENUM_FULLY_CONTAINED returns only filters that fully contain the enum conditions. These filters match every connection in the scope you defined, for example an application-wide or wildcard Block.
    • FWP_FILTER_ENUM_OVERLAPPING also returns filters that match only part of that scope, for example an Allow limited to one port, user, or remote address. These are the exceptions that must be ruled out before claiming that all outbound connections are blocked.

    FWP_FILTER_ENUM_FLAG_BEST_TERMINATING_MATCH returns only the highest-weight terminating filter, so it should not be treated as a simulated arbitration result.

    2. Mapping filters to firewall rules

    What is documented:

    • FWPM_SUBLAYER_MPSSVC_WF hosts Windows Firewall filters, including those from rules added through Windows Firewall. Other sublayers host Windows Service Hardening (FWPM_SUBLAYER_MPSSVC_WSH), App Container isolation (FWPM_SUBLAYER_MPSSVC_APP_ISOLATION), and quarantine (FWPM_SUBLAYER_MPSSVC_QUARANTINE) filters.
    • A single rule can be implemented by more than one filter. Microsoft's firewall guidance notes that using ranges instead of individual addresses or ports "avoids creation of multiple filters under the hood".
    • Rule identity and origin are exposed by the ActiveStore, which is the resultant set of policy (GPOs plus local stores, including Windows Service Hardening). With -TracePolicyStore, PolicyStoreSourceType reports Local, GroupPolicy, Dynamic, Generated, or Hardcoded, and PolicyStoreSource identifies the source (for domain GPOs, the GPO name only).
    • EnforcementStatus shows whether a rule is currently enforced, for example Full, InactiveProfile, or OptimizedOut.
    • Network isolation rules for Store app containers are stored separately and are not accessible with Get-NetFirewallRule.

    Read-only inventory of outbound rules that name the executable or apply to any program (from an elevated PowerShell window):

    $exe = 'C:\Path\To\App.exe'
    # Read-only. This can take a while on systems with many rules.
    Get-NetFirewallRule -PolicyStore ActiveStore -TracePolicyStore -Direction Outbound |
        ForEach-Object {
            $app = $_ | Get-NetFirewallApplicationFilter
            $program = [Environment]::ExpandEnvironmentVariables($app.Program)
            if ($program -eq 'Any' -or $program -eq $exe) {
                [pscustomobject]@{
                    DisplayName       = $_.DisplayName
                    Name              = $_.Name
                    Action            = $_.Action
                    Enabled           = $_.Enabled
                    Profile           = $_.Profile
                    Program           = $app.Program
                    EnforcementStatus = $_.EnforcementStatus -join ', '
                    SourceType        = $_.PolicyStoreSourceType
                    Source            = $_.PolicyStoreSource
                }
            }
        } | Format-Table -AutoSize
    

    Rules can also match by service, package, user, port, or address, so please treat this as an inventory, not a decision. Explicit Block rules take precedence over Allow rules, except allow bypass rules (AllowBypass), and Windows Firewall does not support administrator-assigned rule ordering.

    Correlating these rules with WFP filter display data, conditions, and sublayers is useful for diagnosis, but I would not present it as an authoritative rule-to-filter mapping.

    3. Can enumeration prove that all outbound connections are blocked?

    Not on its own, for these documented reasons:

    • Sublayer arbitration. All sublayers in a layer are evaluated. Within a sublayer, the highest-weight matching filter that returns Permit or Block decides. Across sublayers, Block overrides Permit, but a hard Permit can only be overridden at another sublayer by a callout Veto. A Block in the Windows Firewall sublayer is therefore not conclusive if an overlapping hard Permit exists in a higher-priority sublayer. By default, a filter Permit is soft, a filter Block is hard, and a callout Block is soft.
    • Callouts. Filters with FWP_ACTION_CALLOUT_TERMINATING or FWP_ACTION_CALLOUT_UNKNOWN can return Permit or Block at runtime, and that logic lives in the callout driver, not in the filter object. FWP_ACTION_CALLOUT_INSPECTION never returns Permit or Block.
    • Runtime values. Remote address and port, protocol, interface, user, package, and profile are known only at classification time.
    • No cross-layer arbitration. Traffic permitted at one layer can still be blocked at another, so a claim limited to ALE_AUTH_CONNECT covers connection authorization only.
    • Stateful filtering. Once a connection is authorized, packets in the same ALE flow are permitted automatically until a policy change triggers reauthorization.
    • I could not find a documented management API that evaluates a hypothetical ALE connection against the full classification path without traffic.

    4. Limitations and permissions

    • Access. By default, the filter engine grants GENERIC_ALL to Administrators, GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE to Network Configuration Operators, and only FWPM_ACTRL_OPEN and FWPM_ACTRL_CLASSIFY to Everyone. Enumeration requires FWPM_ACTRL_ENUM on the container and returns only filters for which the caller has FWPM_ACTRL_READ, so a successful enumeration does not prove that no unreadable filters exist. A read-only transaction requires FWPM_ACTRL_BEGIN_READ_TXN. You can review the filter container's security descriptor with netsh wfp show security type=filter.
    • Snapshot. Policy, profile, interface, or rule changes after the snapshot are not reflected.
    • Profiles. Rules apply per profile, and quarantine filters apply while Windows is resolving an interface's firewall profile.
    • Startup. If the claim must cover system startup, boot-time policy is reported separately with netsh wfp show boottimepolicy.
    • Executable identity. The application ID is path based. A copy of the file in another location, a different user, a service context, or an App Container package can match different filters.

    If enforcement evidence is required

    • Without new traffic: If the executable has already attempted connections, recent drops may already be recorded. By default, WFP logs drops for all outbound packets in a small circular log (about 100 to 150 events) that is emptied after a reboot.
    netsh wfp show options optionsfor=NETEVENTS
    netsh wfp show netevents file=app-netevents.xml appid="C:\Path\To\App.exe"
    
    • Controlled test: In the documented TCP flow, connect() is classified at ALE_AUTH_CONNECT before the SYN reaches the outbound transport layer, so an attempt blocked at that layer should not send a SYN. If policy permits the attempt, traffic will be sent, so please use an isolated test environment or a destination you control.
    • From a block to its filter: The filter ID in a drop event, or the Filter Run-Time ID in Security event 5157 if "Audit Filtering Platform Connection" is enabled under your organization's policy, can be located in the filters.xml produced by netsh wfp show filters. That entry shows the filter's sublayer and provider.

    If this instruction is applicable to your situation, I would greatly appreciate it if you could follow the instruction here so others experiencing similar behavior can benefit from it as well.

    Was this answer helpful?

    2 people found this answer helpful.

  2. AI answer

    2026-10-25T09:55:08.2866667+00:00

    WFP filter enumeration can produce a read-only snapshot of filters that might affect an executable, but it cannot prove that every possible outbound connection will be blocked; the strongest supported proof of an actual block is a runtime classification result or its corresponding WFP drop event.

    1. What can be enumerated without traffic

    A user-mode application can:

    1. Open the filtering engine with FwpmEngineOpen0.
    2. Convert the executable path to WFP’s application identifier with FwpmGetAppIdFromFileName0. The resulting value is the lower-case, fully qualified device path used by FWPM_CONDITION_ALE_APP_ID.^1^ ^2^
    3. Enumerate filters using FwpmFilterCreateEnumHandle0 and FwpmFilterEnum0, principally at:
      • FWPM_LAYER_ALE_AUTH_CONNECT_V4
      • FWPM_LAYER_ALE_AUTH_CONNECT_V6
    4. Also inspect relevant redirect, transport, packet, and other layers when the required claim extends beyond initial ALE connection authorization. Outbound TCP connect(), the first UDP transmission to a remote tuple, and outbound ICMP authorization occur at ALE_AUTH_CONNECT.^3^
    5. Enumerate referenced providers, sublayers, provider contexts, and callouts.

    A typical application-specific enumeration template starts as follows:

    FWP_BYTE_BLOB* appId = nullptr;
    FwpmGetAppIdFromFileName0(exePath, &appId);
    
    FWPM_FILTER_CONDITION0 condition{};
    condition.fieldKey = FWPM_CONDITION_ALE_APP_ID;
    condition.matchType = FWP_MATCH_EQUAL;
    condition.conditionValue.type = FWP_BYTE_BLOB_TYPE;
    condition.conditionValue.byteBlob = appId;
    
    FWPM_FILTER_ENUM_TEMPLATE0 t{};
    t.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
    t.enumType = FWP_FILTER_ENUM_OVERLAPPING;
    t.flags = FWP_FILTER_ENUM_FLAG_SORTED;
    t.numFilterConditions = 1;
    t.filterCondition = &condition;
    t.actionMask = 0xFFFFFFFF;
    

    Use FWP_FILTER_ENUM_OVERLAPPING, not only FULLY_CONTAINED, when looking for filters whose conditions overlap the proposed application scope. The template can constrain provider, layer, conditions, action, provider context, and callout.^4^ ^5^

    Do not restrict the inventory to filters explicitly containing ALE_APP_ID: wildcard filters and filters based on user, package, service, protocol, address, port, interface, or profile can also match. Each FWPM_FILTER0 exposes its conditions, action, filter ID, provider context, and effective weight.^6^

    2. Firewall-rule provenance

    There is no documented general-purpose mapping from every WFP filterId or filterKey back to a Windows Defender Firewall rule identifier and policy source. WFP provider and sublayer metadata can identify broad ownership—for example, FWPM_SUBLAYER_MPSSVC_WF hosts Windows Firewall filters, including filters created from firewall rules—but that is not a documented one-to-one rule provenance contract.^7^

    For Windows Firewall rule identity and origin, query the supported WFAS CIM/NetSecurity model separately:

    Get-NetFirewallRule -PolicyStore ActiveStore -TracePolicyStore |
        Where-Object Direction -eq Outbound |
        Select-Object Name, DisplayName, Action, Enabled, Profiles,
                      EnforcementStatus, PolicyStoreSourceType, PolicyStoreSource
    

    With TracePolicyStoreSource, ActiveStore results expose PolicyStoreSource and PolicyStoreSourceType; InstanceID identifies the rule within its policy store, while EnforcementStatus indicates whether it is currently enforced or inactive/optimized out.^8^ Application-filter associations are exposed through the WFAS CIM model.^9^

    Correlating that rule inventory heuristically with WFP display data, conditions, providers, or filter keys is useful diagnostically, but should not be represented as an authoritative documented rule-to-runtime-filter mapping.

    3. Why enumeration cannot prove universal blocking

    Classification compares the concrete runtime tuple and metadata against filters, invokes applicable callouts, and then applies arbitration.^10^ No documented management API performs an offline, side-effect-free simulation of that complete classification for a hypothetical connection.

    The result can depend on:

    • Sublayer priority, filter weight, soft/hard actions, vetoes, and cross-layer decisions.^11^
    • Third-party callouts whose classifyFn can permit, block, continue, defer, request more data, or make an asynchronous decision using runtime metadata or packet data.^12^
    • Address, port, protocol, interface, user, package, service, redirect, and profile values not known from the executable path alone.
    • Stateful ALE behavior: after authorization, packets in the flow are normally permitted until reauthorization, such as after a policy change.^13^
    • Policy/profile changes after enumeration.

    Therefore, the defensible no-traffic statement is:

    “At the snapshot time, every readable, statically analyzable filter identified for the examined layers and specified hypothetical tuple appears to arbitrate to block, subject to callout behavior and later state or policy changes.”

    It is not defensible to claim that all outbound connections from the executable are guaranteed blocked.

    4. Snapshot and permission limitations

    FwpmFilterEnum0 operates on the snapshot taken when its enumeration handle was created.^14^ For a consistent current view, create and consume the enumerator within the same explicit read transaction. Enumeration also returns only filters for which the caller has FWPM_ACTRL_READ, and requires FWPM_ACTRL_ENUM on their containers.^15^ Consequently, a successful enumeration does not by itself establish that no unreadable filters exist.

    For definitive evidence of a particular decision, observe a real classification and inspect WFP net events. Drop events identify the filterId and layer; newer structures also record direction and original/current profiles.^16^ WFP’s event store is circular, snapshot-enumerated, limited in size, and cleared at reboot, so collect it promptly.^17^


    References

    1. FwpmGetAppIdFromFileName0 function (fwpmu.h)
    2. Filtering condition identifiers
    3. ALE Layers
    4. FWPM_FILTER_ENUM_TEMPLATE0 structure (fwpmtypes.h)
    5. FWP_FILTER_ENUM_TYPE enumeration (fwptypes.h)
    6. FWPM_FILTER0 structure (fwpmtypes.h)
    7. Filtering sublayer identifiers
    8. MSFT_NetFirewallRule class
    9. MSFT_NetFirewallRuleFilterByApplication class
    10. WFP Operation
    11. Filter Arbitration
    12. FWPS_CALLOUT_CLASSIFY_FN0 callback function (fwpsk.h)
    13. ALE Stateful Filtering
    14. FwpmFilterEnum0 function (fwpmu.h)
    15. FwpmFilterCreateEnumHandle0 function (fwpmk.h)
    16. FWPM_NET_EVENT_CLASSIFY_DROP2 structure (fwpmtypes.h)
    17. Logging (Windows Filtering Platform)
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.