Sostituzione di template lato host
Inserisci valori renderizzati dal server (ad esempio segnaposto `{{ .Field }}` in stile template Go) in JavaScript offuscato con la VM senza compromettere la pipeline di offuscamento.
Il problema
Il tuo backend (Go, Rails, Django, PHP, …) serve un file JavaScript il cui contenuto deve essere in parte renderizzato
a ogni richiesta: un endpoint API, un elenco di feature flag, un blob di stato iniziale, un id di build, un nonce. Offuschi il
JS con vmObfuscation: true, ma hai anche bisogno che il motore di template sostituisca i segnaposto nell'output offuscato
dopo la fine dell'offuscamento. reservedNames e reservedStrings mantengono un segnaposto visibile nell'output,
così che possa essere sostituito. Senza di essi, un segnaposto stringa viene assorbito nel bytecode della VM e un segnaposto identificatore
viene emesso in più punti riscritti, quindi il motore di template non trova nulla da sostituire oppure rompe l'output.
Valuta di caricare i valori come dati
Se puoi, evita del tutto di modificare l'output protetto: carica la configurazione di runtime come dati prima che venga eseguito il bundle
protetto. Tienila in uno script separato o recuperala da un endpoint autenticato. In questo modo l'output protetto resta intatto e
vmSelfDefending può rimanere attivo. I dati consegnati a un browser sono comunque visibili a quel browser.
Usa gli schemi seguenti quando i valori devono davvero essere sostituiti nel file offuscato.
Una nota sugli esempi in Go: eseguono una semplice sostituzione di stringhe (strings.ReplaceAll / strings.NewReplacer) sull'output
offuscato e gestiscono autonomamente l'escaping, mostrato per ciascuno schema. Non passano attraverso il pacchetto html/template di Go,
che applicherebbe in aggiunta il proprio escaping contestuale per JavaScript, eseguendo un doppio escaping del contenuto. Se esegui il rendering
tramite html/template, elimina l'escaping manuale e lascia che il motore esegua l'escaping una sola volta.
Quale opzione scegliere?
| Il valore del server è… | Usa |
|---|---|
| Un valore JS grezzo (array, oggetto, numero, booleano: qualsiasi valore JSON) | Schema 1 - reservedNames + segnaposto identificatore |
| Una stringa (il caso comune: JSON renderizzato, un id di build, un nonce) | Schema 2 - reservedStrings + segnaposto template literal |
| Una stringa, quando il codice deve restare ES5 o l'API circostante richiede un letterale stringa tra virgolette | Schema 3 - reservedStrings + segnaposto stringa tra virgolette |
La sostituzione dopo l'offuscamento è incompatibile con vmSelfDefending: true. Consulta le
Note di compatibilità alla fine di questa ricetta.
Schema 1 - reservedNames con un segnaposto identificatore
Ideale per: inserire espressioni JS grezze (array, oggetti, numeri, …) senza alcun problema di escaping delle virgolette.
Scegli un identificatore distintivo che non entri mai in collisione con il codice reale, fai riferimento direttamente a esso e inserisci in reservedNames una regex
che lo riconosca. Con l'offuscamento VM, l'identificatore passa attraverso l'array delle espressioni riservate e
compare così com'è nell'output, ad esempio:
Sostituisci l'identificatore con un'espressione completa serializzata in JSON. Non incollare il valore tra virgolette o backtick:
l'identificatore non si trova all'interno di un letterale stringa, quindi il valore inserito viene analizzato dal motore JS come una normale
espressione. Usa un serializzatore affidabile, esegui l'escape di < quando lo script è incorporato in HTML e testa valori che contengono
virgolette, backslash, ritorni a capo, backtick e ${...}.
Schema 2 - reservedStrings con un segnaposto template literal
Ideale per: motori di template in stile Go / Jinja che richiedono delimitatori come {{ .Field }}, che risultano essere testo JS
valido quando racchiusi tra backtick.
Il segnaposto si trova all'interno di un template literal con un solo quasi e senza interpolazioni. Con l'offuscamento VM passa attraverso l'array delle espressioni riservate, preservando nell'output la forma grezza con i backtick.
Sorgente
Opzioni dell'offuscatore
Interfaccia
Per riservare il segnaposto {{.Config.FeatureFlags}} del sorgente qui sopra, aggiungi questa regex al campo Reserved Strings,
con backslash singoli. L'interfaccia memorizza il valore così com'è, quindi, a differenza del codice JS, i backslash non vengono
raddoppiati:

