{"record":{"id":"aab34f94c10e365b","repo":"crowdsecurity/crowdsec","slug":"obfuscator-produced-empty-output","errorCode":null,"errorMessage":"obfuscator produced empty output","messagePattern":"obfuscator produced empty output","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/challenge/js/cmd/initialbundle/main.go","lineNumber":89,"sourceCode":"\tr := wazero.NewRuntime(ctx)\n\tdefer r.Close(ctx)\n\n\tif _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {\n\t\treturn fmt.Errorf(\"instantiate wasi: %w\", err)\n\t}\n\n\tcompiled, err := r.CompileModule(ctx, wasmBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"compile obfuscator wasm: %w\", err)\n\t}\n\n\tobfuscated, err := obfuscate(ctx, r, compiled, source)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"obfuscate: %w\", err)\n\t}\n\n\tif obfuscated == \"\" {\n\t\treturn errors.New(\"obfuscator produced empty output\")\n\t}\n\n\tif err := writeGzip(outputPath, obfuscated); err != nil {\n\t\treturn fmt.Errorf(\"write %s: %w\", outputPath, err)\n\t}\n\n\tfmt.Fprintf(os.Stderr, \"initialbundle: input %d bytes -> obfuscated %d bytes -> compressed file written\\n\",\n\t\tlen(source), len(obfuscated))\n\n\treturn nil\n}\n\nfunc buildSourceBundle() (string, error) {\n\traw, err := os.ReadFile(challengeCodePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read %s: %w\", challengeCodePath, err)\n\t}\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/challenge/js/cmd/initialbundle/main.go#L71-L107","documentation":"In the initialbundle generator, after compiling and obfuscating the challenge JS, run() checks that the obfuscator returned a non-empty string. An empty result cannot be written as a usable bundle, so the tool fails with this error before writing the gzip output. This guards against the obfuscator silently producing nothing.","triggerScenarios":"obfuscate(ctx, r, compiled, source) returns err==nil but an empty string in run(), called from main.","commonSituations":"Obfuscator misconfiguration (options that strip all code); input source unexpectedly empty or a no-op after compilation; a version change in the obfuscator library changing its return conventions; piping the wrong stream into the obfuscator.","solutions":["Verify the obfuscator options — ensure no settings disable/minimize output to nothing.","Check that the esbuild-compiled input is non-empty before obfuscating; log its length.","Update/verify the obfuscator library version and its API usage.","Inspect the source map/entry selection so the compiled code actually reaches obfuscate()."],"exampleFix":"// before\nobfuscated, err := obfuscate(ctx, r, compiled, source)\nif err != nil { return err }\n// after: pre-validate input and output\nif compiled == \"\" { return errors.New(\"compiled input is empty\") }\nobfuscated, err := obfuscate(ctx, r, compiled, source)\nif err != nil { return err }\nif obfuscated == \"\" { return errors.New(\"obfuscator produced empty output\") }","handlingStrategy":"validation","validationCode":"if compiled == \"\" {\n    return errors.New(\"compiled JS input is empty before obfuscation\")\n}","typeGuard":null,"tryCatchPattern":"obfuscated, err := obfuscate(ctx, r, compiled, source)\nif err != nil {\n    return fmt.Errorf(\"obfuscate: %w\", err)\n}\nif obfuscated == \"\" {\n    return errors.New(\"obfuscator produced empty output\")\n}","preventionTips":["Sanity-check input length before each pipeline stage","Keep obfuscator options reviewed in version control","Pin the obfuscator library version","Add a CI check that the generated bundle is non-empty"],"tags":["build","javascript","obfuscation","tooling"],"backgroundTag":"empty-response-body","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}