FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
levelcode/extensions/levelcode-ai/commandSafety.js at develop · levelcodeai/levelcode · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
levelcodeai
/
levelcode
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
3
Code
Issues
0
Pull requests
3
Discussions
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Discussions
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
levelcode
/
extensions
/
levelcode-ai
/
commandSafety.js
Copy path
More file actions
More file actions
Latest commit
History
History
History
98 lines (90 loc) · 5.42 KB
Breadcrumbs
levelcode
/
extensions
/
levelcode-ai
/
commandSafety.js
Copy path
File metadata and controls
98 lines (90 loc) · 5.42 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*---------------------------------------------------------------------------------------------
* Danger classifier for autopilot (see the run_command gate in agent.js).
*
* In autopilot the agent runs shell commands WITHOUT asking — except the ones this flags, which
* still show the approval card. This is a SECURITY gate, so it is deliberately biased toward flagging:
* a false positive costs one extra prompt; a false negative auto-runs something irreversible. When in
* doubt, flag. Matching is word-boundaried and scans the WHOLE command (so `echo hi && rm -rf x` and
* `xargs rm` are caught wherever the dangerous token sits), accepting that a dangerous word inside a
* quoted string ("rm is scary") will over-flag — that is the safe direction.
*
* Scope (user-chosen "Deletion + irreversible"): file deletion, discarding uncommitted work, plus a
* small set of hard-to-undo, high-blast-radius ops — sudo, force-push / history rewrite, piping a
* remote script into a shell, irreversible publishes, and writes into system directories. Pure +
* dependency-free so the boundary is unit-testable (test/commandSafety.test.js) without booting the extension.
*
* Known limitations (by design — this is a good-faith guardrail, not a sandbox): it matches command
* strings, so it does NOT catch deletion smuggled through an interpreter (`node -e fs.rmSync(...)`,
* `python -c shutil.rmtree(...)`), a bare truncating redirect (`> important.txt`), or a command
* deliberately obfuscated to evade it. Prompt injection that steers the model into one of those forms
* can therefore reach the shell unprompted in autopilot. It defends against the common case — an
* obviously-destructive command the model emits in good faith — not against an adversary evading it.
*--------------------------------------------------------------------------------------------*/
'use strict'
;
// Each rule: [category, regex]. Ordered so the most specific/telling category wins the report.
const
RULES
=
[
// --- file deletion ---
[
'deletion'
,
/
\b
r
m
\b
/
i
]
,
// rm / git rm / sudo rm / xargs rm (any form)
[
'deletion'
,
/
\b
r
m
d
i
r
\b
/
i
]
,
[
'deletion'
,
/
\b
u
n
l
i
n
k
\b
/
i
]
,
[
'deletion'
,
/
\b
s
h
r
e
d
\b
/
i
]
,
[
'deletion'
,
/
\b
r
i
m
r
a
f
\b
/
i
]
,
// the idiomatic Node recursive delete — no \brm\b boundary inside "rimraf"
[
'deletion'
,
/
\b
g
i
t
\s
+
c
l
e
a
n
\b
/
i
]
,
// -f/-d/-x wipe untracked files
[
'deletion'
,
/
\b
f
i
n
d
\b
[
\s
\S
]
*
?
-
d
e
l
e
t
e
\b
/
i
]
,
[
'deletion'
,
/
\b
f
i
n
d
\b
[
\s
\S
]
*
?
-
e
x
e
c
\s
+
r
m
\b
/
i
]
,
[
'deletion'
,
/
\b
t
r
u
n
c
a
t
e
\b
/
i
]
,
// -s 0 empties a file
[
'deletion'
,
/
\b
d
d
\b
/
i
]
,
// disk-destroyer
[
'deletion'
,
/
\b
m
k
f
s
\b
/
i
]
,
[
'deletion'
,
/
>
\s
*
\/
d
e
v
\/
(
s
d
|
d
i
s
k
|
n
v
m
e
|
n
u
l
l
\/
)
/
i
]
,
// redirect over a device node
// --- discarding uncommitted work (same irreversible effect as reset --hard; NOT in the reflog) ---
[
'discard-changes'
,
/
\b
g
i
t
\s
+
r
e
s
e
t
\s
+
-
-
h
a
r
d
\b
/
i
]
,
// discards the working tree
// `git checkout` that targets a path/HEAD/force (not a branch switch, which is safe):
[
'discard-changes'
,
/
\b
g
i
t
\s
+
c
h
e
c
k
o
u
t
\b
[
^
&
|
;
\n
]
*
(
\s
-
-
(
\s
|
$
)
|
\s
\.
(
\s
|
$
)
|
\b
H
E
A
D
\b
|
-
-
f
o
r
c
e
\b
|
\s
-
f
\b
)
/
i
]
,
// `git restore <path>` overwrites the working tree; `git restore --staged` only unstages (safe).
// But `--staged --worktree` (or `-W`) DOES write the working tree, so flag it before the exemption below.
[
'discard-changes'
,
/
\b
g
i
t
\s
+
r
e
s
t
o
r
e
\b
[
^
\n
&
|
;
]
*
(
-
-
w
o
r
k
t
r
e
e
\b
|
\s
-
W
\b
)
/
i
]
,
[
'discard-changes'
,
/
\b
g
i
t
\s
+
r
e
s
t
o
r
e
\b
(?
!
[
^
\n
&
|
;
]
*
-
-
s
t
a
g
e
d
)
/
i
]
,
// --- irreversible / high blast radius ---
[
'sudo'
,
/
\b
s
u
d
o
\b
/
i
]
,
[
'sudo'
,
/
\b
d
o
a
s
\b
/
i
]
,
[
'force-push'
,
/
\b
g
i
t
\s
+
p
u
s
h
\b
[
\s
\S
]
*
?
(
-
-
f
o
r
c
e
\b
|
-
-
f
o
r
c
e
-
w
i
t
h
-
l
e
a
s
e
\b
|
-
-
m
i
r
r
o
r
\b
|
\s
-
f
\b
)
/
i
]
,
[
'history-rewrite'
,
/
\b
g
i
t
\s
+
f
i
l
t
e
r
-
(
b
r
a
n
c
h
|
r
e
p
o
)
\b
/
i
]
,
[
'history-rewrite'
,
/
\b
g
i
t
\s
+
r
e
f
l
o
g
\s
+
e
x
p
i
r
e
\b
/
i
]
,
[
'history-rewrite'
,
/
\b
g
i
t
\s
+
g
c
\b
[
\s
\S
]
*
?
-
-
p
r
u
n
e
/
i
]
,
[
'remote-exec'
,
/
\b
(
c
u
r
l
|
w
g
e
t
|
f
e
t
c
h
)
\b
[
\s
\S
]
*
?
\|
\s
*
(
s
u
d
o
\s
+
)
?
(
s
h
|
b
a
s
h
|
z
s
h
|
k
s
h
|
f
i
s
h
|
p
y
t
h
o
n
3
?
|
n
o
d
e
|
r
u
b
y
|
p
e
r
l
)
\b
/
i
]
,
[
'publish'
,
/
\b
(
n
p
m
|
y
a
r
n
|
p
n
p
m
)
\s
+
p
u
b
l
i
s
h
\b
/
i
]
,
// --- writes that escape the project into system dirs ---
[
'system-write'
,
/
>
>
?
\s
*
\/
(
e
t
c
|
u
s
r
|
b
i
n
|
s
b
i
n
|
S
y
s
t
e
m
|
L
i
b
r
a
r
y
|
v
a
r
|
b
o
o
t
|
o
p
t
)
\b
/
i
]
,
[
'system-write'
,
/
\b
(
r
m
|
m
v
|
c
p
|
c
h
m
o
d
|
c
h
o
w
n
|
t
e
e
)
\b
[
\s
\S
]
*
?
\s
\/
(
e
t
c
|
u
s
r
|
b
i
n
|
s
b
i
n
|
S
y
s
t
e
m
|
b
o
o
t
)
\b
/
i
]
,
]
;
/**
* Classify a shell command for the autopilot gate.
*
@param
{
string
} command
*
@returns
{
{ dangerous: boolean, category: string|null }
}
*/
function
classifyCommand
(
command
)
{
const
s
=
String
(
command
||
''
)
;
for
(
const
[
category
,
re
]
of
RULES
)
{
if
(
re
.
test
(
s
)
)
{
return
{
dangerous
:
true
,
category
}
;
}
}
return
{
dangerous
:
false
,
category
:
null
}
;
}
/** Convenience boolean wrapper. */
function
isDangerousCommand
(
command
)
{
return
classifyCommand
(
command
)
.
dangerous
;
}
/** Short human label for the approval card ("why is autopilot still asking?"). */
function
dangerLabel
(
category
)
{
switch
(
category
)
{
case
'deletion'
:
return
'deletes files'
;
case
'discard-changes'
:
return
'discards uncommitted changes'
;
case
'sudo'
:
return
'runs as root (sudo)'
;
case
'force-push'
:
return
'force-pushes / rewrites remote history'
;
case
'history-rewrite'
:
return
'rewrites git history'
;
case
'remote-exec'
:
return
'pipes a remote script into a shell'
;
case
'publish'
:
return
'publishes a package'
;
case
'system-write'
:
return
'writes outside the project'
;
default
:
return
'is potentially destructive'
;
}
}
module
.
exports
=
{
classifyCommand
,
isDangerousCommand
,
dangerLabel
}
;
Back
|
FazBrowse Home
|
New Git URL