karnel-termux 4.17.8 → 4.17.10
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/README.md +7 -7
- package/docs/ARCHITECTURE/index.md +6 -0
- package/docs/CHANGELOG.md +69 -0
- package/docs/_config.yml +1 -1
- package/docs/_layouts/base.html +15 -0
- package/docs/assets/css/style.scss +45 -0
- package/docs/cli/index.md +7 -1
- package/docs/doctor/index.md +7 -1
- package/docs/index.md +6 -13
- package/docs/troubleshooting/index.md +21 -6
- package/karnel/RELEASE_COMMIT +1 -1
- package/karnel/cli/commands/brain.sh +2 -2
- package/karnel/cli/commands/doctor/code_langs.sh +1 -1
- package/karnel/cli/commands/open.sh +1 -1
- package/karnel/cli/commands/pg.sh +16 -3
- package/karnel/cli/commands/show.sh +14 -2
- package/karnel/cli/commands/update.sh +15 -5
- package/karnel/tools/ai/cline/install.sh +9 -1
- package/karnel/tools/ai/cursor-cli/install.sh +7 -0
- package/karnel/tools/ai/droid/install.sh +10 -1
- package/karnel/tools/ai/goose/install.sh +1 -1
- package/karnel/tools/ai/keelcode/install.sh +1 -0
- package/karnel/tools/ai/kiro/install.sh +9 -1
- package/karnel/tools/deploy/supabase/install.sh +14 -3
- package/karnel/tools/plugins/install.sh +17 -3
- package/karnel/tools/security/amass/install.sh +1 -1
- package/karnel/tools/security/burpsuite/install.sh +1 -1
- package/karnel/tools/security/ffuf/install.sh +1 -1
- package/karnel/tools/security/gobuster/install.sh +1 -1
- package/karnel/tools/security/subfinder/install.sh +1 -1
- package/karnel/tools/security/zap/install.sh +1 -1
- package/karnel/tools/utils/zork/zork.sh +8 -3
- package/karnel/tools/voice/uninstall.sh +12 -5
- package/karnel/utils/agent_actions.sh +26 -5
- package/karnel/utils/install.sh +1 -3
- package/karnel/utils/log.sh +1 -1
- package/karnel/utils/tools.sh +1 -4
- package/karnel/utils/version.sh +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://github.com/israelmarques1024-dotcom/karnel-termux">
|
|
11
|
-
<img src="https://img.shields.io/badge/version-4.17.
|
|
11
|
+
<img src="https://img.shields.io/badge/version-4.17.10-0078D4?style=for-the-badge" alt="Version">
|
|
12
12
|
</a>
|
|
13
13
|
<a href="https://www.npmjs.com/package/karnel-termux">
|
|
14
14
|
<img src="https://img.shields.io/npm/v/karnel-termux?style=for-the-badge&logo=npm&color=cb3837" alt="npm">
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
<a href="https://termux.dev/">
|
|
23
23
|
<img src="https://img.shields.io/badge/platform-Termux%20%7C%20Android-0078D4?style=for-the-badge" alt="Platform">
|
|
24
24
|
</a>
|
|
25
|
-
<a href="https://
|
|
26
|
-
<img src="https://img.shields.io/badge/Site-karneltermux.
|
|
25
|
+
<a href="https://israelmarques1024-dotcom.github.io/karnel-termux">
|
|
26
|
+
<img src="https://img.shields.io/badge/Site-karneltermux.github.io-0078D4?style=for-the-badge" alt="Website">
|
|
27
27
|
</a>
|
|
28
28
|
</p>
|
|
29
29
|
|
|
@@ -61,7 +61,7 @@ Core agent contributions by **devcorex**.
|
|
|
61
61
|
### Via checksummed GitHub release (recommended)
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
version=4.17.
|
|
64
|
+
version=4.17.10
|
|
65
65
|
tmpdir=$(mktemp -d) && trap 'rm -rf "$tmpdir"' EXIT
|
|
66
66
|
base="https://github.com/israelmarques1024-dotcom/karnel-termux/releases/download/v$version"
|
|
67
67
|
curl -fsSL "$base/karnel-termux-install.sh" -o "$tmpdir/karnel-termux-install.sh"
|
|
@@ -507,7 +507,7 @@ karnel open ai # Open AI module docs
|
|
|
507
507
|
karnel open db # Open DB module docs
|
|
508
508
|
```
|
|
509
509
|
|
|
510
|
-
Documentation loads from https://
|
|
510
|
+
Documentation loads from https://israelmarques1024-dotcom.github.io/karnel-termux.
|
|
511
511
|
|
|
512
512
|
---
|
|
513
513
|
|
|
@@ -519,7 +519,7 @@ Documentation loads from https://karneltermux.vercel.app.
|
|
|
519
519
|
- [Troubleshooting](docs/troubleshooting/index.md)
|
|
520
520
|
- [Architecture](docs/ARCHITECTURE/index.md)
|
|
521
521
|
- [Documentation changelog](docs/CHANGELOG.md)
|
|
522
|
-
- [Official website](https://
|
|
522
|
+
- [Official website](https://israelmarques1024-dotcom.github.io/karnel-termux)
|
|
523
523
|
|
|
524
524
|
---
|
|
525
525
|
|
|
@@ -651,7 +651,7 @@ MIT © Israel Marques
|
|
|
651
651
|
---
|
|
652
652
|
|
|
653
653
|
<p align="center">
|
|
654
|
-
<a href="https://
|
|
654
|
+
<a href="https://israelmarques1024-dotcom.github.io/karnel-termux">
|
|
655
655
|
<img src="https://img.shields.io/badge/Full%20Documentation-0078D4?style=for-the-badge" alt="Documentation">
|
|
656
656
|
</a>
|
|
657
657
|
<a href="https://www.youtube.com/@capideb">
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Documentation Changelog
|
|
3
|
+
permalink: /CHANGELOG/
|
|
4
|
+
layout: base
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Documentation Changelog
|
|
2
8
|
|
|
9
|
+
## 4.17.10
|
|
10
|
+
|
|
11
|
+
- Round 10 security/correctness hardening (23 distinct fixes):
|
|
12
|
+
- **Termux `/tmp` fallbacks eliminated** across host-side code
|
|
13
|
+
(`update.sh`, `brain.sh`, `version.sh`, `log.sh`, `agent_actions.sh`,
|
|
14
|
+
`doctor/code_langs.sh`, `supabase`, and the `security/*` tools amass,
|
|
15
|
+
subfinder, ffuf, gobuster, burpsuite, zap) — now use `KARNEL_CACHE`.
|
|
16
|
+
- **`karnel show <module>`** now rejects invalid module names
|
|
17
|
+
(`/`, `..`, `~`), closing a path-traversal / information-disclosure bug.
|
|
18
|
+
- **Agent PLAN (read-only) mode** hardened: blocks `sed`/`awk`/`perl`/
|
|
19
|
+
`xargs`/`make`/`env`/`nohup`/`setsid`, `sed`/`perl -i`, editors,
|
|
20
|
+
`git apply`/`worktree`/`read-tree`/`update-index`, and now also catches
|
|
21
|
+
redirections without a preceding space (`echo x>file`).
|
|
22
|
+
- **Plugin supply chain** fail-closed: installs now require a manifest
|
|
23
|
+
checksum (was silently skipped), and registry installs pin to a committed
|
|
24
|
+
SHA when provided.
|
|
25
|
+
- **`karnel pg backup --schedule`** no longer swallows `crontab` failures
|
|
26
|
+
and uses the escaped DB name to avoid duplicate cron jobs.
|
|
27
|
+
- **Reinstall** now proceeds to install when the uninstall step reports
|
|
28
|
+
"already uninstalled" (rc 2) instead of aborting.
|
|
29
|
+
- **Archive extraction hardened**: `cline`, `goose`, `kiro` AI installers
|
|
30
|
+
and `zork` now use the safe extractors; `zork` also drops literal `/tmp`.
|
|
31
|
+
- Site fully overhauled (navigation, dark mode, GitHub Pages URLs, Liquid
|
|
32
|
+
fixes, consistent front matter).
|
|
33
|
+
|
|
34
|
+
## 4.17.9
|
|
35
|
+
|
|
36
|
+
- Hardened installer and runtime security across the toolkit:
|
|
37
|
+
- `droid` binary install now refuses when no published SHA-256 digest is
|
|
38
|
+
available (fail-closed) instead of silently skipping verification.
|
|
39
|
+
- `keelcode` and `supabase` now extract archives through the hardened
|
|
40
|
+
`safe_extract_tar` (rejects symlink/absolute-path traversal) instead of
|
|
41
|
+
raw `tar`.
|
|
42
|
+
- Restored OpenCode installation: upstream publishes no checksum, so
|
|
43
|
+
`github_download_and_extract` warns instead of refusing (other tools that
|
|
44
|
+
publish checksums remain fail-closed).
|
|
45
|
+
- `cursor-cli` now validates the downloaded bundle is a real gzip archive
|
|
46
|
+
before extraction.
|
|
47
|
+
- Agent PLAN (read-only) mode write-guard hardened: now blocks `sed -i` /
|
|
48
|
+
`perl -i`, full-screen editors, and file descriptors like `2>file`.
|
|
49
|
+
- Agent compaction no longer drops the freshly built summary during the
|
|
50
|
+
trim safety-net.
|
|
51
|
+
- `voice` uninstall no longer removes `termux-api` unless Karnel installed it.
|
|
52
|
+
- `karnel show` no longer depends on `realpath` (portable fallback).
|
|
53
|
+
- `karnel update` reports the accurate installed version instead of a
|
|
54
|
+
misleading `latest`.
|
|
55
|
+
- Reinstall no longer deletes the ownership marker before confirming the
|
|
56
|
+
install, preventing a tool from being orphaned on install failure.
|
|
57
|
+
|
|
58
|
+
## 4.17.8
|
|
59
|
+
|
|
60
|
+
- Documentation site reconciled with the GitHub Pages deployment: the `Publish
|
|
61
|
+
Docs` workflow (`.github/workflows/docs.yml`) builds Jekyll from `docs/` and
|
|
62
|
+
deploys to GitHub Pages, so the live documentation URL is
|
|
63
|
+
`https://israelmarques1024-dotcom.github.io/karnel-termux/`.
|
|
64
|
+
- `docs/CHANGELOG.md` is now a rendered page (added front matter + permalink)
|
|
65
|
+
and all internal links to it use the clean `/CHANGELOG/` path.
|
|
66
|
+
- Tool counts verified against the actual `karnel/tools/*` and
|
|
67
|
+
`karnel/tools/ai/*` directories: 45 AI tools, 3 editors, 8 languages,
|
|
68
|
+
5 databases, 22 dev tools, 11 npm packages, 10 shell plugins, 4 UI
|
|
69
|
+
components, 4 deploy CLIs, 6 games, 2 network tools, 12 utility tools,
|
|
70
|
+
30 security tools, 1 automation tool.
|
|
71
|
+
|
|
3
72
|
## 4.17.7
|
|
4
73
|
|
|
5
74
|
- Documentation site overhauled: valid `_config.yml`, cayman-compatible custom
|
package/docs/_config.yml
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<nav class="site-nav" aria-label="Documentation">
|
|
6
|
+
<a href="{{ '/' | relative_url }}">Docs</a>
|
|
7
|
+
<a href="{{ '/cli/' | relative_url }}">CLI</a>
|
|
8
|
+
<a href="{{ '/doctor/' | relative_url }}">Doctor</a>
|
|
9
|
+
<a href="{{ '/troubleshooting/' | relative_url }}">Troubleshooting</a>
|
|
10
|
+
<a href="{{ '/ARCHITECTURE/' | relative_url }}">Architecture</a>
|
|
11
|
+
<a href="{{ '/CHANGELOG/' | relative_url }}">Changelog</a>
|
|
12
|
+
<a href="https://israelmarques1024-dotcom.github.io/karnel-termux/">Live Site</a>
|
|
13
|
+
</nav>
|
|
14
|
+
|
|
15
|
+
{{ content }}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
--karnel-text: #c9d1d9;
|
|
15
15
|
--karnel-muted: #8b949e;
|
|
16
16
|
--karnel-code-bg: #161b22;
|
|
17
|
+
color-scheme: dark light;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
html {
|
|
@@ -37,13 +38,23 @@ body {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
@media (prefers-color-scheme: dark) {
|
|
41
|
+
html {
|
|
42
|
+
background: var(--karnel-bg);
|
|
43
|
+
}
|
|
40
44
|
body {
|
|
41
45
|
background: var(--karnel-bg);
|
|
42
46
|
color: var(--karnel-text);
|
|
43
47
|
}
|
|
48
|
+
.main-content {
|
|
49
|
+
color: var(--karnel-text);
|
|
50
|
+
}
|
|
44
51
|
.page-header {
|
|
45
52
|
background-image: linear-gradient(120deg, #0078d4, #2f81f7);
|
|
46
53
|
}
|
|
54
|
+
.page-header .project-name,
|
|
55
|
+
.page-header .project-tagline {
|
|
56
|
+
color: #ffffff;
|
|
57
|
+
}
|
|
47
58
|
.main-content h1,
|
|
48
59
|
.main-content h2,
|
|
49
60
|
.main-content h3,
|
|
@@ -235,3 +246,37 @@ body {
|
|
|
235
246
|
border-top: 1px solid #e1e4e8;
|
|
236
247
|
padding-top: 1rem;
|
|
237
248
|
}
|
|
249
|
+
|
|
250
|
+
/* Top navigation bar (injected by _layouts/base.html) */
|
|
251
|
+
.site-nav {
|
|
252
|
+
display: flex;
|
|
253
|
+
flex-wrap: wrap;
|
|
254
|
+
gap: 0.4rem 1.1rem;
|
|
255
|
+
align-items: center;
|
|
256
|
+
padding: 0.7rem 1rem;
|
|
257
|
+
margin-bottom: 1.75rem;
|
|
258
|
+
background: #f3f5f8;
|
|
259
|
+
border: 1px solid #d0d7de;
|
|
260
|
+
border-radius: 10px;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.site-nav a {
|
|
264
|
+
color: #0078d4;
|
|
265
|
+
text-decoration: none;
|
|
266
|
+
font-weight: 600;
|
|
267
|
+
font-size: 0.92rem;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.site-nav a:hover {
|
|
271
|
+
text-decoration: underline;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@media (prefers-color-scheme: dark) {
|
|
275
|
+
.site-nav {
|
|
276
|
+
background: var(--karnel-panel);
|
|
277
|
+
border-color: var(--karnel-border);
|
|
278
|
+
}
|
|
279
|
+
.site-nav a {
|
|
280
|
+
color: var(--karnel-accent);
|
|
281
|
+
}
|
|
282
|
+
}
|
package/docs/cli/index.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CLI Commands
|
|
3
|
+
permalink: /cli/
|
|
4
|
+
layout: base
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Karnel CLI Reference
|
|
2
8
|
|
|
3
9
|
```bash
|
|
@@ -190,7 +196,7 @@ karnel open <target>
|
|
|
190
196
|
```
|
|
191
197
|
|
|
192
198
|
Opens the official documentation page for a module using
|
|
193
|
-
`termux-open-url`. Base URL: `https://
|
|
199
|
+
`termux-open-url`. Base URL: `https://israelmarques1024-dotcom.github.io/karnel-termux`
|
|
194
200
|
|
|
195
201
|
| Target | Opens |
|
|
196
202
|
|------------------|-------|
|
package/docs/doctor/index.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Doctor System
|
|
3
|
+
permalink: /doctor/
|
|
4
|
+
layout: base
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Karnel Doctor
|
|
2
8
|
|
|
3
9
|
`karnel doctor` diagnoses the Termux environment, analyzes project code, and
|
|
@@ -239,5 +245,5 @@ Regression coverage lives in `tests/smoke.sh` and verifies nested module syntax,
|
|
|
239
245
|
the 76-entry registry, pipeline-safe parsing, mode counts, hidden GitHub workflow
|
|
240
246
|
detection, scoped NestJS detection, TypeScript, and Python manifests.
|
|
241
247
|
|
|
242
|
-
See [the 2026-07-16 changelog](../CHANGELOG
|
|
248
|
+
See [the 2026-07-16 changelog](../CHANGELOG/) for the complete audit and hardening
|
|
243
249
|
record.
|
package/docs/index.md
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Karnel Termux Documentation
|
|
3
|
+
permalink: /
|
|
4
|
+
layout: base
|
|
5
|
+
---
|
|
2
6
|
|
|
3
7
|
<img class="karnel-logo" src="{{ '/assets/images/karnel-logo.png' | relative_url }}" alt="Karnel Termux">
|
|
4
8
|
|
|
5
9
|
> Modular Dev Environment for Termux — install languages, databases, AI agents, editors, and more with one command
|
|
6
10
|
|
|
7
|
-
Navigate the docs:
|
|
8
|
-
|
|
9
|
-
<ul class="karnel-nav">
|
|
10
|
-
<li><a href="./cli/">CLI Commands</a></li>
|
|
11
|
-
<li><a href="./doctor/">Doctor System</a></li>
|
|
12
|
-
<li><a href="./troubleshooting/">Troubleshooting</a></li>
|
|
13
|
-
<li><a href="./ARCHITECTURE/">Architecture</a></li>
|
|
14
|
-
<li><a href="./CHANGELOG.md">Changelog</a></li>
|
|
15
|
-
<li><a href="https://israelmarques1024-dotcom.github.io/karnel-termux/">Live Site</a></li>
|
|
16
|
-
</ul>
|
|
17
|
-
|
|
18
11
|
## What is Karnel?
|
|
19
12
|
|
|
20
13
|
Karnel Termux transforms your Android device into a complete development workstation.
|
|
@@ -38,7 +31,7 @@ voice commands, and reviewed plugins — all from modules: `ai`, `auto`, `db`,
|
|
|
38
31
|
<a href="https://github.com/israelmarques1024-dotcom/karnel-termux/blob/main/karnel/tools/utils/fconv/README.md">Utility Scripts — fconv, notes, treex, and more</a>
|
|
39
32
|
<a href="./cli/#supabase--remote-project-helpers">Supabase CLI — remote-project helpers</a>
|
|
40
33
|
<a href="./ARCHITECTURE/">Architecture — project structure and module system</a>
|
|
41
|
-
<a href="./CHANGELOG
|
|
34
|
+
<a href="./CHANGELOG/">Changelog — version history and fixes</a>
|
|
42
35
|
</div>
|
|
43
36
|
|
|
44
37
|
## Credits
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Troubleshooting
|
|
3
|
+
permalink: /troubleshooting/
|
|
4
|
+
layout: base
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Troubleshooting
|
|
2
8
|
|
|
3
9
|
Common issues when installing, updating, or publishing Karnel Termux.
|
|
@@ -43,12 +49,21 @@ npm publish does not block the release. The workflow needs `contents: write`
|
|
|
43
49
|
permission (already declared). If `gh release create` fails, confirm the tag
|
|
44
50
|
exists and the token used by GitHub Actions has write access.
|
|
45
51
|
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
The
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
## Documentation site (GitHub Pages)
|
|
53
|
+
|
|
54
|
+
The documentation site is a Jekyll (cayman theme) site built from the `docs/`
|
|
55
|
+
directory and published to GitHub Pages by the `Publish Docs` workflow
|
|
56
|
+
(`.github/workflows/docs.yml`) on every push to `main` that changes `docs/**`.
|
|
57
|
+
The workflow runs `actions/jekyll-build-pages` (from `docs/`, output to
|
|
58
|
+
`docs/_site`), uploads the result as a Pages artifact, and deploys it to the
|
|
59
|
+
`github-pages` environment. The live site is
|
|
60
|
+
`https://israelmarques1024-dotcom.github.io/karnel-termux/`.
|
|
61
|
+
|
|
62
|
+
If a build fails, open the Actions run for the failing job and read the Jekyll
|
|
63
|
+
output: the usual causes are invalid `_config.yml` YAML, an SCSS compile error
|
|
64
|
+
in `assets/css/style.scss`, or a malformed `{% raw %}{{ }}{% endraw %}` Liquid tag. After a
|
|
65
|
+
successful deploy, the published site is visible under the repository's
|
|
66
|
+
**Settings → Pages**.
|
|
52
67
|
|
|
53
68
|
## Reporting a bug
|
|
54
69
|
|
package/karnel/RELEASE_COMMIT
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ef2964062663afea85983ccb2043d0a8ab6e115e
|
|
@@ -121,7 +121,7 @@ _brain_slug_escape() {
|
|
|
121
121
|
_brain_update_related() {
|
|
122
122
|
local file="$1" slug="$2"
|
|
123
123
|
local tmp
|
|
124
|
-
tmp=$(mktemp "${TMPDIR
|
|
124
|
+
tmp=$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-brain.XXXXXX")
|
|
125
125
|
local frontmatter_end
|
|
126
126
|
frontmatter_end=$(awk '/^---$/ {++n} n==2 {print NR; exit}' "$file")
|
|
127
127
|
|
|
@@ -151,7 +151,7 @@ _brain_update_related() {
|
|
|
151
151
|
_brain_remove_related() {
|
|
152
152
|
local file="$1" slug="$2"
|
|
153
153
|
local tmp
|
|
154
|
-
tmp=$(mktemp "${TMPDIR
|
|
154
|
+
tmp=$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-brain.XXXXXX")
|
|
155
155
|
local frontmatter_end
|
|
156
156
|
frontmatter_end=$(awk '/^---$/ {++n} n==2 {print NR; exit}' "$file")
|
|
157
157
|
|
|
@@ -64,7 +64,7 @@ _init_lang_tools() {
|
|
|
64
64
|
LANG_TOOLS["C/C++:clang_tidy"]="clang-tidy|lint|clang-tidy {} -- -std=c17 2>&1 | head -20|||official"
|
|
65
65
|
|
|
66
66
|
# Java
|
|
67
|
-
LANG_TOOLS["Java:javac"]="javac|syntax|javac -d \"${TMPDIR
|
|
67
|
+
LANG_TOOLS["Java:javac"]="javac|syntax|javac -d \"${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}\" -Xlint:all {} 2>&1 | head -10|||official"
|
|
68
68
|
|
|
69
69
|
# Docker
|
|
70
70
|
LANG_TOOLS["Docker:hadolint"]="hadolint|lint|hadolint Dockerfile|||community"
|
|
@@ -737,9 +737,22 @@ pg_schedule() {
|
|
|
737
737
|
local escaped_db; printf -v escaped_db '%q' "$db_name"
|
|
738
738
|
local escaped_path; printf -v escaped_path '%q' "$KARNEL_PATH"
|
|
739
739
|
local job="$cron_expr KARNEL_PATH=$escaped_path $escaped_path/bin/karnel pg backup $escaped_db >/dev/null 2>&1"
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
740
|
+
local tmpcron
|
|
741
|
+
tmpcron="$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-pg.XXXXXX")" || {
|
|
742
|
+
log_error "Failed to schedule backup for database '$db_name'"
|
|
743
|
+
return 1
|
|
744
|
+
}
|
|
745
|
+
{
|
|
746
|
+
crontab -l 2>/dev/null | grep -vF "karnel pg backup $escaped_db"
|
|
747
|
+
echo "$job"
|
|
748
|
+
} >"$tmpcron"
|
|
749
|
+
if crontab "$tmpcron"; then
|
|
750
|
+
log_success "Backup scheduled successfully ($interval) for database '$db_name'!"
|
|
751
|
+
list_item "Ensure cron daemon is running (run: 'crond')"
|
|
752
|
+
else
|
|
753
|
+
log_error "Failed to schedule backup for database '$db_name'"
|
|
754
|
+
fi
|
|
755
|
+
rm -f "$tmpcron"
|
|
743
756
|
fi
|
|
744
757
|
echo
|
|
745
758
|
}
|
|
@@ -47,6 +47,11 @@ show_main() {
|
|
|
47
47
|
return 1
|
|
48
48
|
fi
|
|
49
49
|
|
|
50
|
+
if [[ ! "$module" =~ ^[A-Za-z0-9_-]+$ ]]; then
|
|
51
|
+
log_error "Invalid module name: $module"
|
|
52
|
+
return 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
50
55
|
if [[ "$module" == "backup" ]]; then
|
|
51
56
|
_show_backup_docs "$tool"
|
|
52
57
|
return
|
|
@@ -86,8 +91,15 @@ show_main() {
|
|
|
86
91
|
return
|
|
87
92
|
fi
|
|
88
93
|
|
|
89
|
-
local readme_path
|
|
90
|
-
|
|
94
|
+
local readme_path raw
|
|
95
|
+
raw="$KARNEL_PATH/tools/$module/$tool/README.md"
|
|
96
|
+
if command -v realpath &>/dev/null; then
|
|
97
|
+
readme_path="$(realpath "$raw" 2>/dev/null)"
|
|
98
|
+
elif command -v readlink &>/dev/null; then
|
|
99
|
+
readme_path="$(readlink -f "$raw" 2>/dev/null)"
|
|
100
|
+
else
|
|
101
|
+
readme_path="$raw"
|
|
102
|
+
fi
|
|
91
103
|
|
|
92
104
|
if [[ -z "$readme_path" ]]; then
|
|
93
105
|
log_error "No documentation found for $module/$tool"
|
|
@@ -226,9 +226,9 @@ _update_try_curl() {
|
|
|
226
226
|
command -v curl &>/dev/null || return 1
|
|
227
227
|
|
|
228
228
|
local meta installer sumfile tag
|
|
229
|
-
meta=$(mktemp "${TMPDIR
|
|
230
|
-
installer=$(mktemp "${TMPDIR
|
|
231
|
-
sumfile=$(mktemp "${TMPDIR
|
|
229
|
+
meta=$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-meta.XXXXXX") || return 1
|
|
230
|
+
installer=$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-install.XXXXXX") || { rm -f "$meta"; return 1; }
|
|
231
|
+
sumfile=$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-sum.XXXXXX") || { rm -f "$meta" "$installer"; return 1; }
|
|
232
232
|
|
|
233
233
|
log_info "Trying the official curl installer..."
|
|
234
234
|
|
|
@@ -347,12 +347,22 @@ _update_try_git() {
|
|
|
347
347
|
return 1
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
+
_npm_installed_version() {
|
|
351
|
+
local v pr
|
|
352
|
+
v=$(npm list -g karnel-termux 2>/dev/null | grep -oP 'karnel-termux@\K[0-9.]+')
|
|
353
|
+
if [[ -z "$v" ]]; then
|
|
354
|
+
pr="$(npm root -g 2>/dev/null)/karnel-termux/package.json"
|
|
355
|
+
[[ -f "$pr" ]] && v=$(grep -oP '"version"\s*:\s*"\K[0-9.]+' "$pr")
|
|
356
|
+
fi
|
|
357
|
+
printf '%s' "${v:-unknown}"
|
|
358
|
+
}
|
|
359
|
+
|
|
350
360
|
_update_try_npm() {
|
|
351
361
|
command -v npm &>/dev/null || return 1
|
|
352
362
|
log_info "Trying npm update..."
|
|
353
363
|
if npm update -g karnel-termux --ignore-scripts 2>/dev/null; then
|
|
354
364
|
local new_ver
|
|
355
|
-
new_ver=$(
|
|
365
|
+
new_ver=$(_npm_installed_version)
|
|
356
366
|
log_success "Updated to v$new_ver via npm"
|
|
357
367
|
return 0
|
|
358
368
|
fi
|
|
@@ -365,7 +375,7 @@ _update_try_npm_install() {
|
|
|
365
375
|
log_info "Trying npm install..."
|
|
366
376
|
if npm install -g karnel-termux@latest --ignore-scripts 2>/dev/null; then
|
|
367
377
|
local new_ver
|
|
368
|
-
new_ver=$(
|
|
378
|
+
new_ver=$(_npm_installed_version)
|
|
369
379
|
log_success "Updated to v$new_ver via npm install"
|
|
370
380
|
return 0
|
|
371
381
|
fi
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
import "@/utils/version"
|
|
5
5
|
import "@/utils/colors"
|
|
6
|
+
import "@/utils/install"
|
|
7
|
+
|
|
8
|
+
if ! declare -f safe_extract_tar >/dev/null 2>&1; then
|
|
9
|
+
safe_extract_tar() {
|
|
10
|
+
local archive="$1" outdir="$2" strip_components="${3:-0}"
|
|
11
|
+
tar -xzf "$archive" -C "$outdir" --strip-components="$strip_components"
|
|
12
|
+
}
|
|
13
|
+
fi
|
|
6
14
|
|
|
7
15
|
: "${KARNEL_DATA:=${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data}"
|
|
8
16
|
: "${KARNEL_CACHE:=${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
@@ -99,7 +107,7 @@ _cline_install_global_impl() {
|
|
|
99
107
|
|
|
100
108
|
mkdir -p "$CLINE_DATA_DIR"
|
|
101
109
|
: >"$CLINE_DATA_DIR/$CLINE_MARKER"
|
|
102
|
-
if !
|
|
110
|
+
if ! safe_extract_tar "$tarball" "$CLINE_DATA_DIR" &>>"$LOG_FILE"; then
|
|
103
111
|
rm -f "$tarball"
|
|
104
112
|
log_error "Failed to extract cline linux-arm64 binary"
|
|
105
113
|
return 1
|
|
@@ -129,11 +129,18 @@ _download_cursor_binary_impl() {
|
|
|
129
129
|
|
|
130
130
|
# Cursor does not publish a verifiable checksum for this asset, so integrity
|
|
131
131
|
# relies on HTTPS transport only; upstream does not publish a verifiable checksum.
|
|
132
|
+
# Validate the payload is a real gzip archive before extracting so a corrupted
|
|
133
|
+
# or error response (e.g. an HTML error page) is rejected.
|
|
132
134
|
if ! curl -fsSL "$download_url" -o "$staging_dir/$tarball" &>>"$LOG_FILE"; then
|
|
133
135
|
rm -rf "$staging_dir"
|
|
134
136
|
log_error "Failed to download Cursor CLI binary"
|
|
135
137
|
return 1
|
|
136
138
|
fi
|
|
139
|
+
if ! gzip -t "$staging_dir/$tarball" 2>/dev/null; then
|
|
140
|
+
rm -rf "$staging_dir"
|
|
141
|
+
log_error "Downloaded Cursor bundle is not a valid gzip archive"
|
|
142
|
+
return 1
|
|
143
|
+
fi
|
|
137
144
|
|
|
138
145
|
if ! tar -zxf "$staging_dir/$tarball" --strip-components=1 -C "$staging_dir" &>>"$LOG_FILE"; then
|
|
139
146
|
rm -rf "$staging_dir"
|
|
@@ -125,13 +125,22 @@ _download_droid_binary_impl() {
|
|
|
125
125
|
|
|
126
126
|
local expected actual
|
|
127
127
|
expected="$(curl -fsSL "$sha_url" 2>/dev/null | awk '{print $1}')"
|
|
128
|
-
if [
|
|
128
|
+
if [[ ! "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
129
|
+
log_error "No published SHA-256 for Droid binary; refusing install"
|
|
130
|
+
rm -f "$DROID_DATA_DIR/droid"
|
|
131
|
+
return 1
|
|
132
|
+
fi
|
|
133
|
+
if command -v sha256sum &>/dev/null; then
|
|
129
134
|
actual="$(sha256sum "$DROID_DATA_DIR/droid" | awk '{print $1}')"
|
|
130
135
|
if [ "$actual" != "$expected" ]; then
|
|
131
136
|
log_error "Checksum verification failed"
|
|
132
137
|
rm -f "$DROID_DATA_DIR/droid"
|
|
133
138
|
return 1
|
|
134
139
|
fi
|
|
140
|
+
else
|
|
141
|
+
log_error "sha256sum unavailable; refusing install"
|
|
142
|
+
rm -f "$DROID_DATA_DIR/droid"
|
|
143
|
+
return 1
|
|
135
144
|
fi
|
|
136
145
|
|
|
137
146
|
chmod +x "$DROID_DATA_DIR/droid"
|
|
@@ -197,7 +197,7 @@ _goose_download_binary_proot_impl() {
|
|
|
197
197
|
return 1
|
|
198
198
|
fi
|
|
199
199
|
verify_github_release_asset aaif-goose/goose "v${latest_version}" "$tarball" "$GOOSE_DATA_DIR/$tarball" || return 1
|
|
200
|
-
if !
|
|
200
|
+
if ! extract_tarball "$GOOSE_DATA_DIR/$tarball" "$GOOSE_DATA_DIR" &>>"$LOG_FILE"; then
|
|
201
201
|
rm -f "$GOOSE_DATA_DIR/$tarball"
|
|
202
202
|
log_error "Failed to extract Goose CLI"
|
|
203
203
|
return 1
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
import "@/utils/colors"
|
|
5
5
|
import "@/utils/version"
|
|
6
|
+
import "@/utils/install"
|
|
7
|
+
|
|
8
|
+
if ! declare -f safe_extract_tar >/dev/null 2>&1; then
|
|
9
|
+
safe_extract_tar() {
|
|
10
|
+
local archive="$1" outdir="$2" strip_components="${3:-0}"
|
|
11
|
+
tar -xzf "$archive" -C "$outdir" --strip-components="$strip_components"
|
|
12
|
+
}
|
|
13
|
+
fi
|
|
6
14
|
|
|
7
15
|
: "${KARNEL_CACHE:=${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
8
16
|
: "${KARNEL_DATA:=${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data}"
|
|
@@ -136,7 +144,7 @@ print(version, download, checksum, sep="\t")
|
|
|
136
144
|
fi
|
|
137
145
|
log_success "Checksum verified"
|
|
138
146
|
|
|
139
|
-
if
|
|
147
|
+
if safe_extract_tar "$archive" "$tmpdir" 2>>"$LOG_FILE"; then
|
|
140
148
|
bin_path=$(find "$tmpdir" -name "kiro-cli" -type f -executable 2>/dev/null | head -1)
|
|
141
149
|
if [[ -z "$bin_path" ]]; then
|
|
142
150
|
bin_path=$(find "$tmpdir" -name "kiro*" -type f -executable 2>/dev/null | head -1)
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
import "@/utils/version"
|
|
5
|
+
import "@/utils/install"
|
|
6
|
+
|
|
7
|
+
if ! declare -f safe_extract_tar >/dev/null 2>&1; then
|
|
8
|
+
safe_extract_tar() {
|
|
9
|
+
local archive="$1" outdir="$2" strip_components="${3:-0}"
|
|
10
|
+
tar -xzf "$archive" -C "$outdir" --strip-components="$strip_components"
|
|
11
|
+
}
|
|
12
|
+
fi
|
|
5
13
|
|
|
6
14
|
_SUPABASE_VERSION="2.20.8"
|
|
7
15
|
_SUPABASE_RELEASE_URL="https://github.com/supabase/cli/releases/download/v${_SUPABASE_VERSION}"
|
|
@@ -44,7 +52,7 @@ install_supabase() (
|
|
|
44
52
|
local checksum_url="${_SUPABASE_RELEASE_URL}/supabase_${_SUPABASE_VERSION}_checksums.txt"
|
|
45
53
|
local tmp_dir staged_bin marker_staging="" old_bin="" old_marker=""
|
|
46
54
|
local _kdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
47
|
-
mkdir -p "$_kdir" 2>/dev/null || _kdir="${TMPDIR
|
|
55
|
+
mkdir -p "$_kdir" 2>/dev/null || _kdir="${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}"
|
|
48
56
|
tmp_dir=$(mktemp -d "$_kdir/supabase.XXXXXX") || return 1
|
|
49
57
|
staged_bin=""
|
|
50
58
|
trap 'rm -rf "$tmp_dir"; [[ -z "$staged_bin" ]] || rm -f "$staged_bin"; [[ -z "$marker_staging" ]] || rm -f "$marker_staging"' EXIT
|
|
@@ -81,8 +89,11 @@ install_supabase() (
|
|
|
81
89
|
fi
|
|
82
90
|
log_success "Checksum verified"
|
|
83
91
|
|
|
84
|
-
# Extract
|
|
85
|
-
|
|
92
|
+
# Extract (hardened: rejects symlink/absolute-path traversal)
|
|
93
|
+
safe_extract_tar "$tmp_dir/$filename" "$tmp_dir" || {
|
|
94
|
+
log_error "Extraction failed"
|
|
95
|
+
return 1
|
|
96
|
+
}
|
|
86
97
|
if [[ ! -f "$tmp_dir/supabase" ]]; then
|
|
87
98
|
log_error "Extraction failed"
|
|
88
99
|
return 1
|
|
@@ -519,7 +519,10 @@ _plugin_verify_checksum() {
|
|
|
519
519
|
local expected actual
|
|
520
520
|
|
|
521
521
|
expected="$(jq -r '.checksum // empty' "$manifest")" || return 1
|
|
522
|
-
[[ -
|
|
522
|
+
if [[ -z "$expected" ]]; then
|
|
523
|
+
log_error "Plugin '$(jq -r '.name' "$manifest")' has no checksum; refusing install"
|
|
524
|
+
return 1
|
|
525
|
+
fi
|
|
523
526
|
|
|
524
527
|
actual="$(_plugin_payload_checksum "$plugin_root")" || return 1
|
|
525
528
|
if [[ "$actual" != "$expected" ]]; then
|
|
@@ -882,11 +885,15 @@ _plugin_clone_repository() {
|
|
|
882
885
|
local repo="$1"
|
|
883
886
|
local ref="$2"
|
|
884
887
|
local destination="$3"
|
|
888
|
+
local commit="$4"
|
|
885
889
|
local source_url="https://github.com/$repo.git"
|
|
886
890
|
|
|
887
891
|
_plugin_require_command git || return 1
|
|
888
892
|
|
|
889
|
-
if [[ -n "$
|
|
893
|
+
if [[ -n "$commit" ]]; then
|
|
894
|
+
git clone "$source_url" "$destination" || return 1
|
|
895
|
+
git -C "$destination" checkout "$commit" --detach || return 1
|
|
896
|
+
elif [[ -n "$ref" ]]; then
|
|
890
897
|
git clone --depth=1 --branch "$ref" "$source_url" "$destination"
|
|
891
898
|
else
|
|
892
899
|
git clone --depth=1 "$source_url" "$destination"
|
|
@@ -1083,6 +1090,13 @@ _plugin_stage_and_install() {
|
|
|
1083
1090
|
local replace_existing="$7"
|
|
1084
1091
|
local staging checkout checkout_root candidate candidate_root manifest_name commit installed_ref expected_commit registry_name
|
|
1085
1092
|
|
|
1093
|
+
expected_commit=""
|
|
1094
|
+
registry_name=""
|
|
1095
|
+
if [[ -n "$registry_entry" ]]; then
|
|
1096
|
+
expected_commit="$(jq -r '.commit // empty' <<<"$registry_entry")" || return 1
|
|
1097
|
+
registry_name="$(jq -r '.name' <<<"$registry_entry")" || return 1
|
|
1098
|
+
fi
|
|
1099
|
+
|
|
1086
1100
|
_plugin_prepare_plugins_dir || return 1
|
|
1087
1101
|
_plugin_validate_repo "$repo" || return 1
|
|
1088
1102
|
[[ -z "$ref" ]] || _plugin_ref_is_valid "$ref" || {
|
|
@@ -1100,7 +1114,7 @@ _plugin_stage_and_install() {
|
|
|
1100
1114
|
}
|
|
1101
1115
|
checkout="$staging/repository"
|
|
1102
1116
|
|
|
1103
|
-
if ! _plugin_clone_repository "$repo" "$ref" "$checkout"; then
|
|
1117
|
+
if ! _plugin_clone_repository "$repo" "$ref" "$checkout" "$expected_commit"; then
|
|
1104
1118
|
log_error "Failed to clone plugin repository '$repo'."
|
|
1105
1119
|
_plugin_cleanup_staging "$staging"
|
|
1106
1120
|
return 1
|
|
@@ -47,7 +47,7 @@ install_amass() (
|
|
|
47
47
|
esac
|
|
48
48
|
url="https://github.com/owasp-amass/amass/releases/download/v${_AMASS_VERSION}/$asset"
|
|
49
49
|
|
|
50
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
50
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/amass.XXXXXX") || return 1
|
|
51
51
|
staged_bin=""
|
|
52
52
|
trap 'rm -rf "$tmpdir"; [ -z "$staged_bin" ] || rm -f "$staged_bin"' EXIT
|
|
53
53
|
archive="$tmpdir/amass.zip"
|
|
@@ -28,7 +28,7 @@ install_burpsuite() (
|
|
|
28
28
|
|
|
29
29
|
local url tmpdir staged_dir wrapper old_dir wrapper_backup
|
|
30
30
|
url="https://portswigger.net/burp/releases/download?product=community&type=Jar&version=${_BURP_VERSION}"
|
|
31
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
31
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/burpsuite.XXXXXX") || return 1
|
|
32
32
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
33
33
|
staged_dir="$tmpdir/data"
|
|
34
34
|
mkdir -p "$staged_dir" "$PREFIX/bin" "$(dirname "$_BURP_DIR")" || return 1
|
|
@@ -26,7 +26,7 @@ _download_ffuf() (
|
|
|
26
26
|
*) return 1 ;;
|
|
27
27
|
esac
|
|
28
28
|
url="https://github.com/ffuf/ffuf/releases/download/v${_FFUF_VERSION}/$asset"
|
|
29
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
29
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/ffuf.XXXXXX") || return 1
|
|
30
30
|
staged_bin=""
|
|
31
31
|
trap 'rm -rf "$tmpdir"; [ -z "$staged_bin" ] || rm -f "$staged_bin"' EXIT
|
|
32
32
|
archive="$tmpdir/ffuf.tar.gz"
|
|
@@ -19,7 +19,7 @@ _install_gobuster_bin() (
|
|
|
19
19
|
x86_64) checksum="871be404ce5f80c96b864586b3caa90f894598d1a8222ae316c19e5f70e04cfc" ;;
|
|
20
20
|
esac
|
|
21
21
|
local url="https://github.com/OJ/gobuster/releases/download/v${_GOBUSTER_VERSION}/$asset"
|
|
22
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
22
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/gobuster.XXXXXX") || return 1
|
|
23
23
|
staged_bin=""
|
|
24
24
|
trap 'rm -rf "$tmpdir"; [ -z "$staged_bin" ] || rm -f "$staged_bin"' EXIT
|
|
25
25
|
archive="$tmpdir/gobuster.tar.gz"
|
|
@@ -47,7 +47,7 @@ install_subfinder() (
|
|
|
47
47
|
esac
|
|
48
48
|
url="https://github.com/projectdiscovery/subfinder/releases/download/v${_SUBFINDER_VERSION}/$asset"
|
|
49
49
|
|
|
50
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
50
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/subfinder.XXXXXX") || return 1
|
|
51
51
|
staged_bin=""
|
|
52
52
|
trap 'rm -rf "$tmpdir"; [ -z "$staged_bin" ] || rm -f "$staged_bin"' EXIT
|
|
53
53
|
archive="$tmpdir/subfinder.zip"
|
|
@@ -34,7 +34,7 @@ install_zap() (
|
|
|
34
34
|
|
|
35
35
|
local url="https://github.com/zaproxy/zaproxy/releases/download/v${_ZAP_VERSION}/$ZAP_ASSET"
|
|
36
36
|
|
|
37
|
-
tmpdir=$(mktemp -d "${TMPDIR
|
|
37
|
+
tmpdir=$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/zap.XXXXXX") || {
|
|
38
38
|
log_error "Falha ao criar diretório temporário"
|
|
39
39
|
return 1
|
|
40
40
|
}
|
|
@@ -3,8 +3,13 @@ ZORK_DIR="$HOME/.local/share/karnel-data/zork"
|
|
|
3
3
|
if [ ! -f "$ZORK_DIR/zork1.dat" ]; then
|
|
4
4
|
mkdir -p "$ZORK_DIR"
|
|
5
5
|
echo "Baixando Zork I..."
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
tmpdir="$(mktemp -d "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/zork.XXXXXX")" || exit 1
|
|
7
|
+
curl -fsSL "https://www.infocom-if.org/downloads/zork1.zip" -o "$tmpdir/zork1.zip"
|
|
8
|
+
if unzip -l "$tmpdir/zork1.zip" 2>/dev/null | grep -qE '\.\.[/\\]|^/|[A-Za-z]:\\'; then
|
|
9
|
+
echo "Refusing potentially unsafe Zork archive" >&2
|
|
10
|
+
rm -rf "$tmpdir"; exit 1
|
|
11
|
+
fi
|
|
12
|
+
unzip -o "$tmpdir/zork1.zip" -d "$ZORK_DIR" 2>/dev/null
|
|
13
|
+
rm -rf "$tmpdir"
|
|
9
14
|
fi
|
|
10
15
|
exec frotz "$ZORK_DIR/zork1.dat" "$@"
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
|
|
5
5
|
_uninstall_voice_tool() {
|
|
6
|
+
local karnel_data="${KARNEL_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data}"
|
|
7
|
+
local marker="$karnel_data/voice/.termux-api-managed"
|
|
6
8
|
if command -v termux-api &>/dev/null; then
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if [[ -f "$marker" ]]; then
|
|
10
|
+
log_info "Removing Termux:API (installed by Karnel)..."
|
|
11
|
+
if ! pkg uninstall -y termux-api &>>"$LOG_FILE"; then
|
|
12
|
+
log_error "Failed to remove Termux:API (see $LOG_FILE)"
|
|
13
|
+
return 1
|
|
14
|
+
fi
|
|
15
|
+
rm -f "$marker"
|
|
16
|
+
log_success "Termux:API removed"
|
|
17
|
+
else
|
|
18
|
+
log_info "Termux:API is present but was not installed by Karnel; leaving it in place"
|
|
11
19
|
fi
|
|
12
|
-
log_success "Termux:API removed"
|
|
13
20
|
else
|
|
14
21
|
log_info "Termux:API is not installed"
|
|
15
22
|
fi
|
|
@@ -481,16 +481,32 @@ _agent_exec_to_file() {
|
|
|
481
481
|
# ------------------------------------------------------------
|
|
482
482
|
_agent_cmd_is_write() {
|
|
483
483
|
local cmd="$1"
|
|
484
|
-
# file redirections
|
|
485
|
-
|
|
484
|
+
# file redirections: >file >>file 2>file 1>>file &>file (also without a
|
|
485
|
+
# preceding space, e.g. echo x>file). Excludes fd-to-fd like >&2 and
|
|
486
|
+
# numeric comparisons >= / =>.
|
|
487
|
+
if printf '%s\n' "$cmd" | grep -qE '(^|[;&|[:space:]]|[A-Za-z0-9])(>|>>|&>)([^&=]|$)'; then
|
|
486
488
|
return 0
|
|
487
489
|
fi
|
|
488
490
|
# command substitution / backticks execute arbitrary code → write
|
|
489
491
|
if printf '%s\n' "$cmd" | grep -qE '\$\(|`'; then
|
|
490
492
|
return 0
|
|
491
493
|
fi
|
|
494
|
+
# in-place editors: sed -i / perl -i modify files in place
|
|
495
|
+
if printf '%s\n' "$cmd" | grep -qiE '(^|[;&|[:space:]])(sed|perl)[[:space:]][^|;&]*-[A-Za-z]*i[A-Za-z]*([[:space:]]|$)'; then
|
|
496
|
+
return 0
|
|
497
|
+
fi
|
|
498
|
+
# full-screen / line editors that can modify files
|
|
499
|
+
if printf '%s\n' "$cmd" | grep -qiE '(^|[;&|[:space:]])(vim|nvim|emacs|ed|ex|vi|nano)[[:space:]]'; then
|
|
500
|
+
return 0
|
|
501
|
+
fi
|
|
502
|
+
# interpreters that can execute arbitrary code / spawn processes / modify
|
|
503
|
+
# files even without a trailing redirection or -i flag (sed 'w', perl
|
|
504
|
+
# open(">"), awk system(), env/setsid/nohup running a command, make, xargs)
|
|
505
|
+
if printf '%s\n' "$cmd" | grep -qiE '(^|[;&|[:space:]])(sed|awk|perl|xargs|make|env|nohup|setsid)[[:space:]]'; then
|
|
506
|
+
return 0
|
|
507
|
+
fi
|
|
492
508
|
# blocklist of commands that write to disk / change state / spawn a shell
|
|
493
|
-
printf '%s\n' "$cmd" | grep -qiE '(^|[;&|[:space:]])(rm|rmdir|unlink|mv|cp|mkdir|touch|ln|chmod|chown|chgrp|install|truncate|tee|dd|mkfs|mount|umount|tar|gzip|gunzip|bzip2|xz|zstd|curl|wget|python3|python|node|npm|bun|yarn|pnpm|cargo|go |rustc|git (add|commit|push|pull|merge|rebase|reset|checkout|switch|restore|clean|stash|tag|clone|init|rm|mv)|pkg (install|uninstall|upgrade|reinstall|update)|apt( |-)|apt-get|dpkg|yum|dnf|pacman|brew|pip|pip3|uv|conda|mysql|psql|sqlite3|redis-cli|mongosh|kill|pkill|killall|service|systemctl|halt|reboot|shutdown|sudo|doas|su|pkexec|chroot|bash|sh|dash|zsh|ksh|eval|source|exec|screen|tmux|ssh|scp|sftp|rsync|telnet|nc|ncat|ftp|lftp|rsh|sshpass|socat|crontab|at |iptables|nft|ufw|docker|podman|kubectl|helm)[[:space:]]' && return 0
|
|
509
|
+
printf '%s\n' "$cmd" | grep -qiE '(^|[;&|[:space:]])(rm|rmdir|unlink|mv|cp|mkdir|touch|ln|chmod|chown|chgrp|install|truncate|tee|dd|mkfs|mount|umount|tar|gzip|gunzip|bzip2|xz|zstd|curl|wget|python3|python|node|npm|bun|yarn|pnpm|cargo|go |rustc|git (add|commit|push|pull|merge|rebase|reset|checkout|switch|restore|clean|stash|tag|clone|init|rm|mv|apply|am|worktree|read-tree|update-index|write-tree|checkout-index)|pkg (install|uninstall|upgrade|reinstall|update)|apt( |-)|apt-get|dpkg|yum|dnf|pacman|brew|pip|pip3|uv|conda|mysql|psql|sqlite3|redis-cli|mongosh|kill|pkill|killall|service|systemctl|halt|reboot|shutdown|sudo|doas|su|pkexec|chroot|bash|sh|dash|zsh|ksh|eval|source|exec|screen|tmux|ssh|scp|sftp|rsync|telnet|nc|ncat|ftp|lftp|rsh|sshpass|socat|crontab|at |iptables|nft|ufw|docker|podman|kubectl|helm)[[:space:]]' && return 0
|
|
494
510
|
return 1
|
|
495
511
|
}
|
|
496
512
|
|
|
@@ -890,7 +906,7 @@ agent_exec_loading() {
|
|
|
890
906
|
local delay=0.08
|
|
891
907
|
local tmpfile
|
|
892
908
|
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
893
|
-
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR
|
|
909
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}"
|
|
894
910
|
tmpfile="$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null)" || tmpfile="$(mktemp 2>/dev/null)"
|
|
895
911
|
|
|
896
912
|
local stty_saved=""
|
|
@@ -1359,12 +1375,17 @@ agent_context_footer() {
|
|
|
1359
1375
|
agent_history_trim_tokens() {
|
|
1360
1376
|
local history="$1" budget="${2:-0}"
|
|
1361
1377
|
(( budget <= 0 )) && { echo "$history"; return; }
|
|
1362
|
-
local toks n
|
|
1378
|
+
local toks n drop_idx is_summary
|
|
1363
1379
|
while :; do
|
|
1364
1380
|
toks=$(agent_context_tokens "$history")
|
|
1365
1381
|
(( toks <= budget )) && break
|
|
1366
1382
|
n=$(printf '%s' "$history" | jq 'length')
|
|
1367
1383
|
(( n <= 4 )) && break
|
|
1384
|
+
drop_idx=$(printf '%s' "$history" | jq -c 'if .[0].role == "system" then 1 else 0 end')
|
|
1385
|
+
is_summary=$(printf '%s' "$history" | jq -r --argjson i "$drop_idx" '.[$i].content // "" | contains("<compacted_summary>")')
|
|
1386
|
+
if [[ "$is_summary" == "true" ]]; then
|
|
1387
|
+
break
|
|
1388
|
+
fi
|
|
1368
1389
|
history=$(printf '%s' "$history" | jq -c 'if .[0].role == "system" then .[0:1] + .[2:] else .[1:] end')
|
|
1369
1390
|
done
|
|
1370
1391
|
echo "$history"
|
package/karnel/utils/install.sh
CHANGED
|
@@ -291,9 +291,7 @@ github_download_and_extract() {
|
|
|
291
291
|
if [[ "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
292
292
|
verify_sha256 "$tarball" "$expected" || return 1
|
|
293
293
|
else
|
|
294
|
-
|
|
295
|
-
rm -f "$tarball"
|
|
296
|
-
return 1
|
|
294
|
+
log_warn "No published SHA-256 digest for $repo/$asset; skipping integrity verification"
|
|
297
295
|
fi
|
|
298
296
|
extract_tarball "$tarball" "$outdir" || return 1
|
|
299
297
|
return 0
|
package/karnel/utils/log.sh
CHANGED
|
@@ -430,7 +430,7 @@ loading() {
|
|
|
430
430
|
local delay=0.08
|
|
431
431
|
local tmpfile
|
|
432
432
|
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
433
|
-
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR
|
|
433
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}"
|
|
434
434
|
tmpfile="$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null)" || tmpfile="$(mktemp 2>/dev/null)"
|
|
435
435
|
local cmd_pid=""
|
|
436
436
|
|
package/karnel/utils/tools.sh
CHANGED
|
@@ -59,10 +59,7 @@ _run_tool_lifecycle_action() {
|
|
|
59
59
|
fi
|
|
60
60
|
"$uninstall_handler"
|
|
61
61
|
rc=$?
|
|
62
|
-
(( rc == 0 )) || return "$rc"
|
|
63
|
-
if (( protected )); then
|
|
64
|
-
rm -f "$marker" || return 1
|
|
65
|
-
fi
|
|
62
|
+
(( rc == 0 || rc == 2 )) || return "$rc"
|
|
66
63
|
"$install_handler"
|
|
67
64
|
rc=$?
|
|
68
65
|
if (( rc == 0 && protected )); then
|
package/karnel/utils/version.sh
CHANGED
|
@@ -52,7 +52,7 @@ _spin_capture() {
|
|
|
52
52
|
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
53
53
|
local tmp
|
|
54
54
|
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
55
|
-
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR
|
|
55
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}"
|
|
56
56
|
tmp=$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null) || tmp=$(mktemp 2>/dev/null)
|
|
57
57
|
local spinner_fd
|
|
58
58
|
if [ -c /dev/tty ] 2>/dev/null; then
|
package/package.json
CHANGED