Harden Windows DLP enforcement and Electron runtime packaging
This commit is contained in:
1 parent
e7d778aeac
commit
8a253eda89
120 files changed
+3569
-135
No files matched your search
@@ -2,6 +2,7 @@ import {z} from 'zod';
|
||||
import {randomUUID} from 'node:crypto';
|
||||
const statuses=['open','investigating','resolved','dismissed'],severities=['low','medium','high','critical'];
|
||||
const positive=z.coerce.number().int().positive().max(Number.MAX_SAFE_INTEGER);
|
||||
// eslint-disable-next-line no-control-regex -- Explicitly reject control characters in security-sensitive input.
|
||||
const note=z.string().trim().min(1).max(1000).refine(v=>!/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/.test(v),'Control characters are forbidden');
|
||||
const allowedMetadata=['decision','ruleId','policyVersion','version','host','level','sourceEventId','contentType','classification','coverage'];
|
||||
function safeEvent(row){if(!row)return null;const input=JSON.parse(row.metadata),metadata={};for(const key of allowedMetadata){const v=input[key];if(typeof v==='string'&&v.length<=256)metadata[key]=v;else if(typeof v==='number'&&Number.isSafeInteger(v))metadata[key]=v;}return {id:row.id,time:row.time,kind:row.kind,deviceId:row.device_id,metadata};}
|
||||
@@ -17,6 +18,7 @@ export function installIncidents(app,store){
|
||||
app.get('/api/admin/incidents',(req,res)=>{const q=z.object({status:z.enum(statuses).optional(),severity:z.enum(severities).optional(),before:positive.optional(),limit:z.coerce.number().int().min(1).max(100).default(50)}).strict().parse(req.query),conditions=[],values=[];for(const key of ['status','severity'])if(q[key]){conditions.push(`${key}=?`);values.push(q[key]);}if(q.before){conditions.push('seq<?');values.push(q.before);}const rows=db.prepare(`SELECT * FROM incident_cases ${conditions.length?'WHERE '+conditions.join(' AND '):''} ORDER BY seq DESC LIMIT ?`).all(...values,q.limit+1),more=rows.length>q.limit;rows.length=Math.min(rows.length,q.limit);res.json({incidents:rows.map(view),nextBefore:more?rows.at(-1).seq:null});});
|
||||
app.get('/api/admin/incidents/:id',(req,res)=>{const row=find(req.params.id);if(!row)return res.status(404).json({error:'Incident not found'});res.json({...view(row),history:db.prepare('SELECT revision,time,actor,status,severity,assignee,comment FROM incident_changes WHERE case_id=? ORDER BY revision').all(row.id)});});
|
||||
app.post('/api/admin/incidents',(req,res)=>{const b=z.object({eventId:positive,severity:z.enum(severities).default('medium')}).strict().parse(req.body),source=db.prepare('SELECT * FROM events WHERE id=?').get(b.eventId);if(!source)return res.status(404).json({error:'Security event not found'});if(source.kind.startsWith('incident.'))return res.status(400).json({error:'Incident audit events cannot create incidents'});if(db.prepare('SELECT id FROM incident_cases WHERE event_id=?').get(b.eventId))return res.status(409).json({error:'Event already linked to an incident'});const time=new Date().toISOString(),row={id:randomUUID(),event_id:b.eventId,revision:1,status:'open',severity:b.severity,assignee:null,created_at:time,updated_at:time};transaction(()=>{db.prepare('INSERT INTO incident_cases(id,event_id,revision,status,severity,assignee,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?)').run(row.id,row.event_id,1,row.status,row.severity,null,time,time);append(row,req.principal.sub);store.event(source.device_id,'incident.created',{actor:req.principal.sub,incidentId:row.id,sourceEventId:b.eventId,revision:1,status:'open',severity:row.severity});});res.status(201).json(view(row));});
|
||||
// eslint-disable-next-line no-control-regex -- Explicitly reject control characters in security-sensitive input.
|
||||
app.patch('/api/admin/incidents/:id',(req,res)=>{const b=z.object({expectedRevision:positive,status:z.enum(statuses).optional(),severity:z.enum(severities).optional(),assignee:z.string().trim().min(1).max(160).refine(v=>!/[\u0000-\u001f\u007f]/.test(v),'Control characters are forbidden').nullable().optional(),comment:note.optional()}).strict().parse(req.body),row=find(req.params.id);if(!row)return res.status(404).json({error:'Incident not found'});if(row.revision!==b.expectedRevision)return res.status(409).json({error:'Incident revision conflict',currentRevision:row.revision});if(row.revision>=1000)return res.status(409).json({error:'Incident history limit reached'});const next={...row,...Object.fromEntries(['status','severity','assignee'].filter(k=>Object.hasOwn(b,k)).map(k=>[k,b[k]])),revision:row.revision+1,updated_at:new Date().toISOString()};if(!b.comment&&['status','severity','assignee'].every(k=>next[k]===row[k]))return res.status(400).json({error:'No incident change supplied'});transaction(()=>{const change=db.prepare('UPDATE incident_cases SET revision=?,status=?,severity=?,assignee=?,updated_at=? WHERE id=? AND revision=?').run(next.revision,next.status,next.severity,next.assignee,next.updated_at,row.id,b.expectedRevision);if(change.changes!==1)throw Object.assign(Error('Incident revision conflict'),{status:409});append(next,req.principal.sub,b.comment);store.event(null,'incident.updated',{actor:req.principal.sub,incidentId:row.id,sourceEventId:row.event_id,revision:next.revision,status:next.status,severity:next.severity,...(b.comment?{commentLength:b.comment.length}:{})});});res.json(view(next));});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user