By NHI Mgmt Group Editorial TeamBased on Semgrep: “LSP.js: Using Wasm and JavaScript to support OCaml on Windows” (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: Semgrep's Windows support effort shows that local SAST portability depends on runtime, build, and file-system assumptions that do not transfer cleanly across operating systems.

Why it matters: IAM, AppSec, and platform teams should treat developer-side security feedback as a deployment-governance problem, because environment friction determines whether controls reach developers before code is merged.


Context

Local static analysis only helps when it can run where developers actually work, and that means the control surface extends beyond scanning logic into packaging, runtime support, and operating system behaviour. When those assumptions are Unix-shaped, Windows developers lose early feedback and security review shifts later in the delivery chain.

This article is fundamentally about portability as a governance issue: if a tool cannot run consistently across developer environments, its value in pre-commit and IDE workflows is uneven by design. The identity angle is indirect but real, because developer endpoints and build pipelines shape where security policy is enforced and when.

For organisations standardising on Windows, the practical question is not whether a scanner exists in CI, but whether it can participate in the daily development loop without unsupported workarounds such as WSL.


Key questions

Q: How should teams handle local security tools when developers use Windows endpoints?

A: Treat Windows support as part of the control boundary, not a packaging afterthought. If a scanner only works in CI or through awkward workarounds, developers lose the early feedback loop that makes local enforcement valuable. The practical test is whether the tool runs predictably in the same environment where code is written and reviewed.

Q: Why do local SAST tools fail when they depend on Unix-specific runtime behaviour?

A: Because process management, filesystem semantics, and optimisation assumptions often differ by operating system. A tool that relies on fork, signals, or tail call optimisation may work in one runtime and collapse in another, which turns portability into a control reliability problem rather than a pure engineering issue.

Q: What do security teams get wrong about cross-platform developer tooling?

A: They often measure success by whether a binary exists, not whether the control behaves consistently across endpoints. If build-time dependencies, newline handling, profile paths, and runtime limits are not validated together, the scanner may be present but unreliable for the developers who need it most.

Q: What happens when security feedback shifts from the IDE to CI?

A: It arrives later, reaches fewer developers, and becomes harder to act on before code is merged. That weakens the preventive value of static analysis, because findings become gatekeeping signals instead of immediate coding guidance. Teams should keep CI scanning, but not use it as a substitute for local enforcement.


Technical breakdown

Why Unix assumptions break local security tooling on Windows

Semgrep's porting work shows a common portability trap: tools built around Unix process, filesystem, and signal semantics often assume a runtime that does not exist on Windows. Even when a language transpiler can emit JavaScript, the application may still depend on low-level behaviours such as fork, spawn, and blocking I/O patterns that are handled differently across operating systems. The result is not just a build problem, but a governance problem, because the tool no longer behaves consistently in the environments where developers write code and expect immediate feedback.

Practical implication: Treat cross-platform support as part of the control design, not as a post-build compatibility issue.

Why build-time selection matters when native and transpiled code diverge

The article's virtual-module approach highlights how build systems become security-enabling infrastructure. When one dependency tree works for native execution and another works for JavaScript, the project needs a way to choose the right implementation at build time rather than bundle both and hope runtime selection works. That distinction matters because native bindings, browser-safe shims, and JavaScript-compatible libraries often pull in incompatible dependencies. If the build system cannot cleanly isolate those paths, the scanner inherits unnecessary failure modes and unstable behaviour.

Practical implication: Use build-time gating to separate runtime-specific dependencies before they become deployment blockers.

Why file semantics and parser behaviour are part of the control boundary

Windows support exposed two classes of issues that security teams often underestimate: file-system differences and language-runtime behaviour. Newline handling changed parsing results, login state had to be stored in the Windows profile path, and the Windows null device required special handling. Separately, a recursive JSON parser that relied on tail call optimisation performed acceptably in OCaml but failed in JavaScript because the runtime could not optimise the same call pattern. These are not edge cases in a security product; they determine whether the control runs fast enough and reliably enough to be trusted by developers.

Practical implication: Validate parsers, paths, and runtime assumptions under the target operating system before claiming local enforceability.


NHI Mgmt Group analysis

Cross-platform security tooling is only as real as its weakest runtime assumption. The Windows work shows that local SAST is not simply a scanner feature, it is a delivery model that depends on operating system behaviour, build tooling, and file semantics. If the tool cannot execute predictably on the endpoint where code is written, the control boundary shifts back to CI, and early feedback is lost.

Build-system portability is a governance issue, not a release engineering detail. The choice to wrap native and JavaScript-friendly dependencies behind virtual modules is a practical reminder that control reliability depends on dependency isolation. In identity and access terms, this is the same pattern we see when runtime context determines whether a policy can actually be enforced.

Developer-experience friction changes control adoption faster than policy language does. Windows users had workarounds, but workarounds create uneven access to security feedback and delay remediation into later pipeline stages. That makes the control weaker in practice even if the scanner itself is technically sound.

Local enforcement should be judged by where it fails, not by where it is intended to run. If a control cannot survive common endpoint differences, it becomes a conditional control that only works for some teams. Practitioners should treat platform coverage as part of control effectiveness, not as an optional packaging concern.

What this signals

Portable control coverage is now a developer-experience requirement, not a luxury. When a security tool cannot execute cleanly on the endpoint platform in use, the organisation has effectively narrowed where policy can be enforced. That matters for release speed, but it matters more for control consistency, because teams start to depend on exceptions instead of standard paths.

Windows-specific file semantics are a useful reminder that control validation must include the operating system layer. Newline handling, profile storage, and null-device behaviour all sit outside the scanner's core logic, yet each one can break the developer workflow that makes local analysis worthwhile. Practitioners should test those assumptions before relying on local feedback as an enforcement mechanism.


For practitioners

  • Map endpoint coverage before mandating local SAST Check whether developers can run the scanner locally on the operating systems they actually use, including Windows, without unsupported workarounds like WSL.
  • Separate native and cross-platform dependency paths Use build-time selection or equivalent isolation so Windows-safe runtime code does not inherit incompatible native bindings or Unix-only libraries.
  • Test file and parser behaviour under the target OS Validate newline handling, null-device behaviour, profile-path storage, and parser recursion limits on the same operating system that developers use.
  • Treat CI-only scanning as a fallback, not the target model Preserve developer-side feedback for pre-commit and IDE workflows so security findings land before code reaches shared pipelines.

Key takeaways

  • Local SAST portability is limited by runtime and operating system assumptions, not just by scanner logic.
  • The Windows case shows that control effectiveness depends on whether developers can use it where they actually work.
  • Teams should validate endpoint coverage, dependency isolation, and file semantics before treating local security feedback as reliable.

Standards & Framework Alignment

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

MITRE ATT&CK addresses the attack and risk surface, while NIST CSF 2.0 and CIS Controls v8 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
NIST CSF 2.0PR.AA-05 — Access Permissions, Entitlements and AuthorizationsDeveloper tooling only works as a control when it is reachable in the actual endpoint environment.
PR.DS-01 — Data-at-rest data are protectedWindows newline, profile, and null-device handling affect how data is read and stored locally.
Recommendation — Validate that local security controls are usable on the endpoints and operating systems your developers actually use. Test file-handling behaviour on each supported platform so local data processing stays reliable.
CIS Controls v8CIS-7 — Continuous Vulnerability ManagementLocal SAST is a vulnerability-management control that must operate consistently across developer endpoints.
Recommendation — Extend vulnerability-management testing to developer machines and build paths, not just CI runners.
MITRE ATT&CKTA0007 — DiscoveryThe article discusses deep inspection of runtime behaviour and parser failure modes to expose implementation limits.
Recommendation — Use runtime and build-path discovery to identify where portability breaks across supported platforms.

Key terms

  • Cross-platform tool portability: The ability of a security or developer tool to run consistently across different operating systems and environments without changing its control outcome. Portability is not just compilation success. It also includes runtime behaviour, filesystem handling, dependency loading, and performance under the target platform.
  • Build-time dependency: A build-time dependency is any package, library, or component introduced while assembling software rather than in the original source tree. These dependencies can change the final security posture without appearing in code review, which is why image and pipeline scanning matter alongside repository analysis.
  • Runtime semantic gap: The difference between how code behaves in one execution environment and how the same code behaves in another. In security tooling, this gap often appears in process management, path handling, and parser performance. If untested, it can turn a working control into an unreliable one.
  • Local enforcement: The ability to make access and policy decisions within the operating environment rather than depending on a live call to a central service. This matters in disconnected deployments because identity assurance must continue even when network access is unreliable.

Deepen your knowledge

The NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, machine identity security, and secrets management. It helps practitioners connect identity control design to the broader security programme their teams operate.
NHIMG Editorial Note
Published by the NHIMG editorial team on August 2, 2026.
Updated on October 12, 2026.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org