Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
••••••••••••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Nix + pnpm + Parcel + lydell/elm-safe-virtual-dom

On January 12th, Flavio Corpa (kvothe) reached out on the #nix channel of the Elm Slack asking for help to make Nix and Parcel work together since he really wanted to use Simon Lydell's elm-safe-virtual-dom in his projects. Presumably, he…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

On January 12th, Flavio Corpa (kvothe) reached out on the #nix channel of the Elm Slack asking for help to make Nix and Parcel work together since he really wanted to use Simon Lydell's elm-safe-virtual-dom in his projects. Presumably, he read Juliano Solanho's (omnibs) post, on NoRedInk's blog, about adopting lydell/elm-safe-virtual-dom that got him excited about the prospects. He had some issues with browsers and auto translation of content that lydell/elm-safe-virtual-dom might be able to fix.



I had recently finished rewriting elm2nix and was on the lookout for opportunities to apply my freshly acquired knowledge so I felt it was fortuitous timing for me that his request was made when I was most able to help.



I approached my solution in two parts:





  1. Rewriting the project to use dwayne/elm2nix.


  2. Adopting lydell/elm-safe-virtual-dom.



If you have Nix installed, you can try out the final result by executing:




nix run github:dwayne/elm-countries-quiz






Let's get into it.






Rewriting the project to use dwayne/elm2nix



In the PR, for this part, I highlighted all the noteworthy changes so I won't rehash them here but I'd make a few comments.






Name your development shell



nix develop doesn't give you any indication that you're in your development shell so to improve the situation you can give the shell a name and use it in your primary prompt string.




devShells.default = pkgs.mkShell {
name = "elm-countries-quiz";

shellHook = ''
export PS1="($name)\n$PS1"
'';
}






This way, when you enter your development shell the prompt changes and there's visual indication that you're in a different environment.






Use the programming language's package manager



In your development environment I found it's best to use Nix to install the programming language's package management tools and then use those tools to manage the project. In this way Nix becomes a way to manage your project's system dependencies while you continue to use the tools that are familiar to you from your programming language's ecosystem.




devShells.default = pkgs.mkShell {
packages = [
elm2nix.packages.${system}.default
pkgs.elmPackages.elm
pkgs.elmPackages.elm-format
pkgs.elmPackages.elm-json
pkgs.elmPackages.elm-test-rs
pkgs.elmPackages.elm-review
pkgs.nodejs_24
pkgs.pnpm
];

shellHook = ''
pnpm install --silent
'';
}






For e.g. anyone entering the development shell above gets access to elm2nix, elm, elm-format, elm-json, elm-test-rs, elm-review, node, npm, and pnpm.



In particular, you can now use pnpm to manage your project's dependencies like you would if you installed it in the traditional way. As a bonus, I run pnpm install --silent whenever you enter the development shell so that's one less thing you need to do to start working on the project.






Use aliases/functions to make it easier to perform common tasks



In your shellHook you can create Bash aliases or define Bash functions to provide shortcuts to the common tasks you find yourself repeating as you work on your project.




