By NHI Mgmt Group Editorial TeamDomain: Cyber SecuritySource: SemgrepPublished September 4, 2025

TL;DR: Cross-platform runtime gaps, build-system constraints, and Windows-specific file semantics can block local SAST delivery, according to Semgrep. The broader lesson is that developer-side security feedback only scales when tooling, packaging, and execution environments are treated as part of the governance problem, not just the scanner itself.


At a glance

What this is: This is a technical blog about making Semgrep run on Windows through JavaScript and WebAssembly, with the key finding that cross-platform support required changes in runtime assumptions, build tooling, and filesystem handling.

Why it matters: It matters to IAM and security practitioners because developer tooling only delivers value when it is deployable in the environments developers actually use, and local security feedback is part of the control surface for secure software delivery.

👉 Read Semgrep's technical breakdown of Windows support for its local SAST tool


Context

Cross-platform security tooling fails when the execution environment is treated as an implementation detail rather than a control requirement. In this case, Semgrep’s Windows gap was not about detection logic alone, but about whether developers could run the scanner locally in the environments where code is written, reviewed, and fixed. For security programmes, that same issue appears whenever access, verification, or policy checks exist only in CI and not at the point of use.

The identity angle is indirect but real: developer tooling is part of the broader security control plane, because the earlier a finding reaches a developer, the less likely it is to become an access, secrets, or supply chain problem downstream. Teams that depend on pre-commit checks, IDE extensions, or local policy enforcement need to think about portability, user experience, and operating-system variance as adoption constraints, not convenience issues.


Key questions

Q: How should security teams validate developer security tools across operating systems?

A: They should test the tool in the exact environments developers use, including native Windows, macOS, Linux, and any sanctioned fallback such as WSL or containers. Validation should cover file parsing, configuration persistence, output suppression, and startup performance. A control that only works in CI is useful, but it does not provide the same early feedback as local execution.

Q: Why do developer security tools fail when they rely on Unix assumptions?

A: Unix assumptions often hide dependencies on process spawning, signals, path layouts, newline handling, and device files such as /dev/null. When those assumptions move to Windows, tools can misread files, fail to persist state, or silently skip expected behaviour. The result is not just portability friction, but weaker security adoption because developers stop trusting the control.

Q: What do teams get wrong about local scanning versus CI scanning?

A: They often assume CI scanning is enough because it eventually catches issues. In practice, local scanning changes behaviour earlier by surfacing findings while code is being written, which improves remediation speed and reduces the number of defects that reach the pipeline. The right model is layered coverage, not a choice between one or the other.

Q: How should teams decide whether platform support is good enough for security tooling?

A: They should measure whether the tool can run without special exceptions, whether it preserves state correctly, and whether it behaves consistently across file systems and shells. If a platform needs a workaround that most developers will not use, the control is not truly available. That is a governance problem, not just an engineering inconvenience.


Technical breakdown

Why local SAST breaks when runtime assumptions change

Static application security testing tools often assume a fairly stable runtime, filesystem, and process model. Here, the challenge was not analysis quality but whether the scanner could execute natively on Windows without depending on WSL. That required moving from an OCaml and Unix-centric execution model to JavaScript and WebAssembly, then selectively limiting the language server surface area so only the necessary runtime behaviours had to be re-created. Practical implication: if a security control cannot run where developers work, its effectiveness drops sharply even if the detection logic is sound.

Practical implication: treat runtime portability as part of control design, not post-release packaging.

How build systems isolate native and web-friendly dependencies

The article’s most useful engineering lesson is the use of Dune virtual modules to choose between native and JavaScript-friendly implementations at build time. That matters because it avoids forcing one dependency graph to satisfy both execution targets. In this case, Lwt’s native path pulled in libev bindings that could not be transpiled, so the build had to separate interfaces from implementations cleanly. This is a pattern security teams should recognise in policy tooling too, where one control framework may need different adapters for IDE, CI, and server-side enforcement.

Practical implication: separate interfaces from implementations so one control can serve multiple execution targets.

Windows filesystem semantics can break security tooling silently

The article shows three Windows-specific behaviours that matter for developer security tools: newline handling, configuration location, and null device semantics. Each one is mundane in isolation, but together they determine whether a tool reads source files correctly, persists login state, and suppresses output without errors. The /dev/null equivalent issue is especially instructive because the failure was not obvious until runtime. For security engineering, these are the kinds of edge cases that turn a working control into a brittle one when environments differ.

Practical implication: test control behaviour against filesystem and path semantics, not only against application logic.


NHI Mgmt Group analysis

Cross-platform delivery is now part of security control effectiveness. A scanner that cannot run locally on Windows cannot support the same developer feedback loop that it provides on Linux or macOS. That shifts the question from feature completeness to control reachability, which is a governance issue as much as a technical one. For security teams, the lesson is to measure whether controls are available at the point of development, not only in central pipelines.

Build-time modularity is a governance enabler, not just a code-organisation choice. The use of virtual modules to swap runtime-specific dependencies shows how one product can preserve native builds while also supporting a different execution target. That pattern maps cleanly to broader security architecture: controls that need multiple operating contexts should expose a stable interface and vary only the implementation. Practitioners should design their tooling estate the same way.

