{"record":{"id":"507f620f27434a54","repo":"icsharpcode/ILSpy","slug":"invalid-baml-signature-length","errorCode":null,"errorMessage":"Invalid BAML signature length.","messagePattern":"Invalid BAML signature length\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"ICSharpCode.BamlDecompiler/Baml/BamlReader.cs","lineNumber":71,"sourceCode":"\t\t\t\t\treturn false;\r\n\t\t\t\tvar sig = new string(rdr.ReadChars(len));\r\n\t\t\t\treturn sig == MSBAML_SIG;\r\n\t\t\t}\r\n\t\t\tfinally\r\n\t\t\t{\r\n\t\t\t\tstr.Position = pos;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tstatic string ReadSignature(Stream str)\r\n\t\t{\r\n\t\t\tvar rdr = new BinaryReader(str, Encoding.Unicode);\r\n\t\t\tuint len = rdr.ReadUInt32();\r\n\t\t\t// len is read straight from the file, before the MSBAML_SIG check below. The only\r\n\t\t\t// accepted signature is the fixed-length \"MSBAML\", so reject any other length here\r\n\t\t\t// rather than allocating an attacker-sized string from a crafted value.\r\n\t\t\tif (len >> 1 != (uint)MSBAML_SIG.Length)\r\n\t\t\t\tthrow new InvalidDataException(\"Invalid BAML signature length.\");\r\n\t\t\tvar sig = new string(rdr.ReadChars((int)(len >> 1)));\r\n\t\t\trdr.ReadBytes((int)(((len + 3) & ~3) - len));\r\n\t\t\treturn sig;\r\n\t\t}\r\n\r\n\t\tpublic static BamlDocument ReadDocument(Stream str, CancellationToken token)\r\n\t\t{\r\n\t\t\tvar ret = new BamlDocument();\r\n\t\t\tvar reader = new BamlBinaryReader(str);\r\n\t\t\tret.Signature = ReadSignature(str);\r\n\t\t\tif (ret.Signature != MSBAML_SIG)\r\n\t\t\t\tthrow new NotSupportedException();\r\n\t\t\tret.ReaderVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() };\r\n\t\t\tret.UpdaterVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() };\r\n\t\t\tret.WriterVersion = new BamlDocument.BamlVersion { Major = reader.ReadUInt16(), Minor = reader.ReadUInt16() };\r\n\t\t\tif (ret.ReaderVersion.Major != 0 || ret.ReaderVersion.Minor != 0x60 ||\r\n\t\t\t\tret.UpdaterVersion.Major != 0 || ret.UpdaterVersion.Minor != 0x60 ||\r\n\t\t\t\tret.WriterVersion.Major != 0 || ret.WriterVersion.Minor != 0x60)\r","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/icsharpcode/ILSpy/blob/60c08fcb74fcc183130f73c861ed35cf944d0bf1/ICSharpCode.BamlDecompiler/Baml/BamlReader.cs#L53-L89","documentation":"Thrown by BamlReader.ReadSignature after reading the 4-byte length prefix of the BAML signature. The check len >> 1 != MSBAML_SIG.Length guards against a crafted length value before any allocation, because the only accepted signature is the fixed 6-char 'MSBAML'. A mismatch means the stream is not valid BAML or has been tampered with.","triggerScenarios":"ReadDocument is given a stream whose first uint (the signature length, stored as char-count<<1) is not exactly 12 (i.e. 6 chars). Typical when the stream is a plain PE/assembly, a managed resource that is not BAML, or arbitrary bytes.","commonSituations":"Pointing the BAML decompiler at a whole .NET DLL instead of the embedded BAML resource; selecting a non-BAML resource entry; corrupted/garbled BAML; an attacker-crafted stream with a huge length value.","solutions":["Make sure you are feeding the actual BAML resource stream (e.g. the entry from a .g.resources stream), not the whole assembly.","Probe the stream first with BamlReader.IsBamlHeader, which performs the same length/signature check non-destructively.","If the resource is corrupt, re-obtain it from the original assembly."],"exampleFix":"// before\nusing var fs = File.OpenRead(path);\nvar doc = BamlReader.ReadDocument(fs, ct); // throws if `path` is not a BAML stream\n\n// after\nusing var fs = File.OpenRead(path);\nif (!BamlReader.IsBamlHeader(fs))\n    throw new InvalidDataException(\"Selected stream is not MSBAML.\");\nfs.Position = 0;\nvar doc = BamlReader.ReadDocument(fs, ct);","handlingStrategy":"validation","validationCode":"// call before ReadDocument\npublic static bool IsLikelyBaml(Stream str)\n{\n    return BamlReader.IsBamlHeader(str); // restores position itself\n}","typeGuard":null,"tryCatchPattern":"try {\n    var doc = BamlReader.ReadDocument(stream, token);\n} catch (InvalidDataException ex) when (ex.Message.Contains(\"signature length\")) {\n    // not a BAML stream; pick the correct resource instead\n}","preventionTips":["Always resolve the .baml entry from the .g.resources stream rather than passing an assembly or arbitrary file.","Use IsBamlHeader as a cheap pre-check at the trust boundary."],"tags":["baml","validation","parsing","security"],"backgroundTag":null,"analyzedSha":"60c08fcb74fcc183130f73c861ed35cf944d0bf1","analyzedAt":"2026-08-13T11:34:51.223Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}