devShells.default = pkgs.mkShell {
shellHook = ''
export PROJECT_ROOT="$PWD"

f () {
elm-format \
"$PROJECT_ROOT"/src \
"$PROJECT_ROOT"/review/src \
"$PROJECT_ROOT"/tests \
--yes
}

r () {
elm-review
}

t () {
elm-test-rs "$PROJECT_ROOT"/tests/*.elm
}

c () {
rm -rf "$PROJECT_ROOT"/{.parcel-cache,dist,elm-stuff,node_modules}
}

s () {
pnpm start
}

echo "Type 'f' to run elm-format"
echo "Type 'r' to run elm-review"
echo "Type 't' to run elm-test-rs"
echo "Type 'c' to remove build artifacts"
echo "Type 's' to start the development server"
'';
}






N.B. I used to use aliases but after learning that for almost every purpose, shell functions are preferable to aliases I've switched to functions in my recent projects.






Building with pnpm and Parcel in Nix



pnpm and Parcel are used to build the application in nix/app.nix.



The file is structured using the conventional callPackage pattern. It uses stdenv.mkDerivation with specific attributes to be able to use pnpm and parcel.



I use file sets to specify the minimum files needed for the build to work. This ensures that rebuilds are only ever considered when those files change.



To work with pnpm I followed the advice in the pnpm section of the Nixpkgs Reference Manual. In particular, I used the fetchPnpmDeps function to create the pnpm store derivation corresponding to the project's pnpm-lock.yaml. The setup hook pnpmConfigHook prepares the build environment to install the pre-fetched dependencies.



To ensure the Elm compiler could work fully offline I use the prepareElmHomeScript function, from dwayne/elm2nix, to create a local Elm cache.



Finally, pnpm build invokes parcel build index.html which builds the project and places the generated files in the dist directory which I copy over to the current derivation's output directory to successfully complete the process.






Adopting lydell/elm-safe-virtual-dom



Simon Lydell does an excellent job explaining his project in its README. The tl;dr is that it's a robust virtual DOM for Elm that makes your application, among other things, resilient against browser extensions that mutate the DOM independent of Elm. One of the things this enables is browser-based translations, the very feature that kvothe wanted working with his project.



To adopt lydell/elm-safe-virtual-dom you have to patch core Elm libraries and get the Elm compiler to use the patched versions.






How it works



The first major thing I did was to create derivations of the patched core Elm libraries whose output directories were structured in a very specific way.



For e.g. lydell/browser is supposed to replace elm/browser 1.0.2 so the output produced by nix/elm-safe-virtual-dom/lydell-browser.nix looks as follows:




$ nix build github:dwayne/elm-countries-quiz#lydellBrowser -L
$ tree result
result
└── elm
└── browser
└── 1.0.2
├── elm.json
└── src
├── Browser
│   ├── AnimationManager.elm
│   ├── Dom.elm
│   ├── Events.elm
│   └── Navigation.elm
├── Browser.elm
├── Debugger
│   ├── Expando.elm
│   ├── History.elm
│   ├── Main.elm
│   ├── Metadata.elm
│   ├── Overlay.elm
│   └── Report.elm
└── Elm
└── Kernel
├── Browser.js
├── Browser.server.js
└── Debugger.js






i.e. it gets mapped to the core library it replaces and the directory structure is exactly what you'd find in the Elm cache under $ELM_HOME/0.19.1/packages. But, the contents are precisely that of lydell/browser.



nix/elm-safe-virtual-dom/lydell-virtual-dom.nix and nix/elm-safe-virtual-dom/lydell-html.nix work in a similar way. The pattern they all use was abstracted into a mkPatch builder in nix/elm-safe-virtual-dom/patch.nix.



Once you have derivations with outputs structured in that way and you know where to find the Elm cache it's a simple matter to remove the old package and replace it with the patched version in the Elm cache. That's what nix/elm-safe-virtual-dom/install-patch-script.nix does. One interesting thing to note is how I used the patched derivation's passthru attribute to get a hold of the path in which the package would be stored in the Elm cache. I use the path to remove the old package and to copy in the patched version.



nix/elm-safe-virtual-dom/patches.nix installs all the required patches. This is used by both nix/app.nix and nix/elm.nix, after the local Elm cache has been created, to install the patched versions of the packages.



N.B. The full details are available in this PR.



As you can imagine, this technique can be generalized to patch any published Elm package in any way you desire but I'm getting ahead of myself and will probably say more on that in a future post.






Further reading








Subscribe to my newsletter



If you're interested in improving your skills with Elm then I invite you to subscribe to my newsletter, Elm with Dwayne. To learn more about it, please read this announcement.

1. Sofort-Triage & Abwehrmaßnahmen

SOC Incident Playbook: Remote Code Execution (RCE) Defense
Syntax validiert (0 Fehler)
title: Detect Exploitation - Nix + pnpm + Parcel + lydell/elm-safe-virtual-dom
id: 29623bf9-1ae1-4261-9304-49050c3d630b
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-25
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-25"
        description = "YARA Signature for "
    strings:
        $str = "Nix + pnpm + Parcel + lydell/e" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("Nix  pnpm  Parcel  lydellelm-safe-virtua")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*Nix  pnpm  Parcel  lydellelm-safe-virtua*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "Nix  pnpm  Parcel  lydellelm-safe-virtua"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc

2. Cyber Threat Intelligence & Forensik

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Nix + pnpm + Parcel + lydell/elm-safe-vi.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Nix + pnpm + Parcel + lydell/elm-safe-virtual-dom

Thematisch verwandte Begriffe: pnpm, Parcel, lydellelmsafevirtualdom · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-87722 | Uncontrolled Resource Consumption (CWE-400 / CWE-1333) in regex search q…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...
↗ Original-Quelle