first commit
This commit is contained in:
commit
ff482ebe23
251 files changed
+19126
No files matched your search
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
const fs=require('node:fs');
|
||||
const {createHash}=require('node:crypto');
|
||||
const {detectType,inspectFileTransfer}=require('../../packages/core/file-transfer.cjs');
|
||||
const CHANNELS={upload:'scanUploads',download:'scanDownloads',clipboard:'scanClipboard',ai:'scanAI'};
|
||||
function icapRequired(policy,channel){if(!Object.hasOwn(CHANNELS,channel))throw Error('Unsupported enterprise inspection channel');const settings=policy.enterprise?.icap;return !!settings?.enabled&&settings[CHANNELS[channel]]!==false;}
|
||||
function deploymentTLS(){
|
||||
const options={};for(const [key,name] of [['ca','SAFETYNET_ICAP_CA_FILE'],['cert','SAFETYNET_ICAP_CERT_FILE'],['key','SAFETYNET_ICAP_KEY_FILE']]){if(process.env[name]){const stat=fs.statSync(process.env[name]);if(!stat.isFile()||stat.size>131072)throw Error('Enterprise scanner certificate configuration unavailable');options[key]=fs.readFileSync(process.env[name]);}}
|
||||
if(!!options.cert!==!!options.key)throw Error('Enterprise scanner client identity incomplete');return options;
|
||||
}
|
||||
async function scanEnterprise(bytes,policy,channel,scanner){
|
||||
const digest=createHash('sha256').update(bytes).digest('hex');
|
||||
const base={engine:'icap',sha256:digest,bytes:bytes.length,coverage:{complete:false},decision:'block',ruleId:'icap-unavailable'};
|
||||
if(!icapRequired(policy,channel))return {...base,engine:'not-required',decision:'allow',ruleId:null,coverage:{complete:true}};
|
||||
const snapshot=Buffer.from(bytes);
|
||||
try{
|
||||
const result=await (scanner||require('./icap-client.cjs').scanIcap)(snapshot,policy.enterprise.icap,deploymentTLS());
|
||||
if(result.decision==='allow'&&result.coverage?.complete===true&&result.sha256===digest&&result.bytes===snapshot.length&&createHash('sha256').update(snapshot).digest('hex')===digest)return {...base,...result};
|
||||
return {...base,ruleId:typeof result.ruleId==='string'&&/^icap-[a-z0-9-]{1,80}$/.test(result.ruleId)?result.ruleId:'icap-inspection-incomplete'};
|
||||
}catch{return base;}
|
||||
finally{snapshot.fill(0);}
|
||||
}
|
||||
async function scanDownloadEnterprise(bytes,policy,localInspector,scanner){
|
||||
const digest=createHash('sha256').update(bytes).digest('hex');
|
||||
const blocked=ruleId=>({decision:'block',ruleId,engine:'enterprise',sha256:digest,bytes:bytes.length,coverage:{complete:false}});
|
||||
const fileVerdict=inspectFileTransfer(bytes,policy,'download');if(fileVerdict.decision!=='allow')return blocked(fileVerdict.ruleId);
|
||||
const noAv=!policy.security?.yara.enabled&&!icapRequired(policy,'download');
|
||||
if(noAv&&!policy.fileTransfers?.download?.allowWithoutMalwareScanner)return blocked('malware-scanner-required');
|
||||
// Antivirus clean does not classify company secrets. Supported documents always
|
||||
// require the contained DLP parser; explicit no-antivirus mode still requires DLP.
|
||||
if(noAv||policy.dlp?.semantic?.enabled||['pdf','zip','png','jpeg','gif','webp','text'].includes(detectType(bytes))){
|
||||
if(!localInspector?.inspect)return blocked('download-dlp-unavailable');
|
||||
let dlp;try{dlp=await localInspector.inspect(bytes,policy);}catch{return blocked('download-dlp-unavailable');}
|
||||
if(dlp.decision!=='allow')return blocked(typeof dlp.ruleId==='string'?dlp.ruleId:'download-dlp-blocked');
|
||||
if(dlp.coverage?.complete!==true)return blocked('download-dlp-incomplete');
|
||||
}
|
||||
if(noAv)return {decision:'allow',ruleId:null,engine:'explicit-no-antivirus',sha256:digest,bytes:bytes.length,coverage:{complete:true}};
|
||||
if(policy.security?.yara.enabled){
|
||||
if(!localInspector)return blocked('yara-unavailable');
|
||||
let local;try{local=await localInspector.scanDownload(bytes,policy);}catch{return blocked('yara-unavailable');}
|
||||
if(local.decision!=='allow')return local;
|
||||
if(local.coverage?.complete!==true||local.sha256!==digest||local.bytes!==bytes.length)return blocked('yara-inspection-incomplete');
|
||||
if(!icapRequired(policy,'download'))return local;
|
||||
}
|
||||
return scanEnterprise(bytes,policy,'download',scanner);
|
||||
}
|
||||
module.exports={icapRequired,scanEnterprise,scanDownloadEnterprise,deploymentTLS};
|
||||
Reference in new issue
Block a user