{"record":{"id":"430c4e3b7b9c0d8f","repo":"paperclipai/paperclip","slug":"public-report-contains-active-or-remote-html-fi","errorCode":null,"errorMessage":"Public report contains active or remote HTML: ${file}","messagePattern":"Public report contains active or remote HTML: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs","lineNumber":191,"sourceCode":"        );\n      continue;\n    }\n    const content = await readFile(absolute, \"utf8\");\n    const richAttempt = /^attempts\\/[^/]+\\/index\\.html$/.test(file);\n    const payload = richAttempt\n      ? validatePublicViewerPage(content, viewer.index)\n      : null;\n    if (!richAttempt) {\n      for (const pattern of CREDENTIAL_PATTERNS) {\n        if (pattern.test(content))\n          throw new Error(\n            `Public report contains credential/session material: ${file}`,\n          );\n      }\n      if (extname(file) !== \".html\") continue;\n      for (const pattern of ACTIVE_HTML_PATTERNS) {\n        if (pattern.test(content))\n          throw new Error(\n            `Public report contains active or remote HTML: ${file}`,\n          );\n      }\n    }\n    const navigation = payload\n      ? [\n          payload.navigation?.suiteHref,\n          payload.navigation?.previous?.href,\n          payload.navigation?.next?.href,\n        ].filter(Boolean)\n      : [];\n    for (const href of [...internalHtmlHrefs(content), ...navigation]) {\n      if (typeof href !== \"string\" || /[?:\\\\]|^\\/|^[a-z]+:/i.test(href))\n        throw new Error(`Unsafe report navigation in ${file}`);\n      const clean = href.split(\"#\", 1)[0].split(\"?\", 1)[0];\n      const target = resolve(\n        root,\n        ...file.split(\"/\").slice(0, -1),","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/scripts/publish-runner-protocol-eval-history.mjs#L173-L209","documentation":"Thrown by validatePublicProtocolEvalReport when a non-rich-attempt HTML file in the public report matches one of the ACTIVE_HTML_PATTERNS: <script>, <iframe>, <object>, <embed>, <form> tags, inline on* event handlers, javascript: URLs, or absolute http(s):// src/href references. The published report must be fully static with no executable or remote-loading content, so active or remote-loading HTML is rejected before S3 upload.","triggerScenarios":"Publishing a report whose index.html, tests/*.html, or attempts/<id>.html (legacy plain pages) contains e.g. <script src=\"https://cdn...\"></script>, an <iframe>, an onclick= attribute, a javascript: link, or any src/href pointing at an absolute http(s) URL.","commonSituations":"Report generator pastes agent output containing raw HTML including script tags without escaping; a marketing/analytics snippet is left in the report template; screenshots are referenced via absolute CDN URLs instead of bundling assets locally; rich-viewer pages are misnamed as legacy attempts/<id>.html so they skip the rich-attempt path and get the strict static-HTML scan.","solutions":["Locate the active HTML element or remote URL in the named file and remove it or replace with a static, relative reference.","HTML-escape all agent-generated content when rendering report pages so embedded code displays as text, not markup.","Serve all assets locally (viewer/assets/*.js|css|woff2) instead of linking remote CDNs.","If the page is a rich attempt, render it as attempts/<id>/index.html (rich-attempt path) instead of the legacy attempts/<id>.html name."],"exampleFix":"// before\n<script src=\"https://cdn.example.com/highlight.js\"></script>\n// after\n<link rel=\"stylesheet\" crossorigin href=\"./assets/app.css\">","handlingStrategy":"validation","validationCode":"const ACTIVE_HTML_PATTERNS = [\n  /<script\\b/iu, /<iframe\\b/iu, /<object\\b/iu, /<embed\\b/iu, /<form\\b/iu,\n  /\\son[a-z]+\\s*=/iu, /javascript\\s*:/iu,\n  /(?:src|href)\\s*=\\s*[\"'](?:https?:)?\\/\\//iu,\n];\nexport const isStaticSafeHtml = (html) => !ACTIVE_HTML_PATTERNS.some((p) => p.test(html));","typeGuard":"const isStaticSafeHtml = (content) => !ACTIVE_HTML_PATTERNS.some((p) => p.test(content));","tryCatchPattern":"try {\n  await validatePublicProtocolEvalReport(reportRoot, { viewerRoot });\n} catch (err) {\n  if (String(err.message).startsWith(\"Public report contains active or remote HTML\")) {\n    console.error(\"Escape embedded agent HTML or remove script/iframe/remote references in the named page.\");\n  }\n  throw err;\n}","preventionTips":["Always HTML-escape agent-generated content when rendering report pages.","Keep report templates free of analytics/marketing script snippets.","Bundle all assets locally under viewer/assets instead of CDN links.","Render rich attempts as attempts/<id>/index.html so they use the validated rich path."],"tags":["security","html","xss","publish-validation"],"backgroundTag":"invalid-config-value","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"}