Implement managed browser security, individual agents and observability
This commit is contained in:
1 parent
ff482ebe23
commit
ea448de2d4
172 files changed
+5404
-347
No files matched your search
@@ -0,0 +1,50 @@
|
||||
'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};
|
||||
Reference in new issue
Block a user