mirror of
https://github.com/wekan/wekan.git
synced 2026-11-07 02:52:33 -05:00
Per correction: use only the existing WeKan database via Meteor JavaScript
queries (works on FerretDB and MongoDB); do not create files/DBs under
WRITABLE_PATH; and have FerretDB report problems to WeKan rather than writing
itself.
- models/eventLog.js: one `eventlog` collection (stream: security|speed|tests).
- server/lib/{securityLog,speedLog,testLog}.js: thin wrappers that insert one
document via EventLog.insertAsync (fire-and-forget, never throw).
- models/lib/securityLogFormat.js slimmed to just sanitizeDetail; remove the
node:sqlite event store (server/lib/eventStore.js) and all file/path/schema
helpers.
- Add a Tests stream: log anything that would fail an existing WeKan test.
- Design docs (WeKan.md, FerretDB.md) rewritten: DB-collection storage, grouped
counts for the summary, Admin Reports read the collection, and FerretDB reports
problems to WeKan which records them (no FerretDB DB/file writes).
- tests/securityLog.test.cjs updated (sanitizer + catalog + collection wiring +
no-filesystem guards); verified via Python mirror.
53 lines
2.1 KiB
JavaScript
53 lines
2.1 KiB
JavaScript
// ============================================================================
|
|
// WeKan security event logger (design: docs/Security/Remediation/WeKan.md)
|
|
// ----------------------------------------------------------------------------
|
|
// Single choke point every runtime security guard funnels through when it
|
|
// BLOCKS, SANITIZES or REMEDIATES a request (SSRF rejection, XSS scheme drop,
|
|
// forged-XFF ignore, export-authz denial, invite rate-limit, attachment/avatar
|
|
// upload rejection or sanitization, …).
|
|
//
|
|
// Records one document into the EXISTING WeKan database via a normal Meteor
|
|
// JavaScript query (models/eventLog.js, stream:'security'). No new files/DBs, so
|
|
// it works the same on FerretDB and MongoDB. BEST-EFFORT and NEVER throws into the
|
|
// caller: the insert is fire-and-forget and any error is swallowed. Server-only.
|
|
// ============================================================================
|
|
|
|
import EventLog from '/models/eventLog';
|
|
const { categoryFor } = require('/models/lib/securityCategories');
|
|
const { sanitizeDetail } = require('/models/lib/securityLogFormat');
|
|
|
|
function insert(doc) {
|
|
try {
|
|
const p = EventLog.insertAsync(doc);
|
|
if (p && typeof p.catch === 'function') p.catch(() => {});
|
|
} catch (e) {
|
|
if (process.env.DEBUG === 'true') console.warn('securityLog insert failed:', e && e.message);
|
|
}
|
|
}
|
|
|
|
// Record one security event. Never throws. Pass a catalog `key` (see
|
|
// models/lib/securityCategories) and/or explicit fields; explicit wins.
|
|
export function record(evt = {}) {
|
|
try {
|
|
const base = evt.key ? categoryFor(evt.key) : {};
|
|
const m = { ...base, ...evt };
|
|
const doc = {
|
|
stream: 'security',
|
|
at: new Date(),
|
|
severity: m.severity || 'info',
|
|
category: m.category || 'unknown',
|
|
bleed: m.bleed || 'Generic',
|
|
action: m.action || 'detected',
|
|
source: m.source || '',
|
|
cwe: m.cwe || '',
|
|
detail: sanitizeDetail(m.detail),
|
|
};
|
|
if (m.userId || m.userid) doc.userId = String(m.userId || m.userid);
|
|
insert(doc);
|
|
} catch (e) {
|
|
if (process.env.DEBUG === 'true') console.warn('securityLog.record failed:', e && e.message);
|
|
}
|
|
}
|
|
|
|
export default { record };
|