Add packaged DLP broker and protected Windows service foundation
This commit is contained in:
1 parent
95d23f4e0b
commit
7b5057901a
140 files changed
+11215
-60
No files matched your search
@@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
const {GateError}=require('./http-request-gate.cjs');
|
||||
const allowed=new Set(['content-disposition','content-type','content-language','cache-control','expires','last-modified','etag','location','set-cookie','vary','content-security-policy','content-security-policy-report-only','referrer-policy','permissions-policy','x-content-type-options','x-frame-options','strict-transport-security']);
|
||||
const invalid=value=>typeof value!=='string'||value.length>8192||[...value].some(character=>character.charCodeAt(0)<32&&character!=='\t'||character.charCodeAt(0)===127);
|
||||
|
||||
/** Provisional buffered response. No streaming/compression forwarding.
|
||||
* Content-Length is recomputed from a private body copy. Hop-by-hop and
|
||||
* unrecognized headers are never forwarded. Set-Cookie may be a bounded
|
||||
* string array; values are forwarded separately without comma combining.
|
||||
*/
|
||||
function validateResponse(record,maxBytes=1048576) {
|
||||
if(!record||!Number.isSafeInteger(record.statusCode)||record.statusCode<200||record.statusCode>599||!Number.isSafeInteger(maxBytes)||maxBytes<0||!Buffer.isBuffer(record.body)||record.body.length>maxBytes||!record.headers||typeof record.headers!=='object'||Array.isArray(record.headers))throw new GateError('invalid-upstream-response');
|
||||
const headers=Object.create(null);
|
||||
const seen=new Set(),hop=new Set();
|
||||
for(const [key,value] of Object.entries(record.headers))if(key.toLowerCase()==='connection') {
|
||||
if(invalid(value))throw new GateError('invalid-upstream-response');
|
||||
for(const token of value.split(',')){if(!/^[a-zA-Z0-9-]+$/.test(token.trim()))throw new GateError('invalid-upstream-response');hop.add(token.trim().toLowerCase());}
|
||||
}
|
||||
let size=0;
|
||||
for(const [key,value] of Object.entries(record.headers)) {
|
||||
if(!/^[a-zA-Z0-9-]+$/.test(key))throw new GateError('invalid-upstream-response');
|
||||
const name=key.toLowerCase();
|
||||
if(seen.has(name))throw new GateError('invalid-upstream-response');seen.add(name);
|
||||
if(name==='content-encoding'&&value!==undefined&&value!=='identity')throw new GateError('unsupported-upstream-encoding');
|
||||
if(!allowed.has(name)||hop.has(name))continue;
|
||||
const values=Array.isArray(value)?value:[value];
|
||||
if(values.length>32||(Array.isArray(value)&&name!=='set-cookie')||values.some(invalid))throw new GateError('invalid-upstream-response');
|
||||
size+=key.length+values.reduce((sum,item)=>sum+item.length,0);
|
||||
if(size>32768)throw new GateError('invalid-upstream-response');
|
||||
headers[name]=Array.isArray(value)?Object.freeze([...value]):value;
|
||||
}
|
||||
if((record.statusCode===204||record.statusCode===304)&&record.body.length)throw new GateError('invalid-upstream-response');
|
||||
const body=Buffer.from(record.body);
|
||||
headers['content-length']=String(body.length);headers.connection='close';
|
||||
return Object.freeze({statusCode:record.statusCode,headers:Object.freeze(headers),body});
|
||||
}
|
||||
module.exports={validateResponse};
|
||||
Reference in new issue
Block a user