@juspay/neurolink 13.8.20 → 13.8.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,8 +1,8 @@
1
- ## [13.8.20](https://github.com/juspay/neurolink/compare/v13.8.19...v13.8.20) (2026-10-27)
1
+ ## [13.8.21](https://github.com/juspay/neurolink/compare/v13.8.20...v13.8.21) (2026-10-27)
2
2
 
3
3
  ### Bug Fixes
4
4
 
5
- - **(cli):** stop recommending the retired claude-3-5-sonnet as the Anthropic default ([d1cdcb0](https://github.com/juspay/neurolink/commit/d1cdcb05716ce415924ab6bf2d68ef4bd5befdb6))
5
+ - **(sanitizers):** reject case-insensitive DOCTYPE and ENTITY in SVG ([1230374](https://github.com/juspay/neurolink/commit/1230374bb34b6413b84dc4b37e63c70a1ca02e30))
6
6
 
7
7
  ## [11.2.3](https://github.com/juspay/neurolink/compare/v11.2.2...v11.2.3) (2026-08-19)
8
8
 
@@ -842,7 +842,7 @@ ${s}
842
842
  `)),d&&a.push(`**Speaker notes:** ${d}`),a.push(""))}return a.join(`
843
843
  `).trim()||null}static extractNotesForSlide(t,r,n){const o=n(t.get(LKt(r)));if(o===null)return null;let i=null;gL.lastIndex=0;for(let l=gL.exec(o);l!==null;l=gL.exec(o)){const c=l[0];if(/Type="[^"]*\/notesSlide"/.test(c)){i=c.match(/Target="([^"]+)"/)?.[1]??null;break}}if(!i)return null;const s=i.replace(/^\.\.\//,"ppt/").replace(/^\/+/,""),a=n(t.get(s));return a===null?null:ES.extractTextFromXml(a).join(" ").trim()||null}static extractTextFromXml(t){const r=[];let n=null,o=null,i="";for(const s of t.matchAll(DKt)){const{text:a,closing:u,tag:l,end:c}=s.groups??{};if(a!==void 0){const p=khn(a);o?i+=p:p.trim()&&r.push(p.trim());continue}if(l===void 0&&c===void 0){o&&(i+=" ");continue}const d=l==="p"?1:l==="tc"?2:3;o&&d>=1&&(i.trim()&&o.push(i.trim()),i=""),o&&d>=2&&(n||(n=[]),n.push(o.join(" ")),o=null),n&&d>=3&&(n.some(p=>p)&&r.push(n.join(" | ").trim()),n=null),u===""&&(l==="tr"?n=[]:l==="tc"&&(o=[]))}return r}static async extractSlides(t,r){const o=new rL(t).getEntries(),i=MKt(),{byName:s}=eL(o),a=[];for(const l of s.values()){const c=l.entryName.match(fL);if(c){const d=parseInt(c[1],10);if(r.includes(d)){const p=i(l);p!==null&&a.push({slideNumber:d,xml:p})}}}if(a.sort((l,c)=>l.slideNumber-c.slideNumber),a.length===0){let l=0;for(const c of o)fL.test(c.entryName)&&l++;return`Slides ${r.join(", ")} not found. This presentation has ${l} slide(s).`}const u=[];for(const l of a){const c=ES.extractTextFromXml(l.xml),d=ES.extractNotesForSlide(s,l.slideNumber,i);u.push(`### Slide ${l.slideNumber}`),c.length>0&&u.push(c.join(`
844
844
  `)),d&&u.push(`**Speaker notes:** ${d}`),c.length===0&&!d&&u.push("(No text content on this slide)"),u.push("")}return u.join(`
845
- `).trim()}}}});function Ahn(e){return Chn(e).content}function Chn(e){if(!e||typeof e!="string")throw new Error("SVG content is required and must be a string");const t=[];let r=e;const n=e;if(r.includes("<!DOCTYPE")||r.includes("<!ENTITY"))throw new Error("SVG contains DOCTYPE or ENTITY declarations which are not allowed for security reasons");const o=/<\?xml-stylesheet[^?]*\?>/gi;o.test(r)&&(t.push("XML stylesheet processing instruction"),r=r.replace(o,""));const i=/<!\[CDATA\[[\s\S]*?\]\]>/gi,s=r.match(i);s&&(t.push(`CDATA sections (${s.length} found)`),r=r.replace(i,""));const a=Array.from(Aie);for(let p=0;p<a.length;p++){const m=a[p],h=new RegExp(`<${m}[^>]*>[\\s\\S]*?<\\/${m}>`,"gi"),g=new RegExp(`<${m}[^>]*\\/?>`,"gi");h.test(r)&&(t.push(`Element: <${m}> (with content)`),r=r.replace(h,"")),g.test(r)&&(t.push(`Element: <${m}>`),r=r.replace(g,""))}const u=/<\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*\/?>/g;r=r.replace(u,(p,m)=>{const h=m.toLowerCase();return h==="xml"?p:!yL.has(m)&&!yL.has(h)&&!Array.from(yL).some(y=>y.toLowerCase()===h)?(t.push(`Unknown element: <${m}>`),""):p}),r=xhn(r,t);const l=/(?:=\s*["']?)javascript:[^"'\s>]*/gi;l.test(r)&&(t.push("javascript: URL scheme"),r=r.replace(l,'=""'));const c=/(?:=\s*["']?)data:(?!image\/(?:png|jpeg|jpg|gif|svg\+xml))[^"'\s>]*/gi;c.test(r)&&(t.push("Suspicious data: URL"),r=r.replace(c,'=""'));const d=/(?:=\s*["']?)vbscript:[^"'\s>]*/gi;return d.test(r)&&(t.push("vbscript: URL scheme"),r=r.replace(d,'=""')),r=r.replace(/\s+/g," ").trim(),{content:r,removedItems:Array.from(new Set(t)),wasModified:r!==n}}function xhn(e,t){const r=/<([a-zA-Z][a-zA-Z0-9]*)([^>]*)>/g;return e.replace(r,(n,o,i)=>{if(!i||!i.trim())return n;const s=/([a-zA-Z][a-zA-Z0-9:_-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,a=[];for(let p=s.exec(i);p!==null;p=s.exec(i)){const m=p[1],h=p[2]??p[3]??"",g=m.toLowerCase();if(FKt.has(g)){t.push(`Attribute: ${m}`);continue}if(g.startsWith("on")){t.push(`Event handler: ${m}`);continue}if(!yT.has(m)&&!yT.has(g)&&!Array.from(yT).some(w=>w.toLowerCase()===g)){t.push(`Unknown attribute: ${m}`);continue}const y=h.toLowerCase();if(y.includes("javascript:")){t.push(`javascript: URL in ${m}`);continue}if(y.startsWith("data:")&&!y.startsWith("data:image/png")&&!y.startsWith("data:image/jpeg")&&!y.startsWith("data:image/jpg")&&!y.startsWith("data:image/gif")&&!y.startsWith("data:image/svg+xml")){t.push(`Suspicious data: URL in ${m}`);continue}if(y.includes("expression(")||y.includes("-moz-binding")||y.includes("behavior:")){t.push(`CSS XSS vector in ${m}`);continue}a.push(`${m}="${Ihn(h)}"`)}const u=/\s([a-zA-Z][a-zA-Z0-9:_-]*)(?=\s|>|$|\/)/g;let l=u.exec(i),c=0;const d=1e3;for(;l!==null&&c++<d;){const p=l[1];(yT.has(p)||yT.has(p.toLowerCase()))&&(a.some(m=>m.startsWith(`${p}=`))||a.push(p)),l=u.exec(i)}return a.length>0?`<${o} ${a.join(" ")}>`:`<${o}>`})}function Ihn(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Rhn(e){if(!e||typeof e!="string")return!1;const t=e.toLowerCase();if(t.includes("<!doctype")||t.includes("<!entity"))return!1;const r=Array.from(Aie);for(let n=0;n<r.length;n++){const o=r[n];if(t.includes(`<${o.toLowerCase()}`))return!1}return!(/\bon[a-z]+\s*=/i.test(e)||t.includes("javascript:"))}var yL,Aie,yT,FKt,Mhn=S({"src/lib/utils/sanitizers/svg.ts"(){"use strict";yL=new Set(["svg","g","defs","symbol","marker","rect","circle","ellipse","line","polyline","polygon","path","text","tspan","linearGradient","radialGradient","stop","pattern","clipPath","mask","filter","feGaussianBlur","feOffset","feBlend","feColorMatrix","feMerge","feMergeNode","title","desc","metadata"]),Aie=new Set(["script","style","foreignObject","use","image","a","animate","set","animateMotion","animateTransform","animateColor","iframe","object","embed"]),yT=new Set(["id","class","x","y","width","height","cx","cy","r","rx","ry","d","points","x1","y1","x2","y2","fill","stroke","stroke-width","stroke-dasharray","stroke-linecap","stroke-linejoin","opacity","fill-opacity","stroke-opacity","fill-rule","transform","viewBox","xmlns","xmlns:xlink","preserveAspectRatio","version","offset","stop-color","stop-opacity","gradientUnits","gradientTransform","patternUnits","patternTransform","spreadMethod","font-family","font-size","font-weight","font-style","text-anchor","dominant-baseline","alignment-baseline","letter-spacing","stdDeviation","dx","dy","in","in2","result","mode","type","values","clipPathUnits","maskUnits","maskContentUnits","markerWidth","markerHeight","refX","refY","orient","markerUnits"]),FKt=new Set(["style","href","xlink:href","onload","onerror","onclick","onmouseover","onmouseout","onmousedown","onmouseup","onmousemove","onfocus","onblur","onabort","onbegin","onend","onrepeat","onactivate","onscroll","onresize","onzoom","oninput","onchange","onsubmit","onreset","onkeydown","onkeyup","onkeypress","ondrag","ondragstart","ondragend","ondragenter","ondragleave","ondragover","ondrop","onunload","oncopy","oncut","onpaste"])}}),UKt={};ue(UKt,{SvgProcessor:()=>Cie,isSvgFile:()=>Phn,processSvg:()=>Ohn,svgProcessor:()=>vL,validateSvgSize:()=>Dhn});function Phn(e,t){return vL.isFileSupported(e,t)}function Dhn(e){return e<=5242880}async function Ohn(e,t){return vL.processFile(e,t)}var BKt,zKt,Cie,vL,Nhn=S({"src/lib/processors/markup/SvgProcessor.ts"(){"use strict";Mhn(),Kh(),BKt=["image/svg+xml"],zKt=[".svg"],Cie=class extends em{constructor(){super({maxSizeMB:5,timeoutMs:3e4,supportedMimeTypes:[...BKt],supportedExtensions:[...zKt],fileTypeName:"SVG",defaultFilename:"image.svg"})}async validateDownloadedFile(e,t){const r=e.toString("utf-8").trim(),n=r.startsWith("<?xml"),o=r.toLowerCase().startsWith("<!doctype"),i=r.toLowerCase().startsWith("<svg"),s=r.toLowerCase().includes("<svg");return!n&&!o&&!i&&!s?r.toLowerCase().includes("<html")?"Download failed - received HTML instead of SVG content":"Invalid SVG - missing <svg> element":null}buildProcessedResult(e,t){const r=e.toString("utf-8"),n=this.getFilename(t),o=Rhn(r),i=[];let s;try{s=Ahn(r)}catch{s='<svg xmlns="http://www.w3.org/2000/svg"></svg>',i.push("SVG sanitization failed - malformed content replaced with empty SVG for security")}o||i.push("SVG contained potentially unsafe content that was sanitized");const a=s!==r;return{textContent:s,rawContent:a?r:void 0,sanitized:!o||a,securityWarnings:i,buffer:e,mimetype:t.mimetype||"image/svg+xml",size:t.size,filename:n}}},vL=new Cie}});async function Lhn(){return(await Promise.resolve().then(()=>(Qoe(),K3))).videoProcessor}async function $hn(){return(await Promise.resolve().then(()=>(Dqt(),eie))).audioProcessor}async function Fhn(){return(await Promise.resolve().then(()=>(sie(),iL))).archiveProcessor}function GKt(e){return d1e(e)}function Uhn(e,t){const r=GKt(e),n=Ol.get(r);if(n&&n.expiresAt>t)return Ol.delete(r),Ol.set(r,n),n.contentType;n&&Ol.delete(r)}function Bhn(e){for(const[t,r]of Ol)r.expiresAt<=e&&Ol.delete(t)}function qKt(e,t,r){if(!t)return;const n=GKt(e);if(Ol.set(n,{contentType:t,expiresAt:r+jKt}),Ol.size>xie&&Bhn(r),Ol.size>xie){const o=Ol.keys().next().value;o!==void 0&&Ol.delete(o)}}function zhn(e){let t=e;for(let r=0;r<6;r++){const n=t instanceof Error?t.cause:void 0;if(!(n instanceof Error))return t;t=n}return t}function Ghn(e){let t,r=e;for(let n=0;n<6&&r instanceof Error;n++){const o=r.code;typeof o=="string"&&(t=o),r=r.cause}return t}function qhn(e){if(!(e instanceof Error))return!1;const t=[];let r=e;for(;r instanceof Error&&t.length<6;)t.push(r),r=r.cause;const n=t.map(a=>a.message).join(" | ").toLowerCase(),o=t.map(a=>a.code).reverse().find(a=>typeof a=="string")?.toUpperCase();if(o&&VKt.includes(o))return!0;const i=n.match(/http\s*(\d{3})/);if(i){const a=parseInt(i[1],10);if(HKt.includes(a))return!1;if(WKt.includes(a))return!0}return["timeout","timed out","connection reset","econnreset","etimedout","network error","socket hang up","enotfound","getaddrinfo","unavailable","service unavailable"].some(a=>n.includes(a))}function jhn(e){const t=e.trim();if(!t)return!1;const r=t[0],n=t[t.length-1];if(!(r==="{"&&n==="}"||r==="["&&n==="]"))return!1;try{return JSON.parse(t),!0}catch{return!1}}function wL(e){return e<1024?`${e} bytes`:e<1024*1024?`${(e/1024).toFixed(2)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(2)} MB`:`${(e/(1024*1024*1024)).toFixed(2)} GB`}function Vhn(e){const t=Udn(e);if(t)return t;const r=v3(e);if(Yre[r]||Hkt[r]||jkt.includes(r))return"text"}function Hhn(e){const t=e.toString("latin1",0,Math.min(e.length,4096)),r=t.match(/mimetype(application\/vnd\.oasis\.opendocument\.[a-z-]+)/);if(r){const n=r[1],o=Xte(n);if(o)return{type:o.fileType,mimeType:n}}if(!t.includes("[Content_Types].xml"))return null;for(const[n,o]of[["xl/","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],["word/","application/vnd.openxmlformats-officedocument.wordprocessingml.document"],["ppt/","application/vnd.openxmlformats-officedocument.presentationml.presentation"]])if(t.includes(n)){const i=Xte(o);if(i)return{type:i.fileType,mimeType:o}}return null}var jKt,xie,Ol,VKt,HKt,WKt,rf,KKt,JKt,XKt,YKt,ZKt,Iie,QKt,eJt=S({"src/lib/utils/fileDetector.ts"(){"use strict";Ti(),Sr(),Kd(),Rl(),Vkt(),q0(),wpn(),Zre(),ZD(),wat(),K0(),A3(),z(),Qkt(),et(),It(),oAt(),nCt(),ene(),jKt=6e4,xie=512,Ol=new Map,VKt=["ETIMEDOUT","ECONNRESET","ECONNREFUSED","ENOTFOUND","ENETUNREACH","EAI_AGAIN","EPIPE","ECONNABORTED","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT","UND_ERR_SOCKET"],HKt=[400,401,403,404,405],WKt=[429,500,502,503,504],rf=class wt{static DEFAULT_NETWORK_TIMEOUT=3e4;static DEFAULT_HEAD_TIMEOUT=5e3;static DEFAULT_DOCUMENT_TIMEOUT=3e4;static async detectAndProcess(t,r){const n=wt.deriveInputFilename(t),o=wt.deriveInputSize(t);return pt({name:"file.detect_and_process",tracer:Be.file,attributes:{[$e.FILE_NAME]:n,[$e.FILE_SIZE_BYTES]:o}},async i=>{const a=typeof t=="string"&&(t.startsWith("http://")||t.startsWith("https://"))?await wt.loadUrl(t,r):void 0,u=a?{...await wt.detect(a.content,{...r,filenameHint:r?.filenameHint||wt.deriveInputFilename(t)},a.contentType,r?.filenameHint||wt.deriveInputFilename(t)),source:"url"}:await wt.detect(t,r);if(i.setAttribute($e.FILE_CATEGORY,u.type),i.setAttribute($e.FILE_MIMETYPE,u.mimeType||"unknown"),i.setAttribute($e.FILE_CONFIDENCE,u.metadata.confidence),f.info(`[NEUROLINK] File detected: ${n} (${u.mimeType||"unknown"}, ${wL(o)}) \u2192 category: ${u.type}`),r?.allowedTypes&&!r.allowedTypes.includes(u.type)){const d=a?.content??await wt.loadContent(t,u,r),p=[];for(const h of r.allowedTypes)try{const g=await wt.tryFallbackParsing(d,h,r);if(g){f.info(`[FileDetector] \u2705 ${h.toUpperCase()} fallback successful`);const y=typeof g.content=="string"?g.content.length:g.content?.length||0;return i.setAttribute($e.FILE_OUTPUT_LENGTH,y),i.setAttribute($e.FILE_SUCCESS,!0),i.setAttribute($e.FILE_PROCESSOR_USED,`fallback:${h}`),f.info(`[NEUROLINK] File processed: ${n} \u2192 ${y} bytes output (fallback: ${h})`),g}}catch(g){const y=g instanceof Error?g.message:String(g);p.push(`${h}: ${y}`),f.debug(`[FileDetector] ${h} fallback failed: ${y}`)}f.warn(`[FileDetector] All fallback parsing failed for type "${u.type}". Attempted: ${r.allowedTypes.join(", ")}. Falling through to universal handler.`);const m=await wt.processFile(d,u,r);return wt.setFileResultSpanAttributes(i,m,n,u.type),m}const l=a?.content??await wt.loadContent(t,u,r),c=await wt.processFile(l,u,r);return wt.setFileResultSpanAttributes(i,c,n,u.type),c})}static setFileResultSpanAttributes(t,r,n,o){const i=typeof r.content=="string"?r.content.length:r.content?.length||0,s=Array.isArray(r.images)?r.images.length>0:!1,a=Array.isArray(r.images)?r.images.length:0;t.setAttribute($e.FILE_OUTPUT_LENGTH,i),t.setAttribute($e.FILE_SUCCESS,!0),t.setAttribute($e.FILE_PROCESSOR_USED,o),t.setAttribute($e.FILE_HAS_IMAGES,s),t.setAttribute($e.FILE_IMAGE_COUNT,a),f.info(`[NEUROLINK] File processed: ${n} \u2192 ${i} bytes output`+(a>0?` + ${a} image(s)`:"")+` (processor: ${o})`)}static deriveInputFilename(t){if(typeof t=="string"){if(t.startsWith("data:"))return"data-uri";if(t.startsWith("http"))try{return new URL(t).pathname.split("/").pop()||"url-file"}catch{return"url-file"}return t.split("/").pop()||t.split("\\").pop()||"file"}return Buffer.isBuffer(t)?"buffer":t?.filename||"unknown-input"}static deriveInputSize(t){if(Buffer.isBuffer(t))return t.length;if(typeof t=="string"){if(t.startsWith("data:")){const r=t.split(",")[1];return r?Math.floor(r.length*3/4):0}return t.length}return 0}static deriveInputSource(t){return Buffer.isBuffer(t)?"buffer":typeof t=="string"?t.startsWith("data:")?"datauri":t.startsWith("http://")||t.startsWith("https://")?"url":"path":"buffer"}static async tryFallbackParsing(t,r,n){switch(f.info(`[FileDetector] Attempting ${r.toUpperCase()} fallback parsing`),r){case"csv":{const o=n?.csvOptions,i=await vA.process(t,o);return f.info(`[FileDetector] CSV fallback: ${i.metadata?.rowCount||0} rows, ${i.metadata?.columnCount||0} columns`),i}case"text":{const o=t.toString("utf-8");if(wt.isValidText(o))return{type:"text",content:o,mimeType:wt.guessTextMimeType(o),metadata:{confidence:70,size:t.length}};throw new Error("Content does not appear to be valid text")}case"image":throw new Error("Image type requires binary detection, cannot fallback parse");case"pdf":throw new Error("PDF type requires binary detection, cannot fallback parse");case"audio":throw new Error("Audio type requires binary detection, cannot fallback parse");case"video":throw new Error("Video type requires binary detection, cannot fallback parse");case"archive":throw new Error("Archive type requires binary detection, cannot fallback parse");case"xlsx":throw new Error("Excel type requires binary detection, cannot fallback parse");case"docx":throw new Error("Word type requires binary detection, cannot fallback parse");case"pptx":throw new Error("PowerPoint type requires binary detection, cannot fallback parse");case"svg":{const o=t.toString("utf-8");if(o.includes("<svg")&&o.includes("</svg>"))return{type:"svg",content:o,mimeType:"image/svg+xml",metadata:{confidence:70,size:t.length}};throw new Error("Content does not appear to be valid SVG")}default:return null}}static isValidText(t){if(t.includes("\0"))return!1;let r=0;for(let n=0;n<t.length;n++){const o=t.charCodeAt(n);(o>=32&&o<127||o===9||o===10||o===13||o>127)&&r++}return r/t.length>=.9}static guessTextMimeType(t){const r=t.trim();if(r.startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))try{return JSON.parse(r),"application/json"}catch{}return wt.looksLikeXMLStrict(r)?r.includes("<!DOCTYPE html")||r.toLowerCase().includes("<html")||r.includes("<head")||r.includes("<body")?"text/html":"application/xml":wt.looksLikeYAMLStrict(r)?"application/yaml":"text/plain"}static looksLikeYAMLStrict(t){if(t.length===0)return!1;const r=t.split(`
845
+ `).trim()}}}});function Ahn(e){return Chn(e).content}function Chn(e){if(!e||typeof e!="string")throw new Error("SVG content is required and must be a string");const t=[];let r=e;const n=e,o=r.toUpperCase();if(o.includes("<!DOCTYPE")||o.includes("<!ENTITY")||/<!\s*(?:doctype|entity)/i.test(r))throw new Error("SVG contains DOCTYPE or ENTITY declarations which are not allowed for security reasons");const i=/<\?xml-stylesheet[^?]*\?>/gi;i.test(r)&&(t.push("XML stylesheet processing instruction"),r=r.replace(i,""));const s=/<!\[CDATA\[[\s\S]*?\]\]>/gi,a=r.match(s);a&&(t.push(`CDATA sections (${a.length} found)`),r=r.replace(s,""));const u=Array.from(Aie);for(let m=0;m<u.length;m++){const h=u[m],g=new RegExp(`<${h}[^>]*>[\\s\\S]*?<\\/${h}>`,"gi"),y=new RegExp(`<${h}[^>]*\\/?>`,"gi");g.test(r)&&(t.push(`Element: <${h}> (with content)`),r=r.replace(g,"")),y.test(r)&&(t.push(`Element: <${h}>`),r=r.replace(y,""))}const l=/<\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*\/?>/g;r=r.replace(l,(m,h)=>{const g=h.toLowerCase();return g==="xml"?m:!yL.has(h)&&!yL.has(g)&&!Array.from(yL).some(v=>v.toLowerCase()===g)?(t.push(`Unknown element: <${h}>`),""):m}),r=xhn(r,t);const c=/(?:=\s*["']?)javascript:[^"'\s>]*/gi;c.test(r)&&(t.push("javascript: URL scheme"),r=r.replace(c,'=""'));const d=/(?:=\s*["']?)data:(?!image\/(?:png|jpeg|jpg|gif|svg\+xml))[^"'\s>]*/gi;d.test(r)&&(t.push("Suspicious data: URL"),r=r.replace(d,'=""'));const p=/(?:=\s*["']?)vbscript:[^"'\s>]*/gi;return p.test(r)&&(t.push("vbscript: URL scheme"),r=r.replace(p,'=""')),r=r.replace(/\s+/g," ").trim(),{content:r,removedItems:Array.from(new Set(t)),wasModified:r!==n}}function xhn(e,t){const r=/<([a-zA-Z][a-zA-Z0-9]*)([^>]*)>/g;return e.replace(r,(n,o,i)=>{if(!i||!i.trim())return n;const s=/([a-zA-Z][a-zA-Z0-9:_-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,a=[];for(let p=s.exec(i);p!==null;p=s.exec(i)){const m=p[1],h=p[2]??p[3]??"",g=m.toLowerCase();if(FKt.has(g)){t.push(`Attribute: ${m}`);continue}if(g.startsWith("on")){t.push(`Event handler: ${m}`);continue}if(!yT.has(m)&&!yT.has(g)&&!Array.from(yT).some(w=>w.toLowerCase()===g)){t.push(`Unknown attribute: ${m}`);continue}const y=h.toLowerCase();if(y.includes("javascript:")){t.push(`javascript: URL in ${m}`);continue}if(y.startsWith("data:")&&!y.startsWith("data:image/png")&&!y.startsWith("data:image/jpeg")&&!y.startsWith("data:image/jpg")&&!y.startsWith("data:image/gif")&&!y.startsWith("data:image/svg+xml")){t.push(`Suspicious data: URL in ${m}`);continue}if(y.includes("expression(")||y.includes("-moz-binding")||y.includes("behavior:")){t.push(`CSS XSS vector in ${m}`);continue}a.push(`${m}="${Ihn(h)}"`)}const u=/\s([a-zA-Z][a-zA-Z0-9:_-]*)(?=\s|>|$|\/)/g;let l=u.exec(i),c=0;const d=1e3;for(;l!==null&&c++<d;){const p=l[1];(yT.has(p)||yT.has(p.toLowerCase()))&&(a.some(m=>m.startsWith(`${p}=`))||a.push(p)),l=u.exec(i)}return a.length>0?`<${o} ${a.join(" ")}>`:`<${o}>`})}function Ihn(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Rhn(e){if(!e||typeof e!="string")return!1;const t=e.toLowerCase();if(t.includes("<!doctype")||t.includes("<!entity")||/<!\s*(?:doctype|entity)/i.test(e))return!1;const r=Array.from(Aie);for(let n=0;n<r.length;n++){const o=r[n];if(t.includes(`<${o.toLowerCase()}`))return!1}return!(/\bon[a-z]+\s*=/i.test(e)||t.includes("javascript:"))}var yL,Aie,yT,FKt,Mhn=S({"src/lib/utils/sanitizers/svg.ts"(){"use strict";yL=new Set(["svg","g","defs","symbol","marker","rect","circle","ellipse","line","polyline","polygon","path","text","tspan","linearGradient","radialGradient","stop","pattern","clipPath","mask","filter","feGaussianBlur","feOffset","feBlend","feColorMatrix","feMerge","feMergeNode","title","desc","metadata"]),Aie=new Set(["script","style","foreignObject","use","image","a","animate","set","animateMotion","animateTransform","animateColor","iframe","object","embed"]),yT=new Set(["id","class","x","y","width","height","cx","cy","r","rx","ry","d","points","x1","y1","x2","y2","fill","stroke","stroke-width","stroke-dasharray","stroke-linecap","stroke-linejoin","opacity","fill-opacity","stroke-opacity","fill-rule","transform","viewBox","xmlns","xmlns:xlink","preserveAspectRatio","version","offset","stop-color","stop-opacity","gradientUnits","gradientTransform","patternUnits","patternTransform","spreadMethod","font-family","font-size","font-weight","font-style","text-anchor","dominant-baseline","alignment-baseline","letter-spacing","stdDeviation","dx","dy","in","in2","result","mode","type","values","clipPathUnits","maskUnits","maskContentUnits","markerWidth","markerHeight","refX","refY","orient","markerUnits"]),FKt=new Set(["style","href","xlink:href","onload","onerror","onclick","onmouseover","onmouseout","onmousedown","onmouseup","onmousemove","onfocus","onblur","onabort","onbegin","onend","onrepeat","onactivate","onscroll","onresize","onzoom","oninput","onchange","onsubmit","onreset","onkeydown","onkeyup","onkeypress","ondrag","ondragstart","ondragend","ondragenter","ondragleave","ondragover","ondrop","onunload","oncopy","oncut","onpaste"])}}),UKt={};ue(UKt,{SvgProcessor:()=>Cie,isSvgFile:()=>Phn,processSvg:()=>Ohn,svgProcessor:()=>vL,validateSvgSize:()=>Dhn});function Phn(e,t){return vL.isFileSupported(e,t)}function Dhn(e){return e<=5242880}async function Ohn(e,t){return vL.processFile(e,t)}var BKt,zKt,Cie,vL,Nhn=S({"src/lib/processors/markup/SvgProcessor.ts"(){"use strict";Mhn(),Kh(),BKt=["image/svg+xml"],zKt=[".svg"],Cie=class extends em{constructor(){super({maxSizeMB:5,timeoutMs:3e4,supportedMimeTypes:[...BKt],supportedExtensions:[...zKt],fileTypeName:"SVG",defaultFilename:"image.svg"})}async validateDownloadedFile(e,t){const r=e.toString("utf-8").trim(),n=r.startsWith("<?xml"),o=r.toLowerCase().startsWith("<!doctype"),i=r.toLowerCase().startsWith("<svg"),s=r.toLowerCase().includes("<svg");return!n&&!o&&!i&&!s?r.toLowerCase().includes("<html")?"Download failed - received HTML instead of SVG content":"Invalid SVG - missing <svg> element":null}buildProcessedResult(e,t){const r=e.toString("utf-8"),n=this.getFilename(t),o=Rhn(r),i=[];let s;try{s=Ahn(r)}catch{s='<svg xmlns="http://www.w3.org/2000/svg"></svg>',i.push("SVG sanitization failed - malformed content replaced with empty SVG for security")}o||i.push("SVG contained potentially unsafe content that was sanitized");const a=s!==r;return{textContent:s,rawContent:a?r:void 0,sanitized:!o||a,securityWarnings:i,buffer:e,mimetype:t.mimetype||"image/svg+xml",size:t.size,filename:n}}},vL=new Cie}});async function Lhn(){return(await Promise.resolve().then(()=>(Qoe(),K3))).videoProcessor}async function $hn(){return(await Promise.resolve().then(()=>(Dqt(),eie))).audioProcessor}async function Fhn(){return(await Promise.resolve().then(()=>(sie(),iL))).archiveProcessor}function GKt(e){return d1e(e)}function Uhn(e,t){const r=GKt(e),n=Ol.get(r);if(n&&n.expiresAt>t)return Ol.delete(r),Ol.set(r,n),n.contentType;n&&Ol.delete(r)}function Bhn(e){for(const[t,r]of Ol)r.expiresAt<=e&&Ol.delete(t)}function qKt(e,t,r){if(!t)return;const n=GKt(e);if(Ol.set(n,{contentType:t,expiresAt:r+jKt}),Ol.size>xie&&Bhn(r),Ol.size>xie){const o=Ol.keys().next().value;o!==void 0&&Ol.delete(o)}}function zhn(e){let t=e;for(let r=0;r<6;r++){const n=t instanceof Error?t.cause:void 0;if(!(n instanceof Error))return t;t=n}return t}function Ghn(e){let t,r=e;for(let n=0;n<6&&r instanceof Error;n++){const o=r.code;typeof o=="string"&&(t=o),r=r.cause}return t}function qhn(e){if(!(e instanceof Error))return!1;const t=[];let r=e;for(;r instanceof Error&&t.length<6;)t.push(r),r=r.cause;const n=t.map(a=>a.message).join(" | ").toLowerCase(),o=t.map(a=>a.code).reverse().find(a=>typeof a=="string")?.toUpperCase();if(o&&VKt.includes(o))return!0;const i=n.match(/http\s*(\d{3})/);if(i){const a=parseInt(i[1],10);if(HKt.includes(a))return!1;if(WKt.includes(a))return!0}return["timeout","timed out","connection reset","econnreset","etimedout","network error","socket hang up","enotfound","getaddrinfo","unavailable","service unavailable"].some(a=>n.includes(a))}function jhn(e){const t=e.trim();if(!t)return!1;const r=t[0],n=t[t.length-1];if(!(r==="{"&&n==="}"||r==="["&&n==="]"))return!1;try{return JSON.parse(t),!0}catch{return!1}}function wL(e){return e<1024?`${e} bytes`:e<1024*1024?`${(e/1024).toFixed(2)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(2)} MB`:`${(e/(1024*1024*1024)).toFixed(2)} GB`}function Vhn(e){const t=Udn(e);if(t)return t;const r=v3(e);if(Yre[r]||Hkt[r]||jkt.includes(r))return"text"}function Hhn(e){const t=e.toString("latin1",0,Math.min(e.length,4096)),r=t.match(/mimetype(application\/vnd\.oasis\.opendocument\.[a-z-]+)/);if(r){const n=r[1],o=Xte(n);if(o)return{type:o.fileType,mimeType:n}}if(!t.includes("[Content_Types].xml"))return null;for(const[n,o]of[["xl/","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],["word/","application/vnd.openxmlformats-officedocument.wordprocessingml.document"],["ppt/","application/vnd.openxmlformats-officedocument.presentationml.presentation"]])if(t.includes(n)){const i=Xte(o);if(i)return{type:i.fileType,mimeType:o}}return null}var jKt,xie,Ol,VKt,HKt,WKt,rf,KKt,JKt,XKt,YKt,ZKt,Iie,QKt,eJt=S({"src/lib/utils/fileDetector.ts"(){"use strict";Ti(),Sr(),Kd(),Rl(),Vkt(),q0(),wpn(),Zre(),ZD(),wat(),K0(),A3(),z(),Qkt(),et(),It(),oAt(),nCt(),ene(),jKt=6e4,xie=512,Ol=new Map,VKt=["ETIMEDOUT","ECONNRESET","ECONNREFUSED","ENOTFOUND","ENETUNREACH","EAI_AGAIN","EPIPE","ECONNABORTED","UND_ERR_CONNECT_TIMEOUT","UND_ERR_HEADERS_TIMEOUT","UND_ERR_BODY_TIMEOUT","UND_ERR_SOCKET"],HKt=[400,401,403,404,405],WKt=[429,500,502,503,504],rf=class wt{static DEFAULT_NETWORK_TIMEOUT=3e4;static DEFAULT_HEAD_TIMEOUT=5e3;static DEFAULT_DOCUMENT_TIMEOUT=3e4;static async detectAndProcess(t,r){const n=wt.deriveInputFilename(t),o=wt.deriveInputSize(t);return pt({name:"file.detect_and_process",tracer:Be.file,attributes:{[$e.FILE_NAME]:n,[$e.FILE_SIZE_BYTES]:o}},async i=>{const a=typeof t=="string"&&(t.startsWith("http://")||t.startsWith("https://"))?await wt.loadUrl(t,r):void 0,u=a?{...await wt.detect(a.content,{...r,filenameHint:r?.filenameHint||wt.deriveInputFilename(t)},a.contentType,r?.filenameHint||wt.deriveInputFilename(t)),source:"url"}:await wt.detect(t,r);if(i.setAttribute($e.FILE_CATEGORY,u.type),i.setAttribute($e.FILE_MIMETYPE,u.mimeType||"unknown"),i.setAttribute($e.FILE_CONFIDENCE,u.metadata.confidence),f.info(`[NEUROLINK] File detected: ${n} (${u.mimeType||"unknown"}, ${wL(o)}) \u2192 category: ${u.type}`),r?.allowedTypes&&!r.allowedTypes.includes(u.type)){const d=a?.content??await wt.loadContent(t,u,r),p=[];for(const h of r.allowedTypes)try{const g=await wt.tryFallbackParsing(d,h,r);if(g){f.info(`[FileDetector] \u2705 ${h.toUpperCase()} fallback successful`);const y=typeof g.content=="string"?g.content.length:g.content?.length||0;return i.setAttribute($e.FILE_OUTPUT_LENGTH,y),i.setAttribute($e.FILE_SUCCESS,!0),i.setAttribute($e.FILE_PROCESSOR_USED,`fallback:${h}`),f.info(`[NEUROLINK] File processed: ${n} \u2192 ${y} bytes output (fallback: ${h})`),g}}catch(g){const y=g instanceof Error?g.message:String(g);p.push(`${h}: ${y}`),f.debug(`[FileDetector] ${h} fallback failed: ${y}`)}f.warn(`[FileDetector] All fallback parsing failed for type "${u.type}". Attempted: ${r.allowedTypes.join(", ")}. Falling through to universal handler.`);const m=await wt.processFile(d,u,r);return wt.setFileResultSpanAttributes(i,m,n,u.type),m}const l=a?.content??await wt.loadContent(t,u,r),c=await wt.processFile(l,u,r);return wt.setFileResultSpanAttributes(i,c,n,u.type),c})}static setFileResultSpanAttributes(t,r,n,o){const i=typeof r.content=="string"?r.content.length:r.content?.length||0,s=Array.isArray(r.images)?r.images.length>0:!1,a=Array.isArray(r.images)?r.images.length:0;t.setAttribute($e.FILE_OUTPUT_LENGTH,i),t.setAttribute($e.FILE_SUCCESS,!0),t.setAttribute($e.FILE_PROCESSOR_USED,o),t.setAttribute($e.FILE_HAS_IMAGES,s),t.setAttribute($e.FILE_IMAGE_COUNT,a),f.info(`[NEUROLINK] File processed: ${n} \u2192 ${i} bytes output`+(a>0?` + ${a} image(s)`:"")+` (processor: ${o})`)}static deriveInputFilename(t){if(typeof t=="string"){if(t.startsWith("data:"))return"data-uri";if(t.startsWith("http"))try{return new URL(t).pathname.split("/").pop()||"url-file"}catch{return"url-file"}return t.split("/").pop()||t.split("\\").pop()||"file"}return Buffer.isBuffer(t)?"buffer":t?.filename||"unknown-input"}static deriveInputSize(t){if(Buffer.isBuffer(t))return t.length;if(typeof t=="string"){if(t.startsWith("data:")){const r=t.split(",")[1];return r?Math.floor(r.length*3/4):0}return t.length}return 0}static deriveInputSource(t){return Buffer.isBuffer(t)?"buffer":typeof t=="string"?t.startsWith("data:")?"datauri":t.startsWith("http://")||t.startsWith("https://")?"url":"path":"buffer"}static async tryFallbackParsing(t,r,n){switch(f.info(`[FileDetector] Attempting ${r.toUpperCase()} fallback parsing`),r){case"csv":{const o=n?.csvOptions,i=await vA.process(t,o);return f.info(`[FileDetector] CSV fallback: ${i.metadata?.rowCount||0} rows, ${i.metadata?.columnCount||0} columns`),i}case"text":{const o=t.toString("utf-8");if(wt.isValidText(o))return{type:"text",content:o,mimeType:wt.guessTextMimeType(o),metadata:{confidence:70,size:t.length}};throw new Error("Content does not appear to be valid text")}case"image":throw new Error("Image type requires binary detection, cannot fallback parse");case"pdf":throw new Error("PDF type requires binary detection, cannot fallback parse");case"audio":throw new Error("Audio type requires binary detection, cannot fallback parse");case"video":throw new Error("Video type requires binary detection, cannot fallback parse");case"archive":throw new Error("Archive type requires binary detection, cannot fallback parse");case"xlsx":throw new Error("Excel type requires binary detection, cannot fallback parse");case"docx":throw new Error("Word type requires binary detection, cannot fallback parse");case"pptx":throw new Error("PowerPoint type requires binary detection, cannot fallback parse");case"svg":{const o=t.toString("utf-8");if(o.includes("<svg")&&o.includes("</svg>"))return{type:"svg",content:o,mimeType:"image/svg+xml",metadata:{confidence:70,size:t.length}};throw new Error("Content does not appear to be valid SVG")}default:return null}}static isValidText(t){if(t.includes("\0"))return!1;let r=0;for(let n=0;n<t.length;n++){const o=t.charCodeAt(n);(o>=32&&o<127||o===9||o===10||o===13||o>127)&&r++}return r/t.length>=.9}static guessTextMimeType(t){const r=t.trim();if(r.startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))try{return JSON.parse(r),"application/json"}catch{}return wt.looksLikeXMLStrict(r)?r.includes("<!DOCTYPE html")||r.toLowerCase().includes("<html")||r.includes("<head")||r.includes("<body")?"text/html":"application/xml":wt.looksLikeYAMLStrict(r)?"application/yaml":"text/plain"}static looksLikeYAMLStrict(t){if(t.length===0)return!1;const r=t.split(`
846
846
  `);if(r.length===1)return t==="---"||t==="...";const n=[];n.push(t.startsWith("---")),n.push(/^\.\.\.$|[\n]\.\.\.$/.test(t)),n.push(/^[\s]*-\s+[^-]/m.test(t));const o=/^[\s]*[a-zA-Z_][a-zA-Z0-9_-]*:\s*(.+)$/,i=r.filter(a=>o.test(a)).length;return n.push(i>=2),n.filter(Boolean).length>=2}static looksLikeXMLStrict(t){if(t.startsWith("<?xml"))return!0;if(!t.startsWith("<"))return!1;if(t.includes("<!DOCTYPE html"))return!0;if(!/<[a-zA-Z][a-zA-Z0-9-]*(?:\s[^>]*)?>/.test(t))return!1;const n=/<\/[a-zA-Z][a-zA-Z0-9-]*>/.test(t),o=/<[a-zA-Z][a-zA-Z0-9-]*(?:\s[^>]*)?\s*\/\s*>/.test(t);return n||o}static async detect(t,r,n,o){const i=eAt(r?.mimetypeHint);if(i){const c=tAt(i);if(c){const d=rAt(i),p={type:c,mimeType:i,extension:d||null,source:wt.deriveInputSource(t),metadata:{confidence:95,filename:r?.filenameHint||wt.deriveInputFilename(t),size:wt.deriveInputSize(t)}};return f.info(`[FileDetector] Type: ${c} (95%, from mimetype hint: ${i})`),p}}const s=r?.confidenceThreshold??80,a=[new YKt,new ZKt(n,oa(r)),new Iie,new QKt];let u=null,l="none";for(const c of a){const d=c.constructor.name,p=await c.detect(c instanceof Iie&&o?o:t);if((!u||p.metadata.confidence>u.metadata.confidence)&&(u=p,l=d),p.metadata.confidence>=s)return f.info(`[FileDetector] Type: ${p.type} (${p.metadata.confidence}%, strategy: ${d})`),wt.withResolvedExtension(p,t,r)}return!u||u.type==="unknown"?f.error(`[FileDetector] Detection failed: no strategy identified a type (best: ${l}, ${u?.metadata.confidence??0}%, threshold ${s}%)`):f.debug(`[FileDetector] Best-effort type below threshold: ${u.type} (${u.metadata.confidence}%, threshold ${s}%, strategy: ${l})`),wt.withResolvedExtension(u,t,r)}static withResolvedExtension(t,r,n){if(!t)return t;const o=n?.filenameHint||t.metadata?.filename||wt.deriveInputFilename(r);if(!o)return t;const i=o.split(/[\\/]/).pop()??o,s=i.lastIndexOf("."),a=t.extension??(s>0&&s<i.length-1?i.slice(s+1).toLowerCase():null),u=t.metadata&&!t.metadata.filename?{...t.metadata,filename:i}:t.metadata;return a===t.extension&&u===t.metadata?t:{...t,extension:a,metadata:u}}static async loadContent(t,r,n){let o=r.source;switch(o==="buffer"&&!Buffer.isBuffer(t)&&typeof t=="string"&&(t.startsWith("data:")?o="datauri":t.startsWith("http://")||t.startsWith("https://")?o="url":o="path"),o){case"url":return await wt.loadFromURL(t,n);case"path":return await wt.loadFromPath(t,n);case"buffer":return t;case"datauri":return wt.loadFromDataURI(t);default:throw new Error(`Unknown source: ${o}`)}}static describeKeyframe(t,r){if(!(typeof t!="number"||!Number.isFinite(t)))return`Video keyframe at ${oCt(t)} into a ${r} video`}static formatInformativePlaceholder(t,r,n,o,i){const s=n.length<1024?`${n.length} bytes`:n.length<1048576?`${(n.length/1024).toFixed(1)} KB`:`${(n.length/1048576).toFixed(1)} MB`,a=i instanceof Error?i.message:i?String(i):"Processing returned no usable content";return`[${t} File: "${r}"]
847
847
  Size: ${s}
848
848
  Format: ${o.mimeType||"unknown"}
@@ -244,7 +244,11 @@ export function sanitizeSvgContentDetailed(svgContent) {
244
244
  let content = svgContent;
245
245
  const originalContent = svgContent;
246
246
  // 1. Block DOCTYPE and ENTITY declarations (XXE prevention)
247
- if (content.includes("<!DOCTYPE") || content.includes("<!ENTITY")) {
247
+ // Case-insensitive check to prevent XXE bypass via mixed/lowercase declarations (<!doctype, <!entity)
248
+ const upperContent = content.toUpperCase();
249
+ if (upperContent.includes("<!DOCTYPE") ||
250
+ upperContent.includes("<!ENTITY") ||
251
+ /<!\s*(?:doctype|entity)/i.test(content)) {
248
252
  throw new Error("SVG contains DOCTYPE or ENTITY declarations which are not allowed for security reasons");
249
253
  }
250
254
  // 2. Remove XML stylesheet processing instructions
@@ -436,7 +440,9 @@ export function isSvgContentSafe(svgContent) {
436
440
  }
437
441
  const lowerContent = svgContent.toLowerCase();
438
442
  // Check for XXE
439
- if (lowerContent.includes("<!doctype") || lowerContent.includes("<!entity")) {
443
+ if (lowerContent.includes("<!doctype") ||
444
+ lowerContent.includes("<!entity") ||
445
+ /<!\s*(?:doctype|entity)/i.test(svgContent)) {
440
446
  return false;
441
447
  }
442
448
  // Check for dangerous elements
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "13.8.20",
3
+ "version": "13.8.21",
4
4
  "packageManager": "pnpm@10.34.7+sha512.upirxYVTmTM3W1lx9LxtbHOhtLftxKh559EC/lQj0eAjCdZ8YKEfBJVQk6luUhrZw7E4zdZUylvlY/N4s65IvQ==",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
6
6
  "author": {