{"record":{"id":"87fd7d73faf2ba7c","repo":"davila7/claude-code-templates","slug":"sem-e016","errorCode":"SEM_E016","errorMessage":"javascript: protocol detected (XSS risk)","messagePattern":"javascript: protocol detected \\(XSS risk\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli-tool/src/validation/validators/SemanticValidator.js","lineNumber":288,"sourceCode":"\n        this.addError(code, message, {\n          path,\n          severity,\n          matches: contexts.length,\n          examples: contexts.slice(0, 3)\n        });\n      }\n    }\n  }\n\n  /**\n   * Check for HTML/Script injection attempts\n   */\n  checkHtmlInjection(content, path) {\n    const dangerousTags = [\n      { tag: '<script', code: 'SEM_E014', message: '<script> tag detected (XSS risk)' },\n      { tag: '<iframe', code: 'SEM_E015', message: '<iframe> tag detected (injection risk)' },\n      { tag: 'javascript:', code: 'SEM_E016', message: 'javascript: protocol detected (XSS risk)' },\n      { tag: 'onclick=', code: 'SEM_E017', message: 'Inline event handler detected (XSS risk)' },\n      { tag: 'onerror=', code: 'SEM_E018', message: 'onerror handler detected (XSS risk)' }\n    ];\n\n    for (const { tag, code, message } of dangerousTags) {\n      const lowerContent = content.toLowerCase();\n      if (lowerContent.includes(tag.toLowerCase())) {\n        const index = lowerContent.indexOf(tag.toLowerCase());\n        const lineInfo = this.getLineFromIndex(content, index);\n\n        this.addError(code, message, {\n          path,\n          severity: 'critical',\n          line: lineInfo.line,\n          column: lineInfo.column,\n          position: lineInfo.position,\n          lineText: lineInfo.lineText,\n          context: this.getContext(content, index, 50)","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/davila7/claude-code-templates/blob/a0851ed10c7c60463dac8cfaaca124cf32d5804d/cli-tool/src/validation/validators/SemanticValidator.js#L270-L306","documentation":"SEM_E016 is emitted by checkHtmlInjection when the content (case-insensitively) contains the substring 'javascript:'. The javascript: URL scheme executes arbitrary JS when a link is followed, so any occurrence in component markdown is treated as an XSS risk.","triggerScenarios":"validate() where content.toLowerCase().includes('javascript:'). Substring match: matches links like [x](javascript:alert(1)) but also prose such as 'written in JavaScript: a guide' or code examples calling 'javascript:' protocols.","commonSituations":"Docs that say 'using JavaScript: features include...' with a colon immediately after the word; example payloads demonstrating XSS; bookmarklet-style instructions.","solutions":["Rephrase prose so 'JavaScript' is not immediately followed by a colon ('using JavaScript — features include...')","Remove javascript: links from markdown; use normal https:// links","Escape XSS payload examples inside code fences as 'java\\x73cript:' or describe the payload in words"],"exampleFix":"# before\nLearn about JavaScript: closures, promises, and more.\n# before (link)\n[x](javascript:alert(1))\n# after\nLearn about JavaScript — closures, promises, and more.\n# after (link)\n[x](https://example.com)","handlingStrategy":"validation","validationCode":"if (component.content.toLowerCase().includes('javascript:')) {\n  // check prose 'JavaScript:' false positive or a javascript: URL to remove\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid 'JavaScript:' followed by a colon in prose","Never use javascript: URLs in links","Describe XSS payloads instead of pasting them"],"tags":["xss","javascript-url","static-analysis"],"backgroundTag":"xss-script-tag-detected","analyzedSha":"a0851ed10c7c60463dac8cfaaca124cf32d5804d","analyzedAt":"2026-08-28T14:11:56.058Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}