Windows-specific edge cases expose the hidden assumptions behind developer security workflows. Line endings, config paths, and null-device behaviour look like minor portability bugs, but they determine whether the control produces reliable results or silent failure. That matters because security tooling loses authority quickly when developers see inconsistent behaviour across platforms. Teams should treat environment parity testing as part of security validation, not just QA.

Developer-side security adoption depends on latency, not just accuracy. The article’s emphasis on local IDE feedback reflects a broader reality: developers act on findings sooner when the control is available while they code. That shortens remediation delay and reduces the chance that insecure code, secrets, or risky access patterns survive until later pipeline stages. For the field, the operational question is no longer whether a tool can find issues, but whether it can fit the developer workflow with enough speed to change behaviour.

Platform support decisions increasingly shape whether security controls are governed or merely installed. A control that works only in CI can still be useful, but it does not fully participate in day-to-day developer decision-making. The implication for security programmes is to classify local execution support as a requirement for any tool that claims early feedback value. Practitioners should therefore evaluate portability, not just detection coverage, when they choose scanning and policy tooling.

What this signals

Local developer security controls increasingly need the same portability discipline that teams already expect from identity and access tooling. If findings only appear in CI, the organisation has moved detection later in the lifecycle, which weakens the practical value of the control even when coverage looks high on paper.

Feedback-latency debt: when a control only works after code reaches a shared pipeline, the organisation accumulates delay between issue introduction and remediation. For practitioners, that debt shows up as slower fixes, more context switching, and weaker confidence in whether the security tool is part of the developer workflow or merely adjacent to it.

Teams that support heterogeneous developer fleets should treat OS-specific validation as part of secure software delivery governance. The relevant question is not whether the scanner can be built once, but whether it can be trusted everywhere developers write code, including environments with different filesystem conventions, shells, and runtime constraints.


For practitioners

  • Validate security tooling on every developer platform Run scanners and IDE extensions on the same operating systems your engineers use, then record where local execution depends on WSL, container wrappers, or other workarounds. Include newline handling, config-path persistence, and null-device behaviour in the test plan, because those are the failure modes most likely to erode trust in the control.
  • Separate runtime adapters from security logic Design security tools so the core detection or policy engine is insulated from platform-specific I/O, process, and filesystem code. That lets you support native, browser, or transpiled execution paths without forking the control model itself, which reduces maintenance risk and makes deployment decisions easier.
  • Test for silent failure, not only exceptions Check whether your tooling writes state, reads files, and suppresses output correctly when the operating system behaves differently from Unix defaults. Silent failures are especially damaging in security workflows because they create the appearance of coverage while leaving developers without actionable feedback.
  • Make local feedback a formal control objective If your programme depends on pre-commit or IDE scanning, define local execution as a measurable requirement alongside CI coverage. That helps teams prioritise portability work, performance tuning, and environment parity before rollout gaps become adoption gaps.

Key takeaways

  • Semgrep’s Windows work shows that security tool effectiveness depends on platform reach, not only on detection quality.
  • The engineering constraints were in runtime portability, build selection, and filesystem semantics, which are the same kinds of hidden assumptions that break many control deployments.
  • Security teams should treat local execution, environment parity, and silent-failure testing as part of the control requirement for developer-facing tooling.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
NIST CSF 2.0PR.IP-1Portability and environment validation affect whether the control is actually deployable.
NIST SP 800-53 Rev 5SI-7The article is about reliable security tool behaviour under different runtime conditions.
CIS Controls v8CIS-16 , Application Software SecurityDeveloper-facing scanning sits inside secure software lifecycle controls.

Test tool integrity and correct operation across platforms before treating local scanning as production-ready.


Key terms

  • Static Application Security Testing: Static Application Security Testing is a method for finding security flaws by examining code, binaries, or configuration without executing the application. It is strongest when used early in development, where teams can fix issues before deployment and prevent avoidable defects from reaching production.
  • WebAssembly: WebAssembly is a compact binary format designed to run code efficiently in modern runtimes. Security tooling often uses it to extend portability, but the surrounding runtime still needs careful handling of filesystem, process, and platform-specific behaviour to avoid breakage.
  • Virtual Modules: Virtual modules let a build system define one interface and multiple interchangeable implementations. In practice, that allows a security tool to keep a stable contract while choosing platform-specific code paths at build time, which is useful when native and transpiled targets have different dependency constraints.
  • Feedback Latency: Feedback latency is the delay between introducing a security issue and surfacing a finding to the person who can fix it. Lower latency usually improves remediation, because developers can act while the change is still in context and before the issue spreads into later pipeline stages.

What's in the full article

Semgrep's full article covers the implementation detail this post intentionally leaves for the source:

  • How the OCaml to JavaScript path was assembled with js_of_ocaml and Emscripten for Windows support
  • Why Dune virtual modules let the team switch between native and JavaScript-friendly Lwt implementations
  • The exact Windows newline, HOME, and NUL handling fixes that were needed for the language server
  • The LLVM optimisation pass investigation that cut Wasm build times and made testing practical

👉 The full Semgrep post covers the cross-platform build path, Windows bug fixes, and performance debugging details

Deepen your knowledge

NHI Mgmt Group covers identity security, NHI governance, and agentic AI through independent research, practitioner guides, and the NHI Foundation Level course, the industry's only accredited NHI security programme. Explore nhimg.org for resources that connect identity governance to the broader security disciplines your programme depends on.
NHIMG Editorial Note
Published by the NHIMG editorial team on August 2, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org