fullcourtdefense-cli 1.35.7 → 1.35.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actionIdentity.js +2 -1
- package/dist/actionPolicyEngine.d.ts +38 -0
- package/dist/actionPolicyEngine.js +383 -24
- package/dist/approvalPrompt.js +2 -2
- package/dist/askDialog.js +5 -4
- package/dist/blockExplanation.js +2 -0
- package/dist/callerEnv.d.ts +33 -0
- package/dist/callerEnv.js +90 -0
- package/dist/commandNarrative.js +111 -4
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/deterministicGuard.d.ts +32 -0
- package/dist/commands/deterministicGuard.js +214 -19
- package/dist/commands/hook.d.ts +34 -1
- package/dist/commands/hook.js +188 -31
- package/dist/commands/mcpGateway.js +2 -0
- package/dist/commands/taintLedger.js +3 -1
- package/dist/commands/workloadProtect.js +6 -2
- package/dist/devConfirm.d.ts +28 -12
- package/dist/devConfirm.js +134 -48
- package/dist/hookSlim.d.ts +1 -1
- package/dist/hookSlim.js +22 -2
- package/dist/nativeHook.d.ts +2 -1
- package/dist/nativeHook.js +109 -3
- package/dist/notify.js +4 -0
- package/dist/shellAst.d.ts +117 -0
- package/dist/shellAst.js +590 -0
- package/dist/shellAstLoader.d.ts +32 -0
- package/dist/shellAstLoader.js +271 -0
- package/dist/telemetry.d.ts +20 -0
- package/dist/telemetry.js +7 -0
- package/dist/vendor/tree-sitter/LICENSE.tree-sitter-bash +21 -0
- package/dist/vendor/tree-sitter/LICENSE.web-tree-sitter +21 -0
- package/dist/vendor/tree-sitter/VERSIONS.json +4 -0
- package/dist/vendor/tree-sitter/tree-sitter-bash.wasm +0 -0
- package/dist/vendor/tree-sitter/tree-sitter.cjs +4031 -0
- package/dist/vendor/tree-sitter/tree-sitter.wasm +0 -0
- package/dist/verdictIpc.js +5 -2
- package/dist/verdictIpcClient.d.ts +11 -1
- package/dist/verdictIpcClient.js +12 -2
- package/dist/version.json +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell AST facts — the structural view of a shell command line that the
|
|
3
|
+
* deterministic guard and the action-policy engine consume as DATA.
|
|
4
|
+
*
|
|
5
|
+
* A tree-sitter-bash parse tree is walked ONCE into a flat, JSON-serializable
|
|
6
|
+
* list of simple commands in execution order. Each command carries its argv
|
|
7
|
+
* with quoting resolved, which words are fully literal, the cwd scope in force
|
|
8
|
+
* when it runs (tracked through `cd`/`pushd`, subshells, loops, functions), the
|
|
9
|
+
* nesting it sits in, its redirections, and — for wrappers such as `sudo`,
|
|
10
|
+
* `bash -c '…'`, `docker run … sh -c '…'` — the inner script parsed recursively.
|
|
11
|
+
*
|
|
12
|
+
* Contract (the part that keeps this safe to put on the decision path):
|
|
13
|
+
*
|
|
14
|
+
* 1. FAIL CLOSED. `complete` is true only when the tree has no ERROR / MISSING
|
|
15
|
+
* node and every node type met is in the explicit allow-list below. Any
|
|
16
|
+
* structure this module does not understand makes the whole result
|
|
17
|
+
* incomplete, and an incomplete result may never RELAX a verdict — the
|
|
18
|
+
* regex floor in the guard and the engine then decides alone. (Same
|
|
19
|
+
* property Codex's `codex-command` and the tree-sitter rewrite of Claude
|
|
20
|
+
* Code's bash safety take: never interpret structure you cannot prove.)
|
|
21
|
+
* 2. Deterministic, no I/O. This file has no imports; the parser is injected
|
|
22
|
+
* as a minimal node interface so the same bytes are vendored into the
|
|
23
|
+
* backend (console simulator) and stay byte-identical with the CLI.
|
|
24
|
+
* 3. Data, not code. The facts cross into the hot-updatable detector worker
|
|
25
|
+
* as JSON. Nothing here executes, expands or resolves anything.
|
|
26
|
+
*
|
|
27
|
+
* Why an AST at all: every false positive of the last months was structural —
|
|
28
|
+
* quoted text mistaken for a command, a heredoc body scanned as shell, a bare
|
|
29
|
+
* `rm -rf *` after `cd scratch/` read as a root wipe, a `$( )` boundary missed.
|
|
30
|
+
* A parser answers those once; a regex answers them one incident at a time.
|
|
31
|
+
*/
|
|
32
|
+
export interface ShellSyntaxNode {
|
|
33
|
+
type: string;
|
|
34
|
+
text: string;
|
|
35
|
+
startIndex: number;
|
|
36
|
+
endIndex: number;
|
|
37
|
+
childCount: number;
|
|
38
|
+
isMissing: boolean;
|
|
39
|
+
isNamed: boolean;
|
|
40
|
+
child(index: number): ShellSyntaxNode | null;
|
|
41
|
+
childForFieldName(name: string): ShellSyntaxNode | null;
|
|
42
|
+
}
|
|
43
|
+
export type CwdScope = 'scoped' | 'unscoped' | 'unknown';
|
|
44
|
+
export interface ShellRedirectFact {
|
|
45
|
+
op: string;
|
|
46
|
+
target: string;
|
|
47
|
+
literal: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface ShellWrapperFact {
|
|
50
|
+
kind: 'privilege' | 'shell' | 'eval' | 'exec' | 'env' | 'container' | 'timing' | 'xargs';
|
|
51
|
+
program: string;
|
|
52
|
+
/** The wrapped script when it is a literal string, parsed with the same walker. */
|
|
53
|
+
inner?: ShellFacts;
|
|
54
|
+
}
|
|
55
|
+
export interface ShellCommandFact {
|
|
56
|
+
/** argv[0] with quotes resolved; '' when it is dynamic (variable, substitution). */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Words with quotes resolved. Dynamic parts keep their source text (`$X`, `$(…)`). */
|
|
59
|
+
argv: string[];
|
|
60
|
+
/** argv[i] is entirely literal: no expansion, substitution, glob-carrying variable. */
|
|
61
|
+
literal: boolean[];
|
|
62
|
+
/** Source text of the command including its redirects, EXCLUDING heredoc bodies. */
|
|
63
|
+
text: string;
|
|
64
|
+
start: number;
|
|
65
|
+
end: number;
|
|
66
|
+
/** cwd scope in force when this command runs. */
|
|
67
|
+
cwdScope: CwdScope;
|
|
68
|
+
depth: {
|
|
69
|
+
subshell: number;
|
|
70
|
+
function: number;
|
|
71
|
+
loop: number;
|
|
72
|
+
conditional: number;
|
|
73
|
+
substitution: number;
|
|
74
|
+
};
|
|
75
|
+
/** Members of one pipeline share an id (0 = not in a pipeline). */
|
|
76
|
+
pipeline: number;
|
|
77
|
+
redirects: ShellRedirectFact[];
|
|
78
|
+
hasHeredoc: boolean;
|
|
79
|
+
wrapper?: ShellWrapperFact;
|
|
80
|
+
}
|
|
81
|
+
export interface ShellFacts {
|
|
82
|
+
parser: 'tree-sitter-bash';
|
|
83
|
+
/** No parse errors and every node type understood. Only a complete result may relax a verdict. */
|
|
84
|
+
complete: boolean;
|
|
85
|
+
/** Why the result is incomplete (first reason). */
|
|
86
|
+
incompleteReason?: string;
|
|
87
|
+
commands: ShellCommandFact[];
|
|
88
|
+
/** Node types met that are not in the allow-list (for diagnostics / corpus growth). */
|
|
89
|
+
unknownNodeTypes: string[];
|
|
90
|
+
/** Any `eval`, `source`/`.`, or dynamic command name — structure the parse cannot see through. */
|
|
91
|
+
dynamicExecution: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** What a `cd`/`pushd` target says about the cwd afterwards. */
|
|
94
|
+
export declare function cdTargetScope(target: string, literal: boolean): CwdScope;
|
|
95
|
+
/** A parsed inner script: its root plus the release of the parser's native tree. */
|
|
96
|
+
export interface ParsedShellTree {
|
|
97
|
+
root: ShellSyntaxNode;
|
|
98
|
+
release(): void;
|
|
99
|
+
}
|
|
100
|
+
export declare const MAX_SHELL_AST_SOURCE = 64000;
|
|
101
|
+
/**
|
|
102
|
+
* Walk a parsed tree into facts. `nesting` guards the recursion through
|
|
103
|
+
* literal `bash -c` scripts (depth 3 is plenty; deeper is treated as unknown).
|
|
104
|
+
*/
|
|
105
|
+
export declare function analyzeShellTree(root: ShellSyntaxNode, nesting?: number): ShellFacts;
|
|
106
|
+
/** Register the grammar-backed parser used for inner `bash -c` scripts. */
|
|
107
|
+
export declare function setInnerShellParser(parse: ((source: string) => ParsedShellTree | undefined) | undefined): void;
|
|
108
|
+
/** All commands, including those inside literal wrapper scripts, depth-first in execution order. */
|
|
109
|
+
export declare function flattenShellCommands(facts: ShellFacts): ShellCommandFact[];
|
|
110
|
+
/** True when every part of the analysis (including inner scripts) is complete. */
|
|
111
|
+
export declare function shellFactsFullyComplete(facts: ShellFacts | undefined): facts is ShellFacts;
|
|
112
|
+
/**
|
|
113
|
+
* Text that looks like PowerShell — tree-sitter-bash will often parse it
|
|
114
|
+
* WITHOUT errors into nonsense, so the loader refuses it up front and the
|
|
115
|
+
* PowerShell model in the engine keeps deciding alone.
|
|
116
|
+
*/
|
|
117
|
+
export declare function looksLikePowerShell(command: string): boolean;
|