{"record":{"id":"eb8dd36f5931aa32","repo":"can1357/oh-my-pi","slug":"codex-security-bundle-locations-must-be-repository","errorCode":null,"errorMessage":"Codex Security bundle locations must be repository-relative: ${value}","messagePattern":"Codex Security bundle locations must be repository-relative: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/importers/codex-security.ts","lineNumber":119,"sourceCode":"}\n\nasync function readJson<T>(filePath: string): Promise<T> {\n\treturn JSON.parse(await Bun.file(filePath).text()) as T;\n}\n\nfunction stringArray(value: unknown): string[] {\n\treturn Array.isArray(value) ? value.filter((item): item is string => typeof item === \"string\") : [];\n}\n\nfunction importedLocationPath(value: string): string {\n\tconst normalized = value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//, \"\");\n\tif (\n\t\t!normalized ||\n\t\tnormalized.startsWith(\"/\") ||\n\t\t/^[a-zA-Z]:\\//.test(normalized) ||\n\t\tnormalized.split(\"/\").includes(\"..\")\n\t) {\n\t\tthrow new Error(`Codex Security bundle locations must be repository-relative: ${value}`);\n\t}\n\treturn normalized;\n}\n\nfunction locationsForFinding(finding: CodexFinding): SecurityLocation[] {\n\tconst locations: SecurityLocation[] = [];\n\tfor (const location of finding.locations ?? []) {\n\t\tif (typeof location.path !== \"string\" || typeof location.startLine !== \"number\") continue;\n\t\tconst normalized: SecurityLocation = {\n\t\t\tpath: importedLocationPath(location.path),\n\t\t\tstartLine: location.startLine,\n\t\t};\n\t\tif (location.endLine !== undefined) normalized.endLine = location.endLine;\n\t\tif (location.role !== undefined) normalized.role = location.role;\n\t\tlocations.push(normalized);\n\t}\n\treturn locations.length > 0 ? locations : [{ path: \"unknown\", startLine: 1, role: \"unknown\" }];\n}","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/importers/codex-security.ts#L101-L137","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rewrite the finding's location paths in findings.json to be relative to the repository root (e.g. \"src/a.ts\")","Remove any \"..\" segments by resolving the path to its repository-relative form before importing","Drop or blank-to-nullify locations for findings that genuinely have no file association if the schema allows"],"exampleFix":"// before (findings.json)\n\"location\": \"/Users/alice/repo/src/auth.ts\"\n// after\n\"location\": \"src/auth.ts\"","handlingStrategy":"validation","validationCode":"for (const f of findingsDocument.findings) {\n  for (const loc of f.locations ?? []) {\n    const p = loc.path ?? \"\";\n    if (!p || p.startsWith(\"/\") || /^[a-zA-Z]:\\//.test(p) || p.split(\"/\").includes(\"..\")) {\n      throw new Error(`Location must be repository-relative: ${p}`);\n    }\n  }\n}","typeGuard":"function isRepoRelativePath(value: unknown): value is string {\n  return typeof value === \"string\" && value.length > 0 &&\n    !value.startsWith(\"/\") && !/^[a-zA-Z]:\\//.test(value) &&\n    !value.split(\"/\").includes(\"..\");\n}","tryCatchPattern":"try {\n  const bundle = await importCodexSecurityBundle(dir);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"must be repository-relative\")) {\n    console.error(`Bad location path in bundle: ${err.message}`); // fix findings.json paths and retry\n  } else throw err;\n}","preventionTips":["Configure the producing tool to emit paths relative to the repository root","Normalize to path.posix.relative(repoRoot, absPath) when generating bundles","Reject absolute/..-containing paths at bundle-generation time, not import time","Never hand-edit findings.json paths; regenerate from the scanner"],"tags":["security","path-validation","codex-security","import"],"backgroundTag":"non-repository-relative-path","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}