@sema-agent/core
Version:
Stateless, task-oriented AI agent core
298 lines (297 loc) • 15.9 kB
TypeScript
/**
* The wrapper programs the tightening reader ({@link import("./shell-lexer.js").readShellCommand}) peels to
* reach the program they run — upstream's three tables (its light strip on every arm, its full strip on
* the deny/ask arms, and its `xargs` clause inlined in the matcher) as ONE closed table. Peeling is
* ADDITIVE on the reading side: the segment keeps its spelled argv as one run candidate and adds one
* candidate per peeled layer, so a deny on the wrapper itself (`Bash(sudo:*)`) and a deny on the wrapped
* program both reach.
*
* The option grammar of every row is CLOSED, and that is the whole safety argument of the peel: a
* wrapper option the row does not name — short or long — stops the peel with an `unreadable` word (the
* caller asks a person) instead of guessing its arity, because a wrong guess names the option's VALUE
* or an operand as the program — a phantom run no deny matches. Three adversarial rounds found exactly
* that shape behind every "unknown is value-less" reading; the closed sets end the family rather than
* the instance. Growing a row is a data edit with upstream's manual page as its source.
*
* Per row: `valueFlags` — options whose value is the NEXT word (`-u root`; the attached `-uroot` and
* `--user=root` spellings are one word and need no row); `flags` — value-less options, including those
* whose value may only be ATTACHED (`--default-signal[=SIG]`, `xargs -i[R]`: bare, they take nothing);
* `attached` — short options whose OPTIONAL value may only be attached (`xargs -i[R]`: the rest of the cluster
* is the value, the next word never is); `commandString` — options whose value is a whole COMMAND STRING (`env -S 'rm -r x'`), unreadable here;
* `positional` — an operand that must precede the command (a priority, a cpu mask, a lock file; a word
* that does not match is unreadable, never the program); `duration` — `timeout`'s duration word;
* `bareDash` — `env -` (the obsolete spelling of `-i`); `assignments` — the wrapper takes `NAME=value`
* operands before its command (`env`, `sudo`; read dequoted, `env 'FOO=1' cmd`); `viaShell` — the program EVALUATES its
* operands as shell input (a command string, a script file, an expression: `watch`, `script`, `eval`,
* `source`, `bash -c`, `trap`, `let`), so the program behind it is never readable from the words — the
* string is not split and judged (upstream splits on whitespace; this reader takes the strict word);
* `executes` — a program that is NOT a wrapper but runs a command named after one of these words ANYWHERE
* in its argv (`find … -exec rm -r {} +`): such a word, or any expansion among its arguments (it could
* expand to that word), makes the program behind it unreadable; the program's own run is still read.
*/
export declare const SHELL_WRAPPER_TABLE: {
readonly command: {
readonly valueFlags: readonly [];
readonly flags: readonly ["-p"];
readonly commandString: readonly [];
};
readonly builtin: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
};
readonly noglob: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
};
readonly nocorrect: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
};
readonly exec: {
readonly valueFlags: readonly ["-a"];
readonly flags: readonly ["-c", "-l"];
readonly commandString: readonly [];
};
readonly env: {
readonly valueFlags: readonly ["-u", "-C", "-a", "-P", "--unset", "--chdir", "--argv0"];
readonly flags: readonly ["-i", "-0", "-v", "--ignore-environment", "--null", "--debug", "--list-signal-handling", "--default-signal", "--ignore-signal", "--block-signal", "--help", "--version"];
readonly commandString: readonly ["-S", "--split-string"];
readonly bareDash: true;
readonly assignments: true;
};
readonly sudo: {
readonly valueFlags: readonly ["-u", "-g", "-U", "-C", "-D", "-h", "-p", "-r", "-R", "-t", "-T", "--user", "--group", "--other-user", "--close-from", "--chdir", "--host", "--prompt", "--role", "--chroot", "--type", "--command-timeout", "-a", "--auth-type"];
readonly flags: readonly ["-A", "-b", "-E", "-H", "-i", "-K", "-k", "-l", "-n", "-P", "-S", "-s", "-V", "-v", "--askpass", "--background", "--preserve-env", "--set-home", "--login", "--remove-timestamp", "--reset-timestamp", "--list", "--non-interactive", "--preserve-groups", "--stdin", "--shell", "--version", "--validate", "--bell", "--help"];
readonly commandString: readonly [];
readonly assignments: true;
};
readonly doas: {
readonly valueFlags: readonly ["-a", "-u", "-C"];
readonly flags: readonly ["-L", "-n", "-s"];
readonly commandString: readonly [];
};
readonly pkexec: {
readonly valueFlags: readonly ["--user"];
readonly flags: readonly ["--disable-internal-agent", "--keep-cwd", "--version", "--help"];
readonly commandString: readonly [];
};
readonly nohup: {
readonly valueFlags: readonly [];
readonly flags: readonly ["--help", "--version"];
readonly commandString: readonly [];
};
readonly time: {
readonly valueFlags: readonly ["-o", "--output", "-f", "--format"];
readonly flags: readonly ["-p", "-a", "-v", "-q", "--append", "--portability", "--verbose", "--quiet", "--help", "--version"];
readonly commandString: readonly [];
};
readonly nice: {
readonly valueFlags: readonly ["-n", "--adjustment"];
readonly flags: readonly ["--help", "--version"];
readonly commandString: readonly [];
};
readonly timeout: {
readonly valueFlags: readonly ["-k", "-s", "--kill-after", "--signal"];
readonly flags: readonly ["-v", "--foreground", "--preserve-status", "--verbose", "--help", "--version"];
readonly commandString: readonly [];
readonly duration: true;
};
readonly stdbuf: {
readonly valueFlags: readonly ["-i", "-o", "-e", "--input", "--output", "--error"];
readonly flags: readonly ["--help", "--version"];
readonly commandString: readonly [];
};
readonly xargs: {
readonly valueFlags: readonly ["-n", "-L", "-P", "-I", "-d", "-s", "-a", "-E", "--max-args", "--max-procs", "--delimiter", "--max-chars", "--arg-file", "--process-slot-var"];
readonly flags: readonly ["-0", "-r", "-t", "-x", "-p", "-o", "--null", "--no-run-if-empty", "--verbose", "--exit", "--interactive", "--open-tty", "--show-limits", "--help", "--version", "--replace", "--eof", "--max-lines"];
readonly attached: readonly ["-i", "-l"];
readonly commandString: readonly [];
};
readonly watch: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly ionice: {
readonly valueFlags: readonly ["-c", "-n", "-p", "-P", "-u", "--class", "--classdata", "--pid", "--pgid", "--uid"];
readonly flags: readonly ["-t", "--ignore", "-h", "--help", "-V", "--version"];
readonly commandString: readonly [];
};
readonly setsid: {
readonly valueFlags: readonly [];
readonly flags: readonly ["-c", "-f", "-w", "--ctty", "--fork", "--wait", "--help", "--version"];
readonly commandString: readonly [];
};
readonly taskset: {
readonly valueFlags: readonly [];
readonly flags: readonly ["-a", "-p", "-c", "--all-tasks", "--pid", "--cpu-list", "--help", "--version"];
readonly commandString: readonly [];
readonly positional: RegExp;
};
readonly chrt: {
readonly valueFlags: readonly ["-p", "--pid", "-T", "-P", "-D", "--sched-runtime", "--sched-period", "--sched-deadline"];
readonly flags: readonly ["-b", "-f", "-i", "-o", "-r", "-d", "-m", "-a", "-R", "-v", "--batch", "--fifo", "--idle", "--other", "--rr", "--deadline", "--max", "--all-tasks", "--reset-on-fork", "--verbose", "--help", "--version"];
readonly commandString: readonly [];
readonly positional: RegExp;
};
readonly strace: {
readonly valueFlags: readonly ["-e", "-o", "-p", "-s", "-E", "-P", "-S", "-a", "-b", "-I", "-u", "-X", "-O", "-U", "--output", "--trace", "--expr", "--attach", "--string-limit", "--env", "--trace-path", "--columns", "--user", "--interruptible", "--detach-on", "--const-print-style", "--summary-sort-by", "--summary-syscall-overhead", "--summary-columns"];
readonly flags: readonly ["-f", "-ff", "-c", "-C", "-d", "-D", "-h", "-i", "-k", "-q", "-qq", "-r", "-t", "-tt", "-ttt", "-T", "-v", "-V", "-w", "-x", "-xx", "-y", "-yy", "-z", "-Z", "-F", "--follow-forks", "--summary-only", "--summary", "--debug", "--help", "--version"];
readonly commandString: readonly [];
};
readonly ltrace: {
readonly valueFlags: readonly ["-a", "-A", "-e", "-l", "-n", "-o", "-p", "-s", "-u", "-x", "-D", "-F", "--align", "--config", "--debug", "--indent", "--library", "--output", "--string-max", "-w", "--where"];
readonly flags: readonly ["-c", "-C", "-f", "-i", "-L", "-r", "-S", "-t", "-tt", "-ttt", "-T", "-V", "--demangle", "--help", "--version"];
readonly commandString: readonly [];
};
readonly flock: {
readonly valueFlags: readonly ["-w", "-E", "--timeout", "--wait", "--conflict-exit-code"];
readonly flags: readonly ["-s", "-x", "-u", "-n", "-o", "-F", "--shared", "--exclusive", "--unlock", "--nonblock", "--nb", "--close", "--no-fork", "--verbose", "--help", "--version"];
readonly commandString: readonly ["-c", "--command"];
readonly positional: RegExp;
};
readonly script: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly ["-c", "--command"];
readonly viaShell: true;
};
readonly unshare: {
readonly valueFlags: readonly ["-R", "-w", "-S", "-G", "--setuid", "--setgid", "--root", "--wd", "--propagation", "--setgroups", "--monotonic", "--boottime", "--map-user", "--map-group"];
readonly flags: readonly ["-m", "-u", "-i", "-n", "-p", "-U", "-C", "-T", "-f", "-r", "-c", "--mount", "--uts", "--ipc", "--net", "--pid", "--user", "--cgroup", "--time", "--fork", "--map-root-user", "--map-current-user", "--kill-child", "--mount-proc", "--keep-caps", "--help", "--version"];
readonly commandString: readonly [];
};
readonly nsenter: {
readonly valueFlags: readonly ["-t", "-S", "-G", "--target", "--setuid", "--setgid"];
readonly flags: readonly ["-a", "-m", "-u", "-i", "-n", "-p", "-U", "-C", "-T", "-r", "-w", "-F", "-Z", "--all", "--mount", "--uts", "--ipc", "--net", "--pid", "--user", "--cgroup", "--time", "--root", "--wd", "--no-fork", "--preserve-credentials", "--help", "--version"];
readonly commandString: readonly [];
};
readonly eval: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly source: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly ".": {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly trap: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly let: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly sh: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly bash: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly zsh: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly dash: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly ksh: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly fish: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly csh: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly tcsh: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly viaShell: true;
};
readonly find: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly executes: readonly ["-exec", "-execdir", "-ok", "-okdir"];
};
readonly compgen: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly executes: readonly ["-C", "-F"];
};
readonly complete: {
readonly valueFlags: readonly [];
readonly flags: readonly [];
readonly commandString: readonly [];
readonly executes: readonly ["-C", "-F"];
};
};
export type ShellWrapperName = keyof typeof SHELL_WRAPPER_TABLE;
/** The shape of one row (see the table's contract). */
export interface ShellWrapperRow {
readonly valueFlags: readonly string[];
readonly flags: readonly string[];
readonly attached?: readonly string[];
readonly commandString: readonly string[];
readonly positional?: RegExp;
readonly duration?: true;
readonly bareDash?: true;
readonly assignments?: true;
readonly viaShell?: true;
readonly executes?: readonly string[];
}
/** Builtins whose OPERANDS name variables: an operand spelling an array element with a non-numeric
* subscript (`arr[a]`, quoted, bare, attached `-varr[a]`, or `arr[a]=1`) is evaluated as arithmetic —
* recursively, like `$((a))` — when the builtin reads or writes it (`printf -v 'arr[a]' …`, `unset arr[a]`,
* `declare arr[a]=1`, `read arr[a]`, `[[ -v arr[a] ]]`, `test -v arr[a]`), and so is the value of an
* INTEGER-attribute assignment (`declare -i x=a`). The lexer marks such a run's hidden run at every peel
* candidate (`command printf -v …`). An operand that is WHOLLY an expansion is not judged here (`unset "$X"`
* — one more indirection; the price of reading it would be a prompt on every `export FOO="$BAR"`), nor is
* an arithmetic comparison's operand (`[[ $n -gt 0 ]]` evaluates `$n` — the same price). */
export declare const VARIABLE_OPERAND_BUILTINS: ReadonlySet<string>;
/** Does this run of a variable-operand builtin evaluate an operand arithmetically? Linear in the words. */
export declare function evaluatesOperand(run: readonly {
readonly text: string;
readonly raw: string;
}[]): boolean;