{"record":{"id":"12e611117b1e6dd3","repo":"affaan-m/ECC","slug":"nasiko-manifest-layer-size-is-outside-the-allowed","errorCode":null,"errorMessage":"Nasiko manifest layer size is outside the allowed range.","messagePattern":"Nasiko manifest layer size is outside the allowed range\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/nasiko-release.js","lineNumber":71,"sourceCode":"\nfunction assertDigest(bytes, expectedDigest, label) {\n  if (!SHA256_PATTERN.test(expectedDigest)) throw new Error(`${label} has an invalid expected digest.`);\n  const actual = digestBytes(bytes);\n  if (actual !== expectedDigest) throw new Error(`${label} digest mismatch: expected ${expectedDigest}, got ${actual}.`);\n}\n\nfunction validateManifest(bytes) {\n  let manifest;\n  try { manifest = JSON.parse(bytes.toString('utf8')); } catch (_error) { throw new Error('Nasiko manifest is not valid JSON.'); }\n  if (manifest.schemaVersion !== 2 || !Array.isArray(manifest.layers) || manifest.layers.length !== 1) {\n    throw new Error('Nasiko manifest must contain exactly one OCI layer.');\n  }\n  const layer = manifest.layers[0];\n  if (layer.mediaType !== 'application/gzip' || !SHA256_PATTERN.test(layer.digest)) {\n    throw new Error('Nasiko manifest layer is not a qualified gzip artifact.');\n  }\n  if (!Number.isSafeInteger(layer.size) || layer.size <= 0 || layer.size > MAX_ARCHIVE_BYTES) {\n    throw new Error('Nasiko manifest layer size is outside the allowed range.');\n  }\n  return { digest: layer.digest, size: layer.size };\n}\n\nfunction readTarString(block, offset, length) {\n  return block.subarray(offset, offset + length).toString('utf8').replace(/\\0.*$/, '');\n}\n\nfunction extractQualifiedTarGzip(archiveBytes, expectedName) {\n  let tar;\n  try { tar = zlib.gunzipSync(archiveBytes, { maxOutputLength: MAX_BINARY_BYTES + 2048 }); }\n  catch (_error) { throw new Error('Nasiko archive is invalid or exceeds the decompressed size limit.'); }\n  let offset = 0;\n  let binary = null;\n  while (offset + 512 <= tar.length) {\n    const header = tar.subarray(offset, offset + 512);\n    if (header.every(byte => byte === 0)) break;\n    const name = readTarString(header, 0, 100);","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/affaan-m/ECC/blob/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/lib/nasiko-release.js#L53-L89","documentation":"validateManifest in scripts/lib/nasiko-release.js bounds-checks the declared layer size before any download or extraction happens: it must be a safe integer, strictly positive, and at most MAX_ARCHIVE_BYTES (100 MiB). This pre-screens against absurd or malicious size declarations and against zero-byte layers that could not contain the binary.","triggerScenarios":"layer.size is not a Number.isSafeInteger (missing, fractional, string), is <= 0, or exceeds 104857600 bytes. Example: manifest declares size 524288000 after a release accidentally doubled up payloads, or a crafted manifest declaring a huge size.","commonSituations":"Upstream artifact grew beyond the 100 MiB cap in a new release; manifests generated by a broken pipeline omitting or corrupting the size field; malicious size-inflation attempts.","solutions":["If the legitimate artifact now exceeds 100 MiB, raise MAX_ARCHIVE_BYTES deliberately in scripts/lib/nasiko-release.js after review","Fix the publishing pipeline so layer.size is a correct positive integer","Treat unexpected huge declarations on a pinned digest as a supply-chain incident and report upstream"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await installNasiko({ version: 'v0.1.0' });\n} catch (error) {\n  if (/layer size is outside the allowed range/.test(String(error.message))) {\n    // Declared size is 0/absent/>100MiB. Check the published manifest; if the\n    // real artifact grew, raise MAX_ARCHIVE_BYTES deliberately with review.\n  }\n  throw error;\n}","preventionTips":["Assert the binary stays under the size caps in release CI before publishing","Keep layer.size correct in generated manifests (integer bytes, not blocks)","Treat size inflation on pinned digests as suspicious until explained"],"tags":["oci","manifest","size-limit","validation"],"backgroundTag":"oci-manifest-invalid","analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}