import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import * as path$1 from "path";
import * as fs from "fs";
//#region src/extensions/security.ts
/**
* Extension Security Module
* 
*  Plugin security and sandboxing.
* Provides path safety checks, permission validation, and allowlist management.
*/
init_logger();
const log = createLogger("Extension:Security");
const DEFAULT_SECURITY_CONFIG = {
	checkPermissions: true,
	allowUntrusted: false,
	allow: [],
	trackProvenance: true,
	allowPromptInjection: false
};
/**
* Check if a path is safe for extension loading.
* - Rejects world-writable directories (mode & 0o002)
* - Verifies file ownership (UID match)
* - Detects symlink escape (realpath outside root)
* - Rejects hardlinks to non-bundled files
*/
function checkExtensionPathSafety(sourcePath, rootDir, origin) {
	try {
		const realSource = fs.realpathSync(sourcePath);
		const realRoot = fs.realpathSync(rootDir);
		if (!realSource.startsWith(realRoot + path$1.sep) && realSource !== realRoot) return {
			safe: false,
			reason: "symlink_escape",
			detail: `Real path ${realSource} escapes root directory ${realRoot}`
		};
		if (process.platform === "win32") return { safe: true };
		const stat = fs.statSync(sourcePath);
		if (origin !== "bundled" && (stat.mode & 2) !== 0) return {
			safe: false,
			reason: "world_writable",
			detail: `Path ${sourcePath} is world-writable`
		};
		if (origin !== "bundled" && process.getuid) {
			const currentUid = process.getuid();
			if (stat.uid !== currentUid && stat.uid !== 0) return {
				safe: false,
				reason: "ownership_mismatch",
				detail: `Path owned by UID ${stat.uid}, current process is UID ${currentUid}`
			};
		}
		if (origin !== "bundled") {
			const sourceStat = fs.statSync(sourcePath);
			if (sourceStat.isFile() && sourceStat.nlink > 1) return {
				safe: false,
				reason: "hardlink",
				detail: `Path ${sourcePath} is a hardlink (nlink: ${sourceStat.nlink})`
			};
		}
		return { safe: true };
	} catch (error) {
		return {
			safe: false,
			reason: "stat_failed",
			detail: `Failed to stat path: ${error instanceof Error ? error.message : String(error)}`
		};
	}
}
/**
* Check all files in an extension directory recursively
*/
function checkExtensionDirSafety(extensionDir, rootDir, origin) {
	const issues = [];
	if (!fs.existsSync(extensionDir)) return {
		safe: false,
		issues: [{
			safe: false,
			reason: "stat_failed",
			detail: "Directory does not exist"
		}]
	};
	const walkDir = (dir) => {
		const entries = fs.readdirSync(dir, { withFileTypes: true });
		for (const entry of entries) {
			const fullPath = path$1.join(dir, entry.name);
			if (entry.isSymbolicLink()) {
				const result = checkExtensionPathSafety(fullPath, rootDir, origin);
				if (!result.safe) issues.push(result);
			} else if (entry.isDirectory()) walkDir(fullPath);
			else if (entry.isFile()) {
				const result = checkExtensionPathSafety(fullPath, rootDir, origin);
				if (!result.safe) issues.push(result);
			}
		}
	};
	walkDir(extensionDir);
	return {
		safe: issues.length === 0,
		issues
	};
}
/**
* Check if an extension is allowed by the allowlist
*/
function isExtensionAllowed(extensionId, config) {
	if (config.allow.length === 0 && !config.allowUntrusted) return false;
	if (config.allow.includes(extensionId)) return true;
	return config.allowUntrusted;
}
/**
* Simple provenance tracking (in-memory for now)
*/
var ProvenanceTracker = class {
	provenance = /* @__PURE__ */ new Map();
	track(extensionId, source, method) {
		this.provenance.set(extensionId, {
			extensionId,
			source,
			installMethod: method,
			installDate: /* @__PURE__ */ new Date()
		});
	}
	get(extensionId) {
		return this.provenance.get(extensionId);
	}
	getAll() {
		return Array.from(this.provenance.values());
	}
};
const provenanceTracker = new ProvenanceTracker();
function logSecurityIssue(extensionId, result) {
	if (result.reason === "world_writable") log.warn(`[Security] Extension "${extensionId}" is in world-writable directory: ${result.detail}`);
	else if (result.reason === "ownership_mismatch") log.warn(`[Security] Extension "${extensionId}" ownership mismatch: ${result.detail}`);
	else if (result.reason === "symlink_escape") log.error(`[Security] Extension "${extensionId}" symlink escape attempt: ${result.detail}`);
	else if (result.reason === "hardlink") log.warn(`[Security] Extension "${extensionId}" hardlink detected: ${result.detail}`);
}
//#endregion
export { DEFAULT_SECURITY_CONFIG, checkExtensionDirSafety, checkExtensionPathSafety, isExtensionAllowed, logSecurityIssue, provenanceTracker };

//# sourceMappingURL=security.js.map