'use strict'; // Final native request headers are scanned in privileged code before release. // No values, names or credential fingerprints are returned as diagnostic facts. const MAX_HEADERS=128,MAX_BYTES=65536; function snapshotHeaders(input,policy){ if(!input||typeof input!=='object'||Array.isArray(input)||![Object.prototype,null].includes(Object.getPrototypeOf(input)))throw Error('headers-uninspectable'); const entries=Object.entries(Object.getOwnPropertyDescriptors(input)); if(entries.length>MAX_HEADERS)throw Error('headers-size-limit'); const headers=Object.create(null),values=[],lines=[];let bytes=0; const limit=Math.min(MAX_BYTES,policy.dlp.maxBytes); for(const [name,descriptor]of entries){ if(!('value'in descriptor)||!/^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,256}$/.test(name)||typeof descriptor.value!=='string')throw Error('headers-uninspectable'); const value=descriptor.value; if(value.length>limit)throw Error('headers-size-limit'); if(/[\x00-\x08\x0A-\x1F\x7F]|[\uD800-\uDFFF]/u.test(value))throw Error('headers-uninspectable'); bytes+=Buffer.byteLength(name)+Buffer.byteLength(value)+4; if(bytes>limit)throw Error('headers-size-limit'); headers[name]=value;values.push(value);lines.push(`${name}: ${value}`); } return {headers:Object.freeze(headers),values,lines,bytes,count:entries.length}; } async function inspectHeaders(snapshot,{policy,inspect,inspectLocal,inspectEnterprise,isCurrent}){ const blocked=ruleId=>({decision:'block',ruleId}); if(!isCurrent())return blocked('policy-changed'); // Individual values preserve exact registered fingerprints. The joined value // view also catches a literal split across multiple distinct header fields. for(const text of [...snapshot.values,snapshot.values.join(''),snapshot.lines.join('\r\n')]){ const bytes=Buffer.from(text); try{const verdict=inspect(bytes,policy);if(verdict.decision!=='allow')return verdict;} finally{bytes.fill(0);} } const bytes=Buffer.from(snapshot.lines.join('\r\n')); try{ if(policy.dlp.semantic.enabled||policy.security.yara.enabled){ if(!inspectLocal)return blocked('inspector-unavailable'); const verdict=await inspectLocal(bytes,policy); if(!isCurrent())return blocked('policy-changed'); if(verdict.decision!=='allow')return verdict; if(verdict.coverage?.complete!==true)return blocked('inspection-incomplete'); } if(inspectEnterprise){ const verdict=await inspectEnterprise(bytes,policy); if(!isCurrent())return blocked('policy-changed'); if(verdict.decision!=='allow')return verdict; if(verdict.coverage?.complete!==true)return blocked('inspection-incomplete'); } return isCurrent()?{decision:'allow',ruleId:null}:blocked('policy-changed'); }finally{bytes.fill(0);} } module.exports={snapshotHeaders,inspectHeaders,MAX_HEADERS,MAX_BYTES};