{"record":{"id":"aa738a45dbc7c823","repo":"paperclipai/paperclip","slug":"unsafe-historical-campaign-id","errorCode":null,"errorMessage":"Unsafe historical campaign ID","messagePattern":"Unsafe historical campaign ID","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs","lineNumber":486,"sourceCode":"  const temporary = await mkdtemp(\n    join(tmpdir(), \"runner-protocol-eval-history-\"),\n  );\n  const historyKey = `${validatedDestination.prefix}/history.json`;\n  const mergedHistory = mergeProtocolEvalHistory(\n    (await downloadJson(\n      validatedDestination.bucket,\n      historyKey,\n      join(temporary, \"history.json\"),\n    )) ?? emptyProtocolEvalHistory(),\n    protocolEvalHistoryRecord(\n      campaign,\n      `${validatedDestination.publicBaseUrl}/${validatedDestination.prefix}`,\n    ),\n  );\n  const history = await enrichProtocolEvalHistory(mergedHistory, {\n    currentCampaign: campaign,\n    loadCampaign: async (id) => {\n      if (!SAFE_CAMPAIGN.test(id)) throw new Error(\"Unsafe historical campaign ID\");\n      return downloadJson(validatedDestination.bucket,\n        `${validatedDestination.prefix}/campaigns/${id}/campaign.json`,\n        join(temporary, `${id}.json`));\n    },\n  });\n  const campaignPrefix = `${validatedDestination.prefix}/campaigns/${campaign.campaignId}`;\n  const manifestKey = `${campaignPrefix}/bundle-manifest.json`;\n  const existing = await downloadJson(\n    validatedDestination.bucket,\n    manifestKey,\n    join(temporary, \"existing-manifest.json\"),\n  );\n  if (existing && existing.bundleDigest !== manifest.bundleDigest) {\n    throw new Error(\n      `Immutable campaign ${campaign.campaignId} already exists with a different digest`,\n    );\n  }\n  if (!existing) {","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs#L468-L504","documentation":"While enriching history, the publisher downloads each historical campaign.json from S3; before doing so it re-validates every campaign ID against SAFE_CAMPAIGN so a tampered or malformed ID in history.json cannot be turned into an arbitrary S3 key or temp filename. An ID failing the gha-N-N(-report-slug) pattern triggers this error.","triggerScenarios":"history.json in the bucket containing a campaign entry with a malformed campaignId (hand-edited, produced by a bug, or from an older schema); injection attempts via IDs containing slashes, dot-dot segments, or unusual characters stored in the remote history.","commonSituations":"A legacy history.json with differently-formatted IDs from before the SAFE_CAMPAIGN convention; manual edits to history.json; corrupted analytics/enrichment data feeding IDs into loadCampaign.","solutions":["Inspect s3://<bucket>/<prefix>/history.json and find the campaign entry with the non-conforming campaignId","Remove or migrate that entry to a SAFE_CAMPAIGN-compliant ID, or reset history.json to a fresh v1 document","Regenerate the offending campaign record through the current publisher so it gets a valid ID","If it came from enrichment/analytics data, fix the upstream source of the ID"],"exampleFix":"// before (history.json)\n{ \"campaignId\": \"../../etc\", ... }\n// after (history.json)\n{ \"campaignId\": \"gha-12-1\", ... }","handlingStrategy":"validation","validationCode":"const SAFE_CAMPAIGN = /^gha-[1-9][0-9]*-[1-9][0-9]*(-report-[a-z0-9][a-z0-9-]{0,39})?$/;\nfor (const c of history.campaigns)\n  if (!SAFE_CAMPAIGN.test(c.campaignId)) throw new Error(`remote history has unsafe id: ${c.campaignId}`);","typeGuard":"const isSafeCampaignId = (v) => typeof v === \"string\" && /^gha-[1-9][0-9]*-[1-9][0-9]*(-report-[a-z0-9][a-z0-9-]{0,39})?$/.test(v);","tryCatchPattern":"try {\n  await publishProtocolEvalHistory({ reportRoot, destination, viewerRoot });\n} catch (e) {\n  if (String(e.message).includes(\"Unsafe historical campaign ID\")) {\n    console.error(\"download history.json, fix/remove the malformed campaignId, and re-upload\");\n  }\n  throw e;\n}","preventionTips":["Never hand-edit history.json; only write it through this publisher","Audit remote history.json entries after any schema/tooling migration","Keep campaign IDs in the SAFE_CAMPAIGN format at creation time"],"tags":["security","validation","s3"],"backgroundTag":"invalid-identifier-format","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}