mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-07 07:42:13 +03:00
fix(security): resolve 5 CodeQL alerts, document FPs, harden deploy skills
Real fixes (alerts auto-close on next scan): - agentSkills/generator: escape backslash before double-quote in YAML frontmatter so a trailing backslash can't escape the closing quote (js/incomplete-sanitization #297/#298) - usage: replace /\s*\(RESTRICTED\)\s*$/ with a non-backtracking literal + trim (js/polynomial-redos #275) - i18n/request: skip __proto__/constructor/prototype in deepMergeFallback (js/prototype-pollution-utility #274) - scripts/ad-hoc/nvidia diag: log key presence only, never key chars (js/clear-text-logging #273) - tests: regression coverage for all three production fixes (YAML round-trip, proto-pollution guard, RESTRICTED strip + ReDoS timing) Docs: - ARCHITECTURE.md: executor count 45->55, OAuth modules 15->16, agy.ts in list Deploy skills (deploy-vps-*-cc/-cx/-ag): add --legacy-peer-deps (npm v11 peer-dep resolver crashes on the omniroute tree) and replace the "; pm2 start" that masked a failed install with a proper && chain.
This commit is contained in:
@@ -15,6 +15,8 @@ export function deepMergeFallback(
|
||||
source: Record<string, unknown>
|
||||
): Record<string, unknown> {
|
||||
for (const [key, sourceValue] of Object.entries(source)) {
|
||||
// Guard against prototype pollution from a crafted locale message tree.
|
||||
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
||||
const targetValue = target[key];
|
||||
if (
|
||||
sourceValue !== null &&
|
||||
|
||||
@@ -48,9 +48,13 @@ function serializeFrontmatter(fm: { name: string; description: string }): string
|
||||
// Use block scalar for description if it contains colons, quotes, or newlines
|
||||
const needsQuote = (v: string): boolean => /[:\n"']/.test(v) || v.startsWith(" ");
|
||||
|
||||
const nameStr = needsQuote(fm.name) ? `"${fm.name.replace(/"/g, '\\"')}"` : fm.name;
|
||||
// Escape order matters for double-quoted YAML scalars: backslash FIRST (so the
|
||||
// escapes we add below are not themselves re-escaped), then the double-quote,
|
||||
// then collapse real newlines into the \n escape sequence.
|
||||
const escDq = (v: string): string => v.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
||||
const nameStr = needsQuote(fm.name) ? `"${escDq(fm.name)}"` : fm.name;
|
||||
const descStr = needsQuote(fm.description)
|
||||
? `"${fm.description.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`
|
||||
? `"${escDq(fm.description).replace(/\n/g, "\\n")}"`
|
||||
: fm.description;
|
||||
|
||||
return `---\nname: ${nameStr}\ndescription: ${descStr}\n---\n`;
|
||||
@@ -363,3 +367,7 @@ export async function generateAgentSkills(opts: GeneratorOptions): Promise<Gener
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
// Exported for unit testing only — keep the internal helpers reachable without
|
||||
// widening the public surface.
|
||||
export const __testing = { serializeFrontmatter };
|
||||
|
||||
Reference in New Issue
Block a user