{"record":{"id":"9af0c1f04c1ce163","repo":"siyuan-note/siyuan","slug":"invalid-encrypted-asset-metadata-size","errorCode":null,"errorMessage":"invalid encrypted asset metadata size","messagePattern":"invalid encrypted asset metadata size","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/crypto.go","lineNumber":2269,"sourceCode":"\t\t}\n\t\tif err = binary.Write(ret, binary.BigEndian, uint32(len(encryptedChunk))); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tret.Write(encryptedChunk)\n\t}\n\tif err = binary.Write(ret, binary.BigEndian, uint32(0)); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret.Bytes(), nil\n}\n\nfunc decryptAssetMetadata(boxID, diskName string, dek, ciphertext []byte) (metadata *encryptedAssetMetadata, contentOffset int, err error) {\n\tif len(ciphertext) < 8 || !bytes.Equal(ciphertext[:4], encryptedAssetMagic) {\n\t\treturn nil, 0, errors.New(\"invalid encrypted asset format\")\n\t}\n\tmetadataSize := int(binary.BigEndian.Uint32(ciphertext[4:8]))\n\tif metadataSize < 1 || metadataSize > encryptedAssetMetadataMaxSize || 8+metadataSize+4 > len(ciphertext) {\n\t\treturn nil, 0, errors.New(\"invalid encrypted asset metadata size\")\n\t}\n\tassetKey := util.DeriveSubKey(dek, \"siyuan/asset\")\n\tdefer zeroAndClear(assetKey)\n\taadPrefix := \"siyuan:asset:\" + boxID + \":assets/\" + diskName\n\tplainMetadata, decryptErr := util.DecryptWithAAD(assetKey, ciphertext[8:8+metadataSize], []byte(aadPrefix+\":metadata\"))\n\tif decryptErr != nil {\n\t\treturn nil, 0, decryptErr\n\t}\n\tmetadata = &encryptedAssetMetadata{}\n\tif err = json.Unmarshal(plainMetadata, metadata); err != nil {\n\t\treturn nil, 0, err\n\t}\n\tif metadata.OriginalName == \"\" || metadata.OriginalName == \".\" ||\n\t\tfilepath.Base(metadata.OriginalName) != metadata.OriginalName || strings.ContainsAny(metadata.OriginalName, `/\\`) {\n\t\treturn nil, 0, errors.New(\"invalid encrypted asset original name\")\n\t}\n\tif metadata.Size < 0 || metadata.Chunks == 0 {\n\t\treturn nil, 0, errors.New(\"invalid encrypted asset content metadata\")","sourceCodeStart":2251,"sourceCodeEnd":2287,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/crypto.go#L2251-L2287","documentation":"Thrown by decryptAssetMetadata when the 4-byte metadata-size field (read from ciphertext[4:8]) is zero, exceeds 1 MiB (encryptedAssetMetadataMaxSize), or when 8 + metadataSize + 4 would exceed the total ciphertext length. This catches truncated, tampered, or bit-flipped asset files where the size header is inconsistent with the actual data.","triggerScenarios":"DecryptAsset is called on a file that has the SYAE magic but a corrupted size field — bit rot on disk, partial write during sync, or deliberate tampering. Also possible if a non-asset SYAE-prefixed file is mistakenly fed to the asset decryptor.","commonSituations":"Disk corruption or bit rot on a long-lived encrypted asset. Sync was interrupted mid-transfer leaving a truncated file. Backup restore produced a file with correct magic but truncated body.","solutions":["Restore the affected asset file from a valid backup or re-sync from a peer.","Verify file integrity (size matches the notebook's asset index) before attempting decryption.","If the file is unrecoverable, remove it from the assets directory to stop repeated decryption failures, and inform the user which asset was lost."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Basic integrity pre-check\nif len(raw) < 12 {\n    return errors.New(\"asset file too small to be valid\")\n}\nmetaSize := binary.BigEndian.Uint32(raw[4:8])\nif metaSize < 1 || metaSize > 1048576 || 8+int(metaSize)+4 > len(raw) {\n    return errors.New(\"asset file metadata header is inconsistent\")\n}","typeGuard":null,"tryCatchPattern":"plain, err := DecryptAsset(boxID, diskName, dek, raw)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid encrypted asset\") {\n        // log and skip this asset, or restore from backup\n        logging.LogWarnf(\"skipping corrupted asset %s: %s\", diskName, err)\n        continue\n    }\n    return err\n}","preventionTips":["Run periodic integrity checks on encrypted assets.","Maintain backups of the encrypted notebook so corrupted assets can be restored.","Monitor sync logs for partial/interrupted transfers."],"tags":["encryption","asset","corruption","size-validation","crypto"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}