yenop 0.0.0 → 0.1.0
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/LICENSE.md +105 -0
- package/README.md +243 -3
- package/dist/adapters/claude-code/hook.d.ts +43 -0
- package/dist/adapters/claude-code/hook.js +101 -0
- package/dist/adapters/claude-code/hook.js.map +1 -0
- package/dist/adapters/claude-code/install.d.ts +23 -0
- package/dist/adapters/claude-code/install.js +86 -0
- package/dist/adapters/claude-code/install.js.map +1 -0
- package/dist/adapters/codex/hook.d.ts +7 -0
- package/dist/adapters/codex/hook.js +134 -0
- package/dist/adapters/codex/hook.js.map +1 -0
- package/dist/adapters/codex/install.d.ts +18 -0
- package/dist/adapters/codex/install.js +66 -0
- package/dist/adapters/codex/install.js.map +1 -0
- package/dist/adapters/cursor/hook.d.ts +25 -0
- package/dist/adapters/cursor/hook.js +228 -0
- package/dist/adapters/cursor/hook.js.map +1 -0
- package/dist/adapters/cursor/install.d.ts +10 -0
- package/dist/adapters/cursor/install.js +57 -0
- package/dist/adapters/cursor/install.js.map +1 -0
- package/dist/adapters/gemini/hook.d.ts +20 -0
- package/dist/adapters/gemini/hook.js +232 -0
- package/dist/adapters/gemini/hook.js.map +1 -0
- package/dist/adapters/gemini/install.d.ts +21 -0
- package/dist/adapters/gemini/install.js +101 -0
- package/dist/adapters/gemini/install.js.map +1 -0
- package/dist/adapters/hooks/pipeline.d.ts +69 -0
- package/dist/adapters/hooks/pipeline.js +131 -0
- package/dist/adapters/hooks/pipeline.js.map +1 -0
- package/dist/adapters/hooks/registry.d.ts +8 -0
- package/dist/adapters/hooks/registry.js +14 -0
- package/dist/adapters/hooks/registry.js.map +1 -0
- package/dist/adapters/mcp/gateway.d.ts +64 -0
- package/dist/adapters/mcp/gateway.js +205 -0
- package/dist/adapters/mcp/gateway.js.map +1 -0
- package/dist/adapters/mcp/run.d.ts +12 -0
- package/dist/adapters/mcp/run.js +86 -0
- package/dist/adapters/mcp/run.js.map +1 -0
- package/dist/adapters/openai-agents/index.d.ts +74 -0
- package/dist/adapters/openai-agents/index.js +139 -0
- package/dist/adapters/openai-agents/index.js.map +1 -0
- package/dist/cli/demo.d.ts +5 -0
- package/dist/cli/demo.js +130 -0
- package/dist/cli/demo.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +746 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/core/config.d.ts +50 -0
- package/dist/core/config.js +93 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/engine.d.ts +31 -0
- package/dist/core/engine.js +301 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/ids.d.ts +5 -0
- package/dist/core/ids.js +36 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +40 -0
- package/dist/core/index.js +73 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/policy.d.ts +41 -0
- package/dist/core/policy.js +205 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/receipts.d.ts +47 -0
- package/dist/core/receipts.js +137 -0
- package/dist/core/receipts.js.map +1 -0
- package/dist/core/report.d.ts +51 -0
- package/dist/core/report.js +125 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/shell.d.ts +105 -0
- package/dist/core/shell.js +921 -0
- package/dist/core/shell.js.map +1 -0
- package/dist/core/state.d.ts +52 -0
- package/dist/core/state.js +269 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/telemetry.d.ts +52 -0
- package/dist/core/telemetry.js +150 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/tools.d.ts +5 -0
- package/dist/core/tools.js +59 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +213 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/daemon/client.d.ts +34 -0
- package/dist/daemon/client.js +138 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/fast.d.ts +9 -0
- package/dist/daemon/fast.js +43 -0
- package/dist/daemon/fast.js.map +1 -0
- package/dist/daemon/server.d.ts +38 -0
- package/dist/daemon/server.js +321 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/service.d.ts +26 -0
- package/dist/daemon/service.js +171 -0
- package/dist/daemon/service.js.map +1 -0
- package/dist/viewer/server.d.ts +52 -0
- package/dist/viewer/server.js +184 -0
- package/dist/viewer/server.js.map +1 -0
- package/package.json +59 -7
- package/policies/README.md +58 -0
- package/policies/approve/default.cedar +72 -0
- package/policies/permit/default.cedar +48 -0
- package/policies/schema.cedarschema +104 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { readAllReceipts, answersFor, isOutcome } from "./receipts.js";
|
|
2
|
+
const APPROVE = "approve:";
|
|
3
|
+
export function buildReport(config, opts = {}) {
|
|
4
|
+
const days = Math.max(1, Math.floor(opts.days ?? 7));
|
|
5
|
+
const to = new Date();
|
|
6
|
+
const from = new Date(to.getTime() - days * 24 * 3600 * 1000);
|
|
7
|
+
const everything = readAllReceipts(config.receiptsPath);
|
|
8
|
+
const answers = answersFor(everything);
|
|
9
|
+
const mine = config.tenant;
|
|
10
|
+
let rows = everything.filter((r) => !isOutcome(r));
|
|
11
|
+
if (!opts.all)
|
|
12
|
+
rows = rows.filter((r) => (typeof r.tenant === "string" ? r.tenant === mine.name : r.tenant.id === mine.id));
|
|
13
|
+
rows = rows.filter((r) => r.ts >= from.toISOString() && r.ts <= to.toISOString());
|
|
14
|
+
const report = {
|
|
15
|
+
from: from.toISOString(),
|
|
16
|
+
to: to.toISOString(),
|
|
17
|
+
days,
|
|
18
|
+
scope: opts.all ? "all" : mine.name,
|
|
19
|
+
runs: new Set(rows.map((r) => r.runId)).size,
|
|
20
|
+
actions: rows.length,
|
|
21
|
+
allow: 0,
|
|
22
|
+
ask: 0,
|
|
23
|
+
deny: 0,
|
|
24
|
+
askOutcomes: { "approved, ran": 0, "approved, failed": 0, "refused by the permission system": 0, "not run: rejected or abandoned": 0, "awaiting an answer": 0 },
|
|
25
|
+
askByRule: {},
|
|
26
|
+
denyByRule: {},
|
|
27
|
+
byRuntime: {},
|
|
28
|
+
byToolKind: {},
|
|
29
|
+
observedOnly: 0,
|
|
30
|
+
};
|
|
31
|
+
let answered = 0;
|
|
32
|
+
let allowedByPerson = 0;
|
|
33
|
+
for (const r of rows) {
|
|
34
|
+
report[r.effect]++;
|
|
35
|
+
report.byRuntime[r.runtime] = (report.byRuntime[r.runtime] ?? 0) + 1;
|
|
36
|
+
report.byToolKind[r.toolKind] = (report.byToolKind[r.toolKind] ?? 0) + 1;
|
|
37
|
+
if (r.mode === "observe" || !r.enforced)
|
|
38
|
+
report.observedOnly++;
|
|
39
|
+
if (r.effect === "ask") {
|
|
40
|
+
const a = answers.get(r.id);
|
|
41
|
+
if (a)
|
|
42
|
+
report.askOutcomes[a]++;
|
|
43
|
+
const allowed = a === "approved, ran" || a === "approved, failed";
|
|
44
|
+
const refused = a === "refused by the permission system" || a === "not run: rejected or abandoned";
|
|
45
|
+
if (allowed || refused) {
|
|
46
|
+
answered++;
|
|
47
|
+
if (allowed)
|
|
48
|
+
allowedByPerson++;
|
|
49
|
+
}
|
|
50
|
+
for (const reason of r.reasons.filter((x) => x.startsWith(APPROVE))) {
|
|
51
|
+
const id = reason.slice(APPROVE.length);
|
|
52
|
+
const cell = (report.askByRule[id] ??= { asked: 0, allowed: 0, refused: 0 });
|
|
53
|
+
cell.asked++;
|
|
54
|
+
if (allowed)
|
|
55
|
+
cell.allowed++;
|
|
56
|
+
if (refused)
|
|
57
|
+
cell.refused++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (r.effect === "deny") {
|
|
61
|
+
for (const reason of r.reasons.filter((x) => !x.startsWith(APPROVE)))
|
|
62
|
+
report.denyByRule[reason] = (report.denyByRule[reason] ?? 0) + 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (answered > 0)
|
|
66
|
+
report.askApprovalRate = allowedByPerson / answered;
|
|
67
|
+
return report;
|
|
68
|
+
}
|
|
69
|
+
function pct(n, of) {
|
|
70
|
+
return of === 0 ? "–" : `${((100 * n) / of).toFixed(1)}%`;
|
|
71
|
+
}
|
|
72
|
+
function top(o, n = 6) {
|
|
73
|
+
return Object.entries(o).sort((a, b) => b[1] - a[1]).slice(0, n);
|
|
74
|
+
}
|
|
75
|
+
/** The report as a person reads it. */
|
|
76
|
+
export function renderReport(r) {
|
|
77
|
+
const L = [];
|
|
78
|
+
L.push(`Yenop report — last ${r.days} day${r.days === 1 ? "" : "s"}${r.scope === "all" ? ", every project" : ` for "${r.scope}"`}`);
|
|
79
|
+
L.push("");
|
|
80
|
+
if (r.actions === 0) {
|
|
81
|
+
L.push("No actions recorded in this period. Run an agent with Yenop installed, or try: yenop demo");
|
|
82
|
+
return L.join("\n");
|
|
83
|
+
}
|
|
84
|
+
L.push(`Runs ${String(r.runs).padStart(7)}`);
|
|
85
|
+
L.push(`Actions ${String(r.actions).padStart(7)}${r.observedOnly ? ` (${r.observedOnly} recorded in observe mode, not enforced)` : ""}`);
|
|
86
|
+
L.push("");
|
|
87
|
+
L.push(`ALLOW ${String(r.allow).padStart(7)} ${pct(r.allow, r.actions).padStart(6)}`);
|
|
88
|
+
L.push(`ASK ${String(r.ask).padStart(7)} ${pct(r.ask, r.actions).padStart(6)}`);
|
|
89
|
+
L.push(`DENY ${String(r.deny).padStart(7)} ${pct(r.deny, r.actions).padStart(6)}`);
|
|
90
|
+
if (r.ask > 0) {
|
|
91
|
+
L.push("");
|
|
92
|
+
L.push("What became of the asks");
|
|
93
|
+
for (const [k, v] of Object.entries(r.askOutcomes))
|
|
94
|
+
if (v)
|
|
95
|
+
L.push(` ${k.padEnd(34)} ${String(v).padStart(5)}`);
|
|
96
|
+
if (r.askApprovalRate !== undefined) {
|
|
97
|
+
const p = r.askApprovalRate;
|
|
98
|
+
const verdict = p >= 0.9 ? "most asks were approved: the baseline may be asking too often" : p <= 0.3 ? "most asks were refused: these were real catches" : "a mix: some rules earn their asks, some may not";
|
|
99
|
+
L.push(` approval rate ${pct(Math.round(p * 1000), 1000).padStart(6)} ${verdict}`);
|
|
100
|
+
}
|
|
101
|
+
const rules = Object.entries(r.askByRule).sort((a, b) => b[1].asked - a[1].asked).slice(0, 8);
|
|
102
|
+
if (rules.length) {
|
|
103
|
+
L.push("");
|
|
104
|
+
L.push("Asks by rule asked allowed refused");
|
|
105
|
+
for (const [id, c] of rules)
|
|
106
|
+
L.push(` ${id.padEnd(40)} ${String(c.asked).padStart(5)} ${String(c.allowed).padStart(7)} ${String(c.refused).padStart(7)}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (r.deny > 0) {
|
|
110
|
+
L.push("");
|
|
111
|
+
L.push("Denies by rule");
|
|
112
|
+
for (const [id, n] of top(r.denyByRule))
|
|
113
|
+
L.push(` ${id.padEnd(40)} ${String(n).padStart(5)}`);
|
|
114
|
+
}
|
|
115
|
+
L.push("");
|
|
116
|
+
L.push("By runtime");
|
|
117
|
+
for (const [k, n] of top(r.byRuntime))
|
|
118
|
+
L.push(` ${k.padEnd(14)} ${String(n).padStart(7)} ${pct(n, r.actions).padStart(6)}`);
|
|
119
|
+
L.push("");
|
|
120
|
+
L.push("By kind of action");
|
|
121
|
+
for (const [k, n] of top(r.byToolKind))
|
|
122
|
+
L.push(` ${k.padEnd(14)} ${String(n).padStart(7)} ${pct(n, r.actions).padStart(6)}`);
|
|
123
|
+
return L.join("\n");
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export interface SimpleCommand {
|
|
2
|
+
argv: string[];
|
|
3
|
+
/** True when this command reads its stdin from a pipe. */
|
|
4
|
+
piped: boolean;
|
|
5
|
+
redirects: {
|
|
6
|
+
op: string;
|
|
7
|
+
target: string;
|
|
8
|
+
}[];
|
|
9
|
+
/** Inner text of any subshell that appeared as a redirect target. */
|
|
10
|
+
redirectSubshells?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ShellFacts {
|
|
13
|
+
/** Programs invoked, wrappers like sudo/env stripped. */
|
|
14
|
+
programs: string[];
|
|
15
|
+
/** Canonical operations, e.g. "git:push", "rm:-r", "terraform:destroy", "aws:ec2:terminate-instances". */
|
|
16
|
+
ops: string[];
|
|
17
|
+
/** Path-like arguments with ~ expanded. Heredoc bodies are never included. */
|
|
18
|
+
paths: string[];
|
|
19
|
+
/** Environment variables referenced, e.g. ["DATABASE_URL"]. */
|
|
20
|
+
envRefs: string[];
|
|
21
|
+
/** SQL statements of concern found in any argument, uppercased: "DROP TABLE", "DELETE FROM", ... */
|
|
22
|
+
sql: string[];
|
|
23
|
+
commandCount: number;
|
|
24
|
+
heredoc: boolean;
|
|
25
|
+
sudo: boolean;
|
|
26
|
+
/** A download or other program's output is piped into an interpreter. */
|
|
27
|
+
pipesToShell: boolean;
|
|
28
|
+
/** Any path matches the secret-file patterns. */
|
|
29
|
+
secretPath: boolean;
|
|
30
|
+
/** An env var whose name looks like a credential is referenced. */
|
|
31
|
+
secretEnv: boolean;
|
|
32
|
+
/** A network client is invoked (curl, wget, ssh, scp, rsync, nc, git clone/pull/push, ...). */
|
|
33
|
+
network: boolean;
|
|
34
|
+
/** Hosts named in URLs and ssh-style targets. */
|
|
35
|
+
hosts: string[];
|
|
36
|
+
/** The network use reaches beyond this machine and private ranges (or the host could not be determined). */
|
|
37
|
+
externalNetwork: boolean;
|
|
38
|
+
/** Content is pulled in from the network: curl/wget fetches, git clone/pull/fetch. */
|
|
39
|
+
download: boolean;
|
|
40
|
+
/** Reads data that should not travel: credential variables, secret files, database clients, secret managers, environment dumps. */
|
|
41
|
+
sensitiveRead: boolean;
|
|
42
|
+
/** Something that sends data out: an HTTP write, ssh/scp/rsync, git push, npm publish, docker push. */
|
|
43
|
+
outbound: boolean;
|
|
44
|
+
/** Deletes, force-pushes, destroys, drops, prunes, wipes. */
|
|
45
|
+
destructive: boolean;
|
|
46
|
+
/** Changes Yenop's own rules, mode, daemon, or hook registration. A guard the guarded party can reconfigure is no guard. */
|
|
47
|
+
controlPlane: boolean;
|
|
48
|
+
/** A scanner, exploitation framework, credential attack, or a reverse-shell pattern. Dual-use: legitimate in authorized testing. */
|
|
49
|
+
offensiveTool: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Part of what runs cannot be seen as a shell command: inline code handed to an interpreter (python -c,
|
|
52
|
+
* node -e, perl -e, ruby -e), a decoded blob piped to a shell, eval of a built string. Opaque code is judged
|
|
53
|
+
* by what it names (paths and hosts found in it) and otherwise treated as needing a person.
|
|
54
|
+
*/
|
|
55
|
+
opaque: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Default secret-file patterns. `**` spans directories, `*` does not. A leading `!` excludes. */
|
|
58
|
+
export declare const DEFAULT_SECRET_PATTERNS: string[];
|
|
59
|
+
/**
|
|
60
|
+
* Path-like strings inside opaque code: anything quoted that looks like a path, plus bare tokens with a
|
|
61
|
+
* slash or a leading dot-directory. This does not understand the language; it does not need to. If the code
|
|
62
|
+
* names a protected file, that is enough to treat the file as touched. A false positive costs a question; a
|
|
63
|
+
* miss costs a bypass.
|
|
64
|
+
*/
|
|
65
|
+
export declare function pathsMentioned(code: string): string[];
|
|
66
|
+
export declare function isControlPlanePath(p: string): boolean;
|
|
67
|
+
/** Loopback, link-local, private ranges, and names that never leave the machine or the LAN. */
|
|
68
|
+
export declare function isInternalHost(host: string): boolean;
|
|
69
|
+
/** Convert a glob with `*`, `**`, `?` into a RegExp matched against a full path. */
|
|
70
|
+
/**
|
|
71
|
+
* Every path that reaches a security check goes through this first.
|
|
72
|
+
* - Backslashes become slashes: Windows paths must match the same patterns as everyone else's. Without this,
|
|
73
|
+
* `D:\\proj\\.env` matched nothing and was readable (found by the first Windows CI run).
|
|
74
|
+
* - Lower-cased: NTFS and default APFS are case-insensitive, so `.ENV` opens `.env`. Patterns are matched
|
|
75
|
+
* case-insensitively everywhere; a file that differs only by case is never a different secret.
|
|
76
|
+
* - A Windows drive prefix is kept (`c:/...`) so absolute-path logic still works.
|
|
77
|
+
*/
|
|
78
|
+
export declare function normalizePath(p: string, opts?: {
|
|
79
|
+
foldCase?: boolean;
|
|
80
|
+
}): string;
|
|
81
|
+
/** Where the filesystem itself ignores case, containment must too; where it does not, folding would loosen the check. */
|
|
82
|
+
export declare const FS_IGNORES_CASE: boolean;
|
|
83
|
+
export declare function globToRegExp(glob: string): RegExp;
|
|
84
|
+
export declare function matchesSecretPattern(path: string, patterns?: string[]): boolean;
|
|
85
|
+
interface Tok {
|
|
86
|
+
kind: "word" | "op" | "newline";
|
|
87
|
+
text: string;
|
|
88
|
+
/** For words: was any part quoted? Quoted words are never treated as operators. */
|
|
89
|
+
quoted: boolean;
|
|
90
|
+
/** Raw text inside $(...) or backticks found in this word, parsed as separate commands. */
|
|
91
|
+
subshells: string[];
|
|
92
|
+
}
|
|
93
|
+
export declare function tokenize(src: string): {
|
|
94
|
+
tokens: Tok[];
|
|
95
|
+
heredoc: boolean;
|
|
96
|
+
};
|
|
97
|
+
export declare function parseCommands(src: string): {
|
|
98
|
+
commands: SimpleCommand[];
|
|
99
|
+
heredoc: boolean;
|
|
100
|
+
};
|
|
101
|
+
export declare function analyzeShell(command: string, opts?: {
|
|
102
|
+
secretPatterns?: string[];
|
|
103
|
+
home?: string;
|
|
104
|
+
}): ShellFacts;
|
|
105
|
+
export {};
|