mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-24 00:11:31 +00:00
60 lines
1.9 KiB
TypeScript
60 lines
1.9 KiB
TypeScript
export type SafeBinSemanticValidationParams = {
|
|
binName?: string;
|
|
positional: readonly string[];
|
|
};
|
|
|
|
type SafeBinSemanticRule = {
|
|
validate?: (params: SafeBinSemanticValidationParams) => boolean;
|
|
configWarning?: string;
|
|
};
|
|
|
|
const JQ_ENV_FILTER_PATTERN = /(^|[^.$A-Za-z0-9_])env([^A-Za-z0-9_]|$)/;
|
|
|
|
const SAFE_BIN_SEMANTIC_RULES: Readonly<Record<string, SafeBinSemanticRule>> = {
|
|
jq: {
|
|
validate: ({ positional }) => !positional.some((token) => JQ_ENV_FILTER_PATTERN.test(token)),
|
|
configWarning:
|
|
"jq supports broad jq programs and builtins (for example `env`), so prefer explicit allowlist entries or approval-gated runs instead of safeBins.",
|
|
},
|
|
};
|
|
|
|
export function normalizeSafeBinName(raw: string): string {
|
|
const trimmed = raw.trim().toLowerCase();
|
|
if (!trimmed) {
|
|
return "";
|
|
}
|
|
const tail = trimmed.split(/[\\/]/).at(-1);
|
|
const normalized = tail ?? trimmed;
|
|
return normalized.replace(/\.(?:exe|cmd|bat|com)$/i, "");
|
|
}
|
|
|
|
export function getSafeBinSemanticRule(binName?: string): SafeBinSemanticRule | undefined {
|
|
const normalized = typeof binName === "string" ? normalizeSafeBinName(binName) : "";
|
|
return normalized ? SAFE_BIN_SEMANTIC_RULES[normalized] : undefined;
|
|
}
|
|
|
|
export function validateSafeBinSemantics(params: SafeBinSemanticValidationParams): boolean {
|
|
return getSafeBinSemanticRule(params.binName)?.validate?.(params) ?? true;
|
|
}
|
|
|
|
export function listRiskyConfiguredSafeBins(entries: Iterable<string>): Array<{
|
|
bin: string;
|
|
warning: string;
|
|
}> {
|
|
const hits = new Map<string, string>();
|
|
for (const entry of entries) {
|
|
const normalized = normalizeSafeBinName(entry);
|
|
if (!normalized || hits.has(normalized)) {
|
|
continue;
|
|
}
|
|
const warning = getSafeBinSemanticRule(normalized)?.configWarning;
|
|
if (!warning) {
|
|
continue;
|
|
}
|
|
hits.set(normalized, warning);
|
|
}
|
|
return Array.from(hits.entries())
|
|
.map(([bin, warning]) => ({ bin, warning }))
|
|
.toSorted((a, b) => a.bin.localeCompare(b.bin));
|
|
}
|