can1357/oh-my-pi · error

Codex Security bundle locations must be repository-relative:

Error message

Codex Security bundle locations must be repository-relative: ${value}

What it means

Codex Security bundle finding locations must be repository-relative paths. importedLocationPath normalizes each location value and rejects empty strings, absolute POSIX paths, drive-letter absolute paths (C:/...), and any path segment equal to '..', because findings must only ever point inside the imported repository bundle.

Source

Thrown at packages/coding-agent/src/security/importers/codex-security.ts:119

}

async function readJson<T>(filePath: string): Promise<T> {
	return JSON.parse(await Bun.file(filePath).text()) as T;
}

function stringArray(value: unknown): string[] {
	return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
}

function importedLocationPath(value: string): string {
	const normalized = value.replaceAll("\\", "/").replace(/^\.\//, "");
	if (
		!normalized ||
		normalized.startsWith("/") ||
		/^[a-zA-Z]:\//.test(normalized) ||
		normalized.split("/").includes("..")
	) {
		throw new Error(`Codex Security bundle locations must be repository-relative: ${value}`);
	}
	return normalized;
}

function locationsForFinding(finding: CodexFinding): SecurityLocation[] {
	const locations: SecurityLocation[] = [];
	for (const location of finding.locations ?? []) {
		if (typeof location.path !== "string" || typeof location.startLine !== "number") continue;
		const normalized: SecurityLocation = {
			path: importedLocationPath(location.path),
			startLine: location.startLine,
		};
		if (location.endLine !== undefined) normalized.endLine = location.endLine;
		if (location.role !== undefined) normalized.role = location.role;
		locations.push(normalized);
	}
	return locations.length > 0 ? locations : [{ path: "unknown", startLine: 1, role: "unknown" }];
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Rewrite the finding's location paths in findings.json to be relative to the repository root (e.g. "src/a.ts")
  2. Remove any ".." segments by resolving the path to its repository-relative form before importing
  3. Drop or blank-to-nullify locations for findings that genuinely have no file association if the schema allows

Example fix

// before (findings.json)
"location": "/Users/alice/repo/src/auth.ts"
// after
"location": "src/auth.ts"
Defensive patterns

Strategy: validation

Validate before calling

for (const f of findingsDocument.findings) {
  for (const loc of f.locations ?? []) {
    const p = loc.path ?? "";
    if (!p || p.startsWith("/") || /^[a-zA-Z]:\//.test(p) || p.split("/").includes("..")) {
      throw new Error(`Location must be repository-relative: ${p}`);
    }
  }
}

Type guard

function isRepoRelativePath(value: unknown): value is string {
  return typeof value === "string" && value.length > 0 &&
    !value.startsWith("/") && !/^[a-zA-Z]:\//.test(value) &&
    !value.split("/").includes("..");
}

Try / catch

try {
  const bundle = await importCodexSecurityBundle(dir);
} catch (err) {
  if (err instanceof Error && err.message.includes("must be repository-relative")) {
    console.error(`Bad location path in bundle: ${err.message}`); // fix findings.json paths and retry
  } else throw err;
}

Prevention

When it happens

Trigger: A findings.json entry has a location path that is absolute (e.g. "/home/user/repo/src/a.ts" or "C:/repo/a.ts"), contains a ".." segment, or is empty/whitespace when a Codex Security bundle is imported.

Common situations: Hand-edited or tool-generated findings.json with machine-absolute paths; paths written on a different machine with drive letters; path traversal segments left in by a generator; empty location fields for findings without a file.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/eb8dd36f5931aa32. Report an issue: GitHub.