API
Dopo l'offuscamento
Il segnaposto viene preservato byte per byte, compresi i backtick che lo circondano.
Sostituzione lato host
Sostituisci {{.Config.FeatureFlags}} con una stringa JSON sottoposta a escape per un template literal. I backtick non richiedono l'escape
delle " interne, ma un backslash, un backtick o ${ all'interno del payload modificherebbero o chiuderebbero comunque il letterale, quindi esegui l'escape
di questi tre:
Durante l'esecuzione: JSON.parse(`{"newCheckout":true,"darkMode":false}`) funziona.
Perché preferire i template literal alle virgolette singole o doppie per i valori stringa? I backtick non richiedono l'escape di "
all'interno del payload JSON. Questo è importante perché la maggior parte dei valori renderizzati dal server è JSON, e il JSON è pieno di virgolette
doppie. Con un segnaposto tra virgolette doppie dovresti eseguire l'escape di ogni " interna (vedi lo Schema 3); con i backtick
il payload richiede solo l'escape dei rari backslash, backtick e ${.
Schema 3 - reservedStrings con un segnaposto stringa tra virgolette
Ideale per: codice sorgente che deve restare in ES5 (senza template literal), o casi in cui l'API circostante si aspetta un normale letterale stringa.
Il segnaposto è un letterale stringa tra virgolette singole o doppie. Con l'offuscamento VM passa attraverso l'array
delle stringhe riservate, che viene emesso come array JS serializzato con JSON.stringify, sempre tra virgolette doppie indipendentemente
dallo stile di virgolette dell'input.
Sorgente
Opzioni dell'offuscatore
Interfaccia
Per riservare il segnaposto {{.Page.Tags}} del sorgente qui sopra, aggiungi questa regex al campo Reserved Strings,
con backslash singoli. L'interfaccia memorizza il valore così com'è, quindi, a differenza del codice JS, i backslash non vengono raddoppiati:

API
Dopo l'offuscamento
Sostituzione lato host
Poiché il segnaposto si trova all'interno di una stringa JS tra virgolette doppie, il payload JSON inserito deve avere i backslash e
le " interne sottoposti a escape:
Output risultante:
Durante l'esecuzione: JSON.parse("[\"news\",\"tech\",\"release\"]") → ["news","tech","release"].
Se dimentichi l'escape, il browser vedrà virgolette sbilanciate e genererà un SyntaxError. Lo Schema 2 evita del tutto
le virgolette doppie usando i backtick.
Più segnaposto in un unico programma
Tutti e tre gli schemi si possono combinare. Una singola regex reservedStrings con un'alternanza può riconoscere ogni forma di segnaposto emessa dal tuo
motore di template, in questo caso sia lo stile {{ .Field }} sia lo stile %{ .Field }:
Puoi combinare nello stesso sorgente segnaposto identificatore (per valori JS grezzi) e segnaposto stringa (per JSON renderizzato), scegliendo per ciascun segnaposto in base a ciò che il server inserirà effettivamente.
Note di compatibilità
vmSelfDefending rompe la sostituzione dopo l'offuscamento
VM Self Defending rileva qualsiasi modifica all'output offuscato dopo la build, compresa una legittima sostituzione di template, e il codice protetto allora si rifiuta di funzionare.
Se ti affidi alla sostituzione di template lato host, imposta vmSelfDefending: false. Lascia disattivato anche selfDefending:
non ha effetto con l'offuscamento VM, ma senza la VM vieta anch'esso qualsiasi modifica all'output.
Suggerimenti sui segnaposto
- Non riutilizzare gli stessi segnaposto per identificatori e stringhe. Un nome riservato come
__TOKEN__e una stringa riservata che corrisponde a__TOKEN__descrivono due percorsi di codice diversi (array delle espressioni riservate e array delle stringhe riservate). Usa forme testuali distinte per ciascuno: ad esempio, una convenzioneUPPER_SNAKEper i segnaposto identificatore e una forma racchiusa tra delimitatori ({{ ... }},%{...},<<<...>>>) per i segnaposto stringa. In questo modo un errore in una regex non può corrispondere silenziosamente all'altra. - Le regex di
reservedStringsvengono applicate ai valori grezzi delle stringhe. La regex viene confrontata con il valore di runtime della stringa, non con il testo sorgente.\{\{[^}]+\}\}riconosce le stringhe che contengono{{.something}}(o qualsiasi altra forma{{...}}). Se il tuo segnaposto può essere circondato da altro contenuto ("prefix-{{.Field}}-suffix"), la regex corrisponde comunque, ma viene preservata l'intera stringa: pianifica la sostituzione di conseguenza. - Funziona con qualsiasi motore di template. Anche se gli esempi usano la sintassi di Go, nulla nell'integrazione di javascript-obfuscator è specifico di Go. Qualsiasi strumento in grado di eseguire una sostituzione a livello di stringa sull'output dell'offuscatore funzionerà: Rails ERB, Django, i tag brevi di PHP, sed in una pipeline di CI e così via. Scegli delimitatori che il tuo motore emette in modo naturale e che non entrino in collisione con la sintassi JS reale.
