affaan-m/ECC · error

Nasiko manifest layer size is outside the allowed range.

Error message

Nasiko manifest layer size is outside the allowed range.

What it means

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.

Source

Thrown at scripts/lib/nasiko-release.js:71

function assertDigest(bytes, expectedDigest, label) {
  if (!SHA256_PATTERN.test(expectedDigest)) throw new Error(`${label} has an invalid expected digest.`);
  const actual = digestBytes(bytes);
  if (actual !== expectedDigest) throw new Error(`${label} digest mismatch: expected ${expectedDigest}, got ${actual}.`);
}

function validateManifest(bytes) {
  let manifest;
  try { manifest = JSON.parse(bytes.toString('utf8')); } catch (_error) { throw new Error('Nasiko manifest is not valid JSON.'); }
  if (manifest.schemaVersion !== 2 || !Array.isArray(manifest.layers) || manifest.layers.length !== 1) {
    throw new Error('Nasiko manifest must contain exactly one OCI layer.');
  }
  const layer = manifest.layers[0];
  if (layer.mediaType !== 'application/gzip' || !SHA256_PATTERN.test(layer.digest)) {
    throw new Error('Nasiko manifest layer is not a qualified gzip artifact.');
  }
  if (!Number.isSafeInteger(layer.size) || layer.size <= 0 || layer.size > MAX_ARCHIVE_BYTES) {
    throw new Error('Nasiko manifest layer size is outside the allowed range.');
  }
  return { digest: layer.digest, size: layer.size };
}

function readTarString(block, offset, length) {
  return block.subarray(offset, offset + length).toString('utf8').replace(/\0.*$/, '');
}

function extractQualifiedTarGzip(archiveBytes, expectedName) {
  let tar;
  try { tar = zlib.gunzipSync(archiveBytes, { maxOutputLength: MAX_BINARY_BYTES + 2048 }); }
  catch (_error) { throw new Error('Nasiko archive is invalid or exceeds the decompressed size limit.'); }
  let offset = 0;
  let binary = null;
  while (offset + 512 <= tar.length) {
    const header = tar.subarray(offset, offset + 512);
    if (header.every(byte => byte === 0)) break;
    const name = readTarString(header, 0, 100);

View on GitHub (pinned to 06c5e118c4)

Solutions

  1. If the legitimate artifact now exceeds 100 MiB, raise MAX_ARCHIVE_BYTES deliberately in scripts/lib/nasiko-release.js after review
  2. Fix the publishing pipeline so layer.size is a correct positive integer
  3. Treat unexpected huge declarations on a pinned digest as a supply-chain incident and report upstream
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await installNasiko({ version: 'v0.1.0' });
} catch (error) {
  if (/layer size is outside the allowed range/.test(String(error.message))) {
    // Declared size is 0/absent/>100MiB. Check the published manifest; if the
    // real artifact grew, raise MAX_ARCHIVE_BYTES deliberately with review.
  }
  throw error;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18). Data as JSON: /api/errors/12e611117b1e6dd3. Report an issue: GitHub.