{"record":{"id":"38f2e1c855546625","repo":"jackwener/OpenCLI","slug":"youdao-note-url-must-use-http-or-https","errorCode":null,"errorMessage":"Youdao Note URL must use http or https","messagePattern":"Youdao Note URL must use http or https","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/youdao/note.js","lineNumber":30,"sourceCode":"  if (payload && !Array.isArray(payload) && typeof payload === 'object' && 'session' in payload && 'data' in payload) {\n    return payload.data;\n  }\n  return payload;\n}\n\nfunction normalizeShareUrl(raw) {\n  const value = String(raw ?? '').trim();\n  if (!value) {\n    throw new ArgumentError('youdao note url cannot be empty', 'Pass a full public share URL from Youdao Notes.');\n  }\n  let parsed;\n  try {\n    parsed = new URL(value);\n  } catch {\n    throw new ArgumentError('Invalid Youdao Note URL', 'Example: https://share.note.youdao.com/ynoteshare/index.html?id=...&type=note');\n  }\n  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n    throw new ArgumentError('Youdao Note URL must use http or https');\n  }\n  if (!ALLOWED_HOSTS.has(parsed.hostname)) {\n    throw new ArgumentError('Youdao Note URL must be under note.youdao.com or note.youdao.cn');\n  }\n  if (!parsed.searchParams.get('id')) {\n    throw new ArgumentError('Youdao Note URL must include an id query parameter');\n  }\n  const type = parsed.searchParams.get('type');\n  if (type && type !== 'note') {\n    throw new ArgumentError('youdao note only accepts shared note URLs', 'Shared notebooks are not implemented yet.');\n  }\n  return parsed.toString();\n}\n\nfunction formatYoudaoTimestamp(value) {\n  if (value == null || value === '') return '';\n  const numeric = Number(value);\n  if (!Number.isFinite(numeric) || numeric <= 0) return String(value);","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/youdao/note.js#L12-L48","documentation":"ArgumentError thrown by normalizeShareUrl when the parsed URL uses a protocol other than http: or https: (e.g. javascript:, file:, ftp:, data:). The library loads the URL in a browser page and only permits web schemes for safety and correctness.","triggerScenarios":"Passing 'javascript:alert(1)', 'file:///path/to/note.html', 'ftp://...', 'ws://...', or a URL whose scheme is uppercase/malformed such that parsed.protocol is not exactly 'https:' or 'http:'.","commonSituations":"Users converting local saved HTML pages into inputs; template interpolation producing javascript:/data: URLs; config containing internal schemes; security-filtered inputs that rewrote the scheme.","solutions":["Use the https form of the share URL: https://share.note.youdao.com/ynoteshare/index.html?id=<id>&type=note","Strip or replace non-http(s) schemes in your input pipeline before calling the command","Verify no prefix like 'javascript:' or 'file:' was accidentally prepended by your code"],"exampleFix":"// before\nawait youdaoNote(`file://${localPath}`);\n// after\nif (!/^https?:\\/\\//.test(inputUrl)) throw new Error('need http(s) share URL');\nawait youdaoNote(inputUrl);","handlingStrategy":"validation","validationCode":"function isHttpUrl(u) {\n  try { const p = new URL(u); return p.protocol === 'https:' || p.protocol === 'http:'; }\n  catch { return false; }\n}\nif (!isHttpUrl(inputUrl)) throw new Error('share URL must be http(s)');","typeGuard":"function hasWebProtocol(v) {\n  try { const p = new URL(v); return p.protocol === 'https:' || p.protocol === 'http:'; } catch { return false; }\n}","tryCatchPattern":"try {\n  await youdaoNote(url);\n} catch (e) {\n  if (String(e.message).includes('must use http or https')) {\n    // replace file:/javascript:/ftp: source with the public https share URL\n  } else throw e;\n}","preventionTips":["Only feed http(s) URLs into browser-automation commands","Reject file:// or javascript: schemes in input sanitation","Normalize schemes to https for Youdao share links"],"tags":["argument-error","url-scheme","validation","security"],"backgroundTag":"unsupported-url-scheme","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}