Skip to content

Reference

Configuration reference

Every field in nebula.config.json — types, defaults, and what it does.

Nebula is driven by a JSON config file (nebula.config.json) passed with --config. This is the complete list of fields. All are optional except inputs; unknown keys produce a warning rather than being silently ignored.

{
  "inputs": ["bin/Release/net8.0/MyApp.dll"],
  "outputDirectory": "bin/Release/net8.0/obf",
  "preservePublicApi": true,
  "controlFlowObfuscation": true,
  "encryptStrings": true
}

Editions. The Free edition does identifier renaming, up to 2 encrypted strings and up to 2 control-flow methods. Everything else (unlimited strings/control-flow, method & resource encryption, anti-tamper, anti-debug, metadata hardening, constants, aggressive naming, cross-assembly rename, signing, PDB output, plugins) is Licensed; aggressive control-flow intensity and watermarking are Enterprise. See Editions.

Input & output

KeyTypeDefaultDescription
inputsstring[]— (required)Assembly path(s) to obfuscate. List all interdependent assemblies together for cross-consistent renaming — see Multiple assemblies.
outputDirectorystring<inputDir>/nebulatedWhere obfuscated assemblies, symbol maps and reports are written.
allowInPlaceboolfalseSafety guard: writing over the input assembly is refused unless this is true, so a mistyped path can’t destroy your source assembly.
copyRuntimeConfigbooltrueCopy each input’s *.runtimeconfig.json / *.deps.json next to the output so a framework-dependent app runs from the output folder.
verifyOutputbooltrueRe-check the transformed module for dangling references before writing and refuse to emit output that wouldn’t load. Leave on.
schemaVersionint1Config schema version, so older files get a clear upgrade warning.

Renaming

KeyTypeDefaultDescription
preservePublicApiboolfalseKeep public/protected type & member names; rename only internal/private. Turn on for a library referenced by code outside the run; off to rename everything eligible.
autoDetectbooltrueAutomatically preserve names required for correctness — reflection/serialization/DI/XAML targets and [Obfuscation]-marked members. Leave on.
includestring[][]Allowlist of type full names eligible for renaming. When non-empty, only these types (and their members) are renamed; everything else is preserved.
excludestring[][]Force-preserve names. A type full name preserves the type and all members; "Namespace.Type.Member" preserves one member.
excludeNamespacesstring[][]Force-preserve whole namespaces: any type whose namespace equals or starts with an entry (e.g. MyApp.Api) keeps its name and its members’.
renameResourcesboolfalseRename embedded resource names and update references (incl. type-associated .resources so ResourceManager still resolves).
aggressiveNamingboolfalseUse hard-to-read Unicode-confusable identifiers instead of short ASCII names. Still deterministic and collision-free.
crossAssemblyRenameboolfalseIn a multi-assembly run, rename types/members shared across the input assemblies and rewrite every cross-assembly reference. Requires all referencing assemblies to be inputs — see Multiple assemblies.

String encryption

KeyTypeDefaultDescription
encryptStringsboolfalseEncrypt string literals in IL and decrypt at runtime with a per-build key.
encryptStringsIncludestring[][]Allowlist of exact literals to encrypt. When non-empty, only these are encrypted. Discover them with nebula inspect --strings.
excludeStringsstring[][]Exact literals to leave un-encrypted (e.g. license text).

Control flow & code protection

KeyTypeDefaultDescription
controlFlowObfuscationboolfalseFlatten method control flow into a dispatcher state machine. Works for all method shapes, including try/catch/finally (the top level and each try body are flattened; nested handlers are kept atomic). Anything not provably safe to move is left intact.
controlFlowIntensitystring"normal"none / light / normal / aggressive — roughly 0 / 25 / 60 / 100 % of eligible methods when no explicit include list is given. aggressive is Enterprise.
controlFlowIncludestring[][]Allowlist of methods to flatten, by Namespace.Type.Method. When non-empty, only these are transformed. Discover names with nebula inspect --methods.
controlFlowExcludestring[][]Methods to skip, by Namespace.Type.Method.
obfuscateConstantsboolfalseReplace integer literal loads with an equivalent XOR expression decoded inline at runtime.
encryptMethodsboolfalseStrongest code protection: encrypt a method’s whole IL and re-emit it at call time via the Nebula.Runtime helper (copied next to the output). Covers static, non-generic methods without exception handlers or by-ref/pointer parameters.
encryptResourcesboolfalseEncrypt embedded resources read via Assembly.GetManifestResourceStream(string) and decrypt on demand. (.resources for ResourceManager/WinForms/satellite are skipped.)

Anti-tamper & anti-debug

KeyTypeDefaultDescription
antiTamperboolfalseInject a load-time integrity check (SHA-256 of the written image) that reacts if the file was modified after obfuscation. Stops casual patching.
antiTamperReactionstring"terminate"On mismatch: terminate (FailFast), throw, exit, or callback.
antiTamperCallbackstringnullNamespace.Type.Method of a static, parameterless method to call when reaction is callback (must be preserved so it resolves).
antiDebugboolfalseInject a managed-debugger detection check that runs on module load. Off by default so it never hinders your own QA builds.
antiDebugReactionstring"throw"On a detected debugger: throw, terminate, exit, or callback.
antiDebugCallbackstringnullCallback method for the anti-debug callback reaction.

Metadata & symbols

KeyTypeDefaultDescription
metadataHardeningboolfalseStrip compile-time-only metadata decompilers use but the CLR doesn’t need (nullable annotation attributes, etc.), preserving runtime-critical metadata.
pdbModestring"none"none discards debug symbols (max protection); obfuscated emits a PDB matching the obfuscated IL for your private crash analysis.

Signing

KeyTypeDefaultDescription
strongNameKeyFilestringnullPath to a .snk to re-sign the output (renaming invalidates any existing strong name). Relative paths resolve against the config file.
strongNameKeyEnvVarstringnullName of an env var holding a base64-encoded .snk, so keys need not live in the config. Takes precedence over strongNameKeyFile.
delaySignboolfalseDelay-sign only (embed the public key, leave room for a later signature).
authenticodeCertFilestringnull.pfx to Authenticode-sign the output (after strong-name signing). Requires signtool / Windows SDK.
authenticodeCertPasswordstringnullPassword for the .pfx — prefer supplying via an env var over inline text.
authenticodeCertThumbprintstringnullSHA-1 thumbprint of a cert in the Windows store to sign with (alternative to a .pfx).
authenticodeTimestampUrlstringnullOptional RFC-3161 timestamp URL for Authenticode signing.

Licensing, incremental & extensibility

KeyTypeDefaultDescription
licenseFilestringnullPath to a license file. When omitted, the NEBULA_LICENSE env var and default locations are checked. Without a valid license, the Free edition runs.
seedMapFilestringnullA previous run’s .symbols.json for incremental/seeded obfuscation: unchanged members reuse their previous obfuscated names; only added/changed members get new names.
pluginsstring[][]Paths to plugin assemblies providing extra IObfuscationPass implementations. Each is appended to the pipeline.
watermarkstringnullEnterprise. A per-customer identifier embedded (obfuscated) into the output so a leaked binary traces back to the customer. Read it with nebula watermark --read.

A fuller example

{
  "inputs": ["out/MyApp.dll", "out/MyApp.Core.dll"],
  "outputDirectory": "out/obf",
  "preservePublicApi": false,
  "crossAssemblyRename": true,
  "encryptStrings": true,
  "controlFlowObfuscation": true,
  "controlFlowIntensity": "normal",
  "obfuscateConstants": true,
  "antiTamper": true,
  "metadataHardening": true,
  "strongNameKeyEnvVar": "MYAPP_SNK_BASE64",
  "pdbMode": "none"
}

See also: CLI reference · MSBuild & CI · Multiple assemblies.