होस्ट-साइड टेम्पलेट सब्स्टिट्यूशन
सर्वर पर रेंडर की गई वैल्यूज़ (जैसे Go html/template के `{{ .Field }}` एक्सप्रेशन) को ऑब्फ़स्केशन पाइपलाइन तोड़े बिना VM-ऑब्फ़स्केटेड JavaScript में डालें।
समस्या
आपका बैकएंड (Go, Rails, Django, PHP, …) एक ऐसी JavaScript फ़ाइल सर्व करता है जिसकी सामग्री हर रिक्वेस्ट पर आंशिक रूप से
रेंडर होनी चाहिए — कोई API एंडपॉइंट, फ़ीचर फ़्लैग्स की सूची, शुरुआती स्टेट का ब्लॉब, कोई बिल्ड आईडी, कोई nonce। आप उस JS को
vmObfuscation: true से ऑब्फ़स्केट करते हैं, लेकिन आपको यह भी चाहिए कि ऑब्फ़स्केशन पूरा होने के बाद टेम्पलेट इंजन
ऑब्फ़स्केटेड आउटपुट में प्लेसहोल्डर्स की जगह वैल्यू भर दे। अगर प्लेसहोल्डर्स VM बाइटकोड में समा जाएँ (स्ट्रिंग्स और
आइडेंटिफ़ायर्स के लिए यही डिफ़ॉल्ट है), तो टेम्पलेट इंजन के पास बदलने को कुछ बचता ही नहीं।
मैं कौन-सा विकल्प चुनूँ?
| सर्वर वैल्यू है… | उपयोग करें |
|---|---|
| एक कच्चा JS एक्सप्रेशन (ऐरे लिटरल, ऑब्जेक्ट, नंबर, बूलियन, फ़ंक्शन कॉल) | reservedNames + आइडेंटिफ़ायर प्लेसहोल्डर |
| एक स्ट्रिंग, और टेम्पलेटिंग डिलिमिटर्स आपके नियंत्रण में हैं | reservedStrings + टेम्पलेट-लिटरल प्लेसहोल्डर |
एक स्ट्रिंग, और टेम्पलेट इंजन कुछ ख़ास डिलिमिटर्स पर मजबूर करता है (जैसे Go का {{ .Field }}) | reservedStrings + स्ट्रिंग या टेम्पलेट-लिटरल प्लेसहोल्डर |
पैटर्न 1 — आइडेंटिफ़ायर प्लेसहोल्डर के साथ reservedNames
किसके लिए सबसे अच्छा: कच्चे JS एक्सप्रेशन (ऐरे, ऑब्जेक्ट, नंबर, …) डालने के लिए, जहाँ कोट-एस्केपिंग की कोई चिंता न हो।
एक ऐसा विशिष्ट आइडेंटिफ़ायर चुनें जो असली कोड से कभी न टकराए, उसका सीधे संदर्भ दें, और reservedNames में उससे मेल खाता एक
regex जोड़ें। VM ऑब्फ़स्केशन के तहत यह आइडेंटिफ़ायर reserved-expressions ऐरे से होकर जाता है और आउटपुट में ज्यों का त्यों
दिखाई देता है।
सोर्स
(function () {
var initialState = __INITIAL_STATE__;
bootstrap(initialState);
})();
ऑब्फ़स्केटर विकल्प
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedNames: ['^__INITIAL_STATE__$']
});
ऑब्फ़स्केशन के बाद
आउटपुट में कहीं आपको इस तरह का एक reserved-expressions ऐरे मिलेगा:
let _r = [__INITIAL_STATE__, /* …other entries… */];
__INITIAL_STATE__ टोकन आइडेंटिफ़ायर के नाम बदलने से बच जाता है और VM बाइटकोड में नहीं समाता।
होस्ट-साइड सब्स्टिट्यूशन (Go उदाहरण)
tpl := template.Must(template.New("obf.js").Parse(obfuscated))
tpl.Execute(w, map[string]any{
"InitialState": map[string]any{"user": "alice", "theme": "dark"},
})
…जहाँ आपका Go टेम्पलेट इस टोकन की जगह एक कच्चा JS एक्सप्रेशन रख देता है:
{{ `__INITIAL_STATE__` }} → {{ .InitialState | toJSON }}
परिणाम:
let _r = [{"user":"alice","theme":"dark"}, /* … */];
न कोट, न एस्केपिंग — डाली गई वैल्यू को JS इंजन एक साधारण एक्सप्रेशन की तरह पार्स करता है।
पैटर्न 2 — टेम्पलेट-लिटरल प्लेसहोल्डर के साथ reservedStrings
किसके लिए सबसे अच्छा: Go / Jinja शैली के टेम्पलेट इंजन, जिन्हें {{ .Field }} जैसे डिलिमिटर चाहिए और जो बैकटिक्स में
लपेटे जाने पर संयोगवश वैध JS टेक्स्ट बन जाते हैं।
प्लेसहोल्डर एक सिंगल-क्वासी, बिना इंटरपोलेशन वाले टेम्पलेट लिटरल के अंदर रहता है। VM ऑब्फ़स्केशन के तहत यह reserved-expressions ऐरे से होकर जाता है और आउटपुट में कच्चा बैकटिक रूप बरकरार रहता है।
सोर्स
(function () {
var featureFlags = JSON.parse(`{{.Config.FeatureFlags}}`);
applyFlags(featureFlags);
})();
Obfuscator options
UI
To reserve the {{.Config.FeatureFlags}} placeholder from the source above, add this regex to the Reserved Strings
field - with single backslashes. The UI stores the value verbatim, so unlike in JS code the backslashes are not
doubled:
\{\{[^}]+\}\}

API
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
After obfuscation
let _r = [`{{.Config.FeatureFlags}}`, /* … */];
The placeholder is preserved byte-for-byte, including the surrounding backticks.
Host-side substitution
Replace {{.Config.FeatureFlags}} with a valid JSON string - it will sit inside backticks at runtime, which do not
require inner-quote escaping:
flagsJSON, _ := json.Marshal(config.FeatureFlags) // e.g. {"newCheckout":true,"darkMode":false}
out := strings.ReplaceAll(obfuscated, "{{.Config.FeatureFlags}}", string(flagsJSON))
At runtime: JSON.parse(`{"newCheckout":true,"darkMode":false}`) - works.
Pattern 3 - reservedStrings with a quoted string placeholder
Best for: source code that must stay in ES5 (no template literals), or cases where the surrounding API expects a regular string literal.
The placeholder is a single- or double-quoted string literal. Under VM obfuscation it routes through the
reserved-strings array, which is emitted as a JSON.stringify-serialized JS array - always double-quoted regardless
of the input quote style.
Source
(function () {
var tags = JSON.parse("{{.Page.Tags}}");
renderTags(tags);
})();
Obfuscator options
UI
To reserve the {{.Page.Tags}} placeholder from the source above, add this regex to the Reserved Strings field -
with single backslashes. The UI stores the value verbatim, so unlike in JS code the backslashes are not doubled:
\{\{[^}]+\}\}

API
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
After obfuscation
var _rs = ["{{.Page.Tags}}", /* … */];
Host-side substitution
Because the placeholder sits inside a double-quoted JS string, the injected JSON payload must have its inner "
characters escaped with \":
raw, _ := json.Marshal(page.Tags) // e.g. ["news","tech","release"]
// Escape " for embedding inside a JS double-quoted string.
escaped := strings.ReplaceAll(string(raw), `"`, `\"`)
out := strings.ReplaceAll(obfuscated, "{{.Page.Tags}}", escaped)
Resulting output:
var _rs = ["[\"news\",\"tech\",\"release\"]", /* … */];
At runtime: JSON.parse("[\"news\",\"tech\",\"release\"]") → ["news","tech","release"].
If you forget the escaping, the browser will see unbalanced quotes and throw a SyntaxError. Pattern 2 sidesteps this
entirely by using backticks.
Multiple placeholders in one program
All three patterns compose. A single reservedStrings regex with an alternation can match every placeholder shape your
template engine emits:
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
reservedNames: ['^__INITIAL_STATE__$'],
reservedStrings: ['\\{\\{[^}]+\\}\\}']
});
You can mix identifier placeholders (for raw JS values) and string placeholders (for rendered JSON) in the same source - pick per-placeholder based on what the server will actually inject.
Compatibility notes
- Don't reuse placeholders across identifiers and strings. A reserved name like
__TOKEN__and a reserved string matching__TOKEN__describe two different code paths (reserved-expressions array vs. reserved-strings array). Use distinct textual shapes for each - for example, anUPPER_SNAKEconvention for identifier placeholders and a delimiter-wrapped shape ({{ ... }},%{...},<<<...>>>) for string placeholders. That way a bug in one regex can't silently match the other. reservedStringsregexes run against raw string values. The regex is matched against the runtime value of the string, not the source text.\{\{[^}]+\}\}matches strings that contain{{.something}}(or any other{{...}}shape). If your placeholder might be wrapped in extra content ("prefix-{{.Field}}-suffix"), the regex still matches but the whole string is preserved - plan your substitution accordingly.- Works with any templating engine. Although the examples use Go
text/templatesyntax, nothing in the javascript-obfuscator integration is Go-specific. Anything that can do a string-level replacement on the obfuscator's output will work: Rails ERB, Django, PHP short-tags, sed in a CI pipeline, etc. Choose delimiters that your engine emits naturally and that don't collide with real JS syntax.
