can1357/oh-my-pi · error · ArchiveError
Invalid old-GNU ${field}
Error message
Invalid old-GNU ${field} What it means
Thrown by normalizeOldGnuName when an old-GNU rename record's path is absolute (starts with '/') after backslash-to-slash conversion. The library rejects absolute paths in old-GNU 'N' metadata to prevent archive members escaping the archive root.
Source
Thrown at packages/utils/src/ar/tar.ts:254
}
function paxDeclaresSparse(
globalPax: ReadonlyMap<string, string>,
localPax: ReadonlyMap<string, string> | undefined,
): boolean {
return paxAttribute(globalPax, localPax, PAX_SPARSE_MARKER) === "1";
}
function indexOfAscii(bytes: Uint8Array, value: string, start: number): number {
for (let offset = start; offset <= bytes.byteLength - value.length; offset++) {
if (bytesMatchAscii(bytes, offset, value)) return offset;
}
return -1;
}
function normalizeOldGnuName(value: string, field: string, limits: ArchiveLimits): string {
const portable = value.replace(/\\/g, "/");
if (path.posix.isAbsolute(portable)) throw new ArchiveError(`Invalid old-GNU ${field}`);
const normalized = normalizeArchiveEntryPath(portable);
if (!normalized) throw new ArchiveError(`Invalid old-GNU ${field}`);
assertArchivePathString(normalized, field, limits.maxPathBytes);
return normalized;
}
function renameOldGnuEntries(
entries: Map<string, ArchiveIndexEntry>,
pendingLinks: Map<ArchiveIndexEntry, PendingTarLink>,
fromPath: string,
toPath: string,
limits: ArchiveLimits,
): void {
const moved = [...entries.entries()].filter(
([entryPath]) => entryPath === fromPath || entryPath.startsWith(`${fromPath}/`),
);
if (moved.length === 0) return;
for (const [entryPath] of moved) entries.delete(entryPath);View on GitHub (pinned to 9690622007)
Solutions
- Inspect the archive with `tar tvf` to find the offending old-GNU record and re-pack the archive with a modern tar implementation.
- Strip or rewrite the typeflag-'N' records from the archive if the rename metadata is unnecessary.
- Treat the archive as untrusted/corrupt and reject it if it comes from an unknown source.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-scan for old-GNU 'N' records with absolute paths before indexing
function hasAbsoluteOldGnuRename(bytes: Uint8Array): boolean {
// crude scan: block typeflag at offset 156 === 'N' plus 'Rename /' pattern
for (let off = 0; off + 512 <= bytes.byteLength; ) {
if (bytes[off + 156] === 0x4e /* N */) return true; // inspect record contents
const size = /* parse octal size at 124 */ 0;
off += 512 + Math.ceil(size / 512) * 512;
}
return false;
} Try / catch
try {
await readTar(bytes, opts);
} catch (e) {
if (e instanceof ArchiveError && e.message.startsWith("Invalid old-GNU")) {
throw new Error("Archive contains unsafe old-GNU rename paths; refusing to index");
}
throw e;
} Prevention
- Re-pack legacy archives with modern GNU tar to drop old-GNU 'N' records.
- Reject archives whose rename metadata contains absolute paths.
- Treat typeflag-'N' blocks in untrusted archives as a red flag.
When it happens
Trigger: Reading a tar with an old-GNU name record (typeflag 'N') containing 'Rename <abs-path> to ...' where the source path is absolute; the source-path normalization (normalizeOldGnuName(source, "source path")) throws this first.
Common situations: Archives written by very old or non-standard GNU tar variants with odd rename metadata; hand-edited or malicious archives attempting path escape.
Related errors
- Invalid old-GNU name record
- Invalid tar member path '${formatArchivePathForError(rawPath
- Invalid empty tar member path
- Tar directory '${formatArchivePathForError(normalized)}' can
- Archive write path must target a file inside the archive
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e323bfe7e8d35508.
Report an issue: GitHub.