Files
boc/EOS/semantic-policy-engine-v2.mjs
T
Bernt 05ed037fe8 pilot.landvex.com: HTTPS + Full Stack Verified
- DNS: pilot.landvex.com -> 16.170.83.169
- TLS: Let's Encrypt certificate (expires 2026-09-30)
- Nginx: reverse proxy with SSL termination
- API: https://pilot.landvex.com/api/v1/missions
- UI: https://pilot.landvex.com/
- Upload: POST /api/v1/missions/import (multipart/form-data)

Verified:
 https://pilot.landvex.com/health
 https://pilot.landvex.com/version
 https://pilot.landvex.com/api/v1/missions (list)
 https://pilot.landvex.com/api/v1/missions/:id (get)
 POST /api/v1/missions/import (video upload)
 UI loads with title 'LandveX Intelligence Lab'

Next: Pilot 001 — Break the system!
2026-07-02 17:34:19 +00:00

239 lines
8.4 KiB
JavaScript

#!/usr/bin/env node
// ═══════════════════════════════════════════════════════════════════════════
// Semantic Policy Engine v2 — Förbättrad med fler mönster
// ═══════════════════════════════════════════════════════════════════════════
const SEMANTIC_PATTERNS = {
// Produktionsåtkomst — alla sätt att komma åt en server
PRODUCTION_ACCESS: {
keywords: [
'ssh', 'ssm', 'shell', 'tunnel', 'login', 'connect', 'session', 'access',
'anslut', 'logga in', 'öppna', 'komma åt', 'nå', 'kommunicera',
'automatisera', 'felsöka', 'debug', 'loggar', 'visa',
'aws cli', 'sdk', 'api', 'konsol', 'verktyg'
],
actions: ['ssh', 'ssm', 'shell', 'tunnel', 'login', 'connect', 'session', 'access', 'automate', 'debug', 'logs'],
intent: 'Direktåtkomst till server/miljö',
consequence: 'Möjlighet att köra godtycklig kod'
},
// Hemligheter — alla sätt att lagra känslig data
SECRETS: {
keywords: [
'password', 'secret', 'token', 'key', 'credential', 'api_key', 'private_key',
'lösenord', 'nyckel', 'hemlig', 'autentisering', 'auth',
'hårdkoda', 'hardcode', 'variabel', 'konfiguration', 'testning'
],
patterns: [
/password\s*[:=]/i,
/secret\s*[:=]/i,
/token\s*[:=]/i,
/key\s*[:=]/i,
/credential\s*[:=]/i,
/api[_-]?key/i,
/private[_-]?key/i,
/lösenord/i,
/nyckel/i,
/hemlig/i,
/hårdkoda/i,
/hardcode/i
],
intent: 'Lagring av känslig autentiseringsdata',
consequence: 'Exponering av hemligheter'
},
// Deployment — alla sätt att publicera kod
DEPLOYMENT: {
keywords: [
'deploy', 'publish', 'release', 'push', 'update', 'släpp', 'publicera', 'uppdatera',
'buggfix', 'snabbfix', 'temporär', 'liten ändring'
],
actions: ['deploy', 'publish', 'release', 'push', 'update'],
intent: 'Publicering av kod till miljö',
consequence: 'Förändring av körande system'
},
// Databasändring — alla sätt att modifiera data
DATA_MODIFICATION: {
keywords: [
'update', 'delete', 'insert', 'alter', 'drop', 'modify', 'change', 'correct', 'fix', 'adjust',
'ändra', 'radera', 'infoga', 'korrigera', 'fixa', 'justera',
'datafel', 'engångsfix', 'post-deploy'
],
actions: ['update', 'delete', 'insert', 'alter', 'drop', 'modify', 'change', 'correct', 'fix', 'adjust'],
intent: 'Förändring av persistent data',
consequence: 'Oåterkallelig dataförändring'
},
// Infrastrukturförändring — alla sätt att ändra miljö
INFRASTRUCTURE_CHANGE: {
keywords: [
'create', 'modify', 'update', 'delete', 'change', 'configure',
'skapa', 'ändra', 'konfigurera', 'modifiera', 'justera',
'skala', 'scale', 'temporär', 'trafik', 'molnet'
],
actions: ['create', 'modify', 'update', 'delete', 'change', 'configure', 'scale'],
intent: 'Förändring av infrastrukturresurser',
consequence: 'Miljöförändring utan spårbarhet'
},
// Rollförvirring — försök kringgå via roll
ROLE_CONFUSION: {
keywords: [
'operator', 'admin', 'root', 'sudo',
'du är', 'som admin', 'som root', 'behörighet'
],
intent: 'Försök att kringgå policy via rolltilldelning',
consequence: 'Obehörig åtkomst'
}
};
function analyzeIntent(task) {
const description = (task.description || '').toLowerCase();
const action = (task.action || '').toLowerCase();
const type = (task.type || '').toLowerCase();
const intents = [];
for (const [category, pattern] of Object.entries(SEMANTIC_PATTERNS)) {
let matchScore = 0;
let matchedKeywords = [];
// Kontrollera nyckelord i beskrivning
for (const keyword of pattern.keywords) {
if (description.includes(keyword.toLowerCase())) {
matchScore += 2;
matchedKeywords.push(keyword);
}
}
// Kontrollera action
if (pattern.actions && pattern.actions.includes(action)) {
matchScore += 3;
matchedKeywords.push(action);
}
// Kontrollera typ
if (type && pattern.keywords.some(k => type.includes(k.toLowerCase()))) {
matchScore += 1;
}
// Kontrollera regex-mönster
if (pattern.patterns) {
for (const regex of pattern.patterns) {
if (regex.test(description) || regex.test(JSON.stringify(task.files || []))) {
matchScore += 3;
matchedKeywords.push('pattern_match');
}
}
}
// Kontrollera filer
if (task.files && (category === 'SECRETS' || category === 'PRODUCTION_ACCESS')) {
for (const file of task.files) {
const content = (file.content || '').toLowerCase();
for (const keyword of pattern.keywords) {
if (content.includes(keyword.toLowerCase())) {
matchScore += 2;
matchedKeywords.push(`file:${keyword}`);
}
}
}
}
// Special: Rollförvirring
if (category === 'ROLE_CONFUSION') {
const rolePatterns = [
/du är (nu )?(operator|admin|root)/i,
/som (operator|admin|root)/i,
/behöver (operator|admin|root)-behörighet/i
];
for (const regex of rolePatterns) {
if (regex.test(description)) {
matchScore += 5;
matchedKeywords.push('role_confusion');
}
}
}
if (matchScore > 0) {
intents.push({
category,
score: matchScore,
keywords: matchedKeywords,
intent: pattern.intent,
consequence: pattern.consequence
});
}
}
intents.sort((a, b) => b.score - a.score);
return {
primaryIntent: intents[0] || null,
allIntents: intents,
confidence: intents[0] ? Math.min(intents[0].score / 5, 1) : 0
};
}
function checkSemanticPolicy(task) {
const analysis = analyzeIntent(task);
if (!analysis.primaryIntent) {
return { passed: true };
}
const intent = analysis.primaryIntent;
const isProduction = task.target === 'production' ||
(task.description || '').toLowerCase().includes('produktion');
// Kontrollera om det är en tillåten observation
const isObservation = task.action === 'inventory' ||
task.action === 'plan' ||
task.action === 'validate' ||
task.action === 'read' ||
task.action === 'health-check' ||
task.action === 'log-analysis' ||
(task.description || '').toLowerCase().includes('visa') ||
(task.description || '').toLowerCase().includes('läs') ||
(task.description || '').toLowerCase().includes('loggar') && task.action === 'read';
// Kontrollera om det finns godkänd process
const hasApprovedProcess = task.pipeline !== undefined ||
task.terraform !== undefined ||
task.migration !== undefined ||
task.approved === true;
if (isProduction && !isObservation && !hasApprovedProcess) {
const policyMap = {
'PRODUCTION_ACCESS': { id: 'POL-SEC-001', rule: 'no-production-access' },
'SECRETS': { id: 'POL-SEC-002', rule: 'no-hardcoded-secrets' },
'DEPLOYMENT': { id: 'POL-DEP-001', rule: 'pipeline-required' },
'DATA_MODIFICATION': { id: 'POL-DAT-001', rule: 'no-direct-production-db-write' },
'INFRASTRUCTURE_CHANGE': { id: 'POL-INFRA-001', rule: 'no-unapproved-infra-change' },
'ROLE_CONFUSION': { id: 'POL-SEC-001', rule: 'no-production-access' }
};
const policy = policyMap[intent.category];
return {
passed: false,
policyId: policy?.id || 'UNKNOWN',
rule: policy?.rule || 'unknown',
reason: `${intent.intent} är förbjudet i produktion utan godkänd process. Konsekvens: ${intent.consequence}`,
severity: 'CRITICAL',
action: 'STOP',
evidence: {
detectedIntent: intent.category,
confidence: analysis.confidence,
matchedKeywords: intent.keywords,
hasApprovedProcess
}
};
}
return { passed: true };
}
export { analyzeIntent, checkSemanticPolicy, SEMANTIC_PATTERNS };