@kinosec/cli 0.10.3 → 0.11.1
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/cli.js +278 -7
- package/dist/cli.js.map +1 -1
- package/dist/vendor/README.md +134 -0
- package/dist/vendor/ctxpack.py +701 -0
- package/package.json +2 -1
- package/vendor/README.md +134 -0
- package/vendor/ctxpack.py +701 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kinosec/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Official KinoSec command-line interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
+
"vendor",
|
|
11
12
|
"LICENSE.md",
|
|
12
13
|
"README.md"
|
|
13
14
|
],
|
package/vendor/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
VENDORED FILE — do not edit here.
|
|
3
|
+
Source of truth: xbowbench/tools/ctxpack/ (packer + README + test suite).
|
|
4
|
+
`kinosec pentest --source` shells out to ctxpack.py to pack a target's source
|
|
5
|
+
into the graybox `source_context` bundle. Stdlib-only Python 3, zero deps.
|
|
6
|
+
To update: re-copy ctxpack.py + README.md from the upstream tool.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# ctxpack
|
|
10
|
+
|
|
11
|
+
A **source-context ingestion** layer that turns a black-box CTF/pentest agent into a
|
|
12
|
+
**graybox** one by feeding it the challenge's SOURCE CODE. Built for DEF CON-style
|
|
13
|
+
targets (usually a small web/pwn app, occasionally a large codebase) under event time
|
|
14
|
+
pressure: **one automatic, dependency-light step**, no mid-round setup.
|
|
15
|
+
|
|
16
|
+
It does *not* build a code graph, embeddings/RAG store, or a whitebox analysis agent. The
|
|
17
|
+
exploit-relevant logic in these targets is kilobytes and fits in context with room to
|
|
18
|
+
spare, so the right move is to **paste the source** — the only real problem is that
|
|
19
|
+
archives are padded with non-logic files (CSS frameworks, images, fonts, vendored deps,
|
|
20
|
+
lockfiles, editor junk). ctxpack is the cheap **extension/path filter** that makes "just
|
|
21
|
+
paste the source" work, with a mandatory manifest so nothing is dropped silently.
|
|
22
|
+
|
|
23
|
+
## The one idea: the metric and the threshold
|
|
24
|
+
|
|
25
|
+
- **Metric — kept-source tokens.** Every file is partitioned KEEP vs DROP; ctxpack sums
|
|
26
|
+
the estimated tokens of the KEEP set only. Token estimate = **`bytes / 3.7`** (no
|
|
27
|
+
tokenizer or API dependency). It routes on *logic-bearing source*, not raw archive bytes.
|
|
28
|
+
- **Threshold — `--budget` (default `120000`).** If kept-source tokens **≤ budget**, emit a
|
|
29
|
+
**paste** bundle (the source itself). If **> budget**, emit a **retrieve** outline (a file
|
|
30
|
+
tree + paths, no bodies) so the agent greps/reads on demand.
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python3 ctxpack.py <SOURCE> [-o OUT] [--budget N] [--bytes-per-token F] [--debug] \
|
|
36
|
+
[--stdout] [--emit-context-file PATH] [--stage-retrieve] [--stage-dir DIR] \
|
|
37
|
+
[--ctags] [--fork-diff [UPSTREAM_REF]]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`<SOURCE>` is a directory **or** an archive (`.zip` / `.tar[.gz]`, safely extracted).
|
|
41
|
+
Outputs land in `OUT` (default `./ctxpack-out`):
|
|
42
|
+
|
|
43
|
+
- `bundle.txt` — the inject-ready context (paste bundle, or retrieve outline).
|
|
44
|
+
- `manifest.json` + `manifest.md` — every INCLUDED file (path, bytes, est-tokens, tier),
|
|
45
|
+
every EXCLUDED file (path, bytes, **reason**), totals, mode, budget, and signals.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python3 ctxpack.py ./challenge-src # -> ./ctxpack-out/{bundle.txt,manifest.*}
|
|
49
|
+
python3 ctxpack.py handout.zip -o /tmp/ctx --budget 120000
|
|
50
|
+
python3 ctxpack.py ./big-repo --stage-retrieve --stage-dir /tmp/ctxpack_src
|
|
51
|
+
python3 ctxpack.py . --fork-diff origin/main # emit only the planted delta vs upstream
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Example (real challenge)
|
|
55
|
+
|
|
56
|
+
`XBEN-039-24/app` → **paste**, 6 KEEP files (~2.4k tokens), 3 DROP (500 KB of JPGs + CSS):
|
|
57
|
+
|
|
58
|
+
| kept | tier | dropped | reason |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `html/index.php` | entrypoint | `html/images/*.jpg` | ext:image |
|
|
61
|
+
| `html/admin.php`, `entrypoint.sh` | source | `html/styles.css` | ext:style |
|
|
62
|
+
| `Dockerfile`, `000-default.conf` | config | | |
|
|
63
|
+
| `db_init.sql` | other (logged) | | |
|
|
64
|
+
|
|
65
|
+
## Tune knobs
|
|
66
|
+
|
|
67
|
+
1. **The config block at the top of `ctxpack.py`** — the DROP/KEEP lists are plain
|
|
68
|
+
constants, easy to edit:
|
|
69
|
+
- `DROP_EXT` (images, fonts, styles, minified/maps, media, binaries) → reason codes.
|
|
70
|
+
- `DROP_FILENAMES` (lockfiles, editor junk) and `DROP_PATH_SEGMENTS`
|
|
71
|
+
(`node_modules/ vendor/ dist/ build/ __pycache__/ third_party/ .git/`).
|
|
72
|
+
- `KEEP_SOURCE_EXT`, `KEEP_TEMPLATE_EXT`, `KEEP_CONFIG_*` (Dockerfile, docker-compose,
|
|
73
|
+
`*.conf`, `requirements*.txt`, `package.json`, nginx/supervisor, `*.env.example`).
|
|
74
|
+
- `ENTRYPOINT_HINTS` — which names sort first (logic-first ordering).
|
|
75
|
+
- **Anything not dropped is KEPT** and, if it matched no KEEP hint, logged with
|
|
76
|
+
`note: kept:default-unknown-ext` ("when unsure, KEEP and log it").
|
|
77
|
+
2. **`--budget N`** — the paste↔retrieve threshold (kept-source tokens).
|
|
78
|
+
3. **`--bytes-per-token F`** — the estimate divisor (default `3.7`; the wider repo habit is
|
|
79
|
+
`4.0` — pass `--bytes-per-token 4`).
|
|
80
|
+
4. **`--debug`** — trace every KEEP/DROP decision (and its reason) to stderr, so the filter
|
|
81
|
+
is auditable mid-event.
|
|
82
|
+
|
|
83
|
+
## Manifest & signals (no silent truncation)
|
|
84
|
+
|
|
85
|
+
`manifest.json`/`manifest.md` list **every** file on both sides with reasons, and totals
|
|
86
|
+
that equal the sum of the included files (byte and token). `signals` flags, without acting:
|
|
87
|
+
`git_present` (fork-of-OSS diff candidate), `binaries_only` (decompile handoff — out of
|
|
88
|
+
scope for a source layer), and `known_ctf_markers` (e.g. `flag*`, `benchmark.json`, or a
|
|
89
|
+
`FLAG{`/`CTF{`/`HTB{` string in a kept file).
|
|
90
|
+
|
|
91
|
+
## Integration — wiring into `ctf_agent_defcon.sh` (default OFF)
|
|
92
|
+
|
|
93
|
+
The bundle is folded into the agent's **system prompt** via the `CTXPACK_BUNDLE` env
|
|
94
|
+
channel, so a small target never needs disk access. **Everything is default-OFF**, so the
|
|
95
|
+
benchmark stays black-box (its anti-cheat measurement is preserved) unless you opt in.
|
|
96
|
+
|
|
97
|
+
- **One command (real events):**
|
|
98
|
+
```bash
|
|
99
|
+
./graybox-run.sh <source-or-archive> <target-url>
|
|
100
|
+
```
|
|
101
|
+
Packs the source, exports `CTXPACK_BUNDLE`, and launches the agent grayboxed.
|
|
102
|
+
- **Benchmark launcher:** `GRAYBOX=1 ./run-one-defcon.sh XBEN-039-24 <out>` packs
|
|
103
|
+
`<challenge>/app` first. Unset → black-box (unchanged).
|
|
104
|
+
- **Agent side:** a default-OFF block (before the `CTF_PROMPT` write) appends the bundle
|
|
105
|
+
under an *authoritative* `## TARGET SOURCE CODE` header. The bundle is inserted via
|
|
106
|
+
command substitution **inside** a double-quoted assignment, so shell metacharacters in
|
|
107
|
+
the source (`"`, `$`, backticks) stay literal and never execute — verified by
|
|
108
|
+
`test_integration.sh`. Trace a run with `grep GRAYBOX <debug-log>`.
|
|
109
|
+
- **Retrieve mode (large codebase):** `--stage-retrieve --stage-dir /tmp/ctxpack_src` puts
|
|
110
|
+
KEEP files under `/tmp` (which the agent's RULE 1 permits it to read) for grep-on-demand.
|
|
111
|
+
|
|
112
|
+
## Testing
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python3 -m unittest -v test_ctxpack.py # fixtures A/B/C + edge-case matrix + invariants + zero-dep proof
|
|
116
|
+
python3 -I ctxpack.py <fixture> # runs isolated: no site-packages, no env -> stdlib-only
|
|
117
|
+
bash test_integration.sh # graybox injection is verbatim-safe + OFF stays black-box
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Invariants asserted: no excluded file appears in the bundle; manifest byte/token totals
|
|
121
|
+
equal the sum of the included files; the tool imports **only** the Python standard library.
|
|
122
|
+
|
|
123
|
+
## Stretch flags (optional, off by default)
|
|
124
|
+
|
|
125
|
+
- `--ctags` — in retrieve mode, run `ctags -R` over the KEEP files for jump-to-definition
|
|
126
|
+
(no-op with a manifest note if `ctags` is absent).
|
|
127
|
+
- `--fork-diff [UPSTREAM_REF]` — if a `.git/` is present (or a ref is supplied), emit
|
|
128
|
+
`git log`/`git diff` vs upstream instead of the full bundle, to isolate a planted delta.
|
|
129
|
+
|
|
130
|
+
## Requirements
|
|
131
|
+
|
|
132
|
+
Python 3 standard library only — **zero third-party dependencies**. No network, no API key,
|
|
133
|
+
no tokenizer. (Tested on CPython 3.14; uses `sys.stdlib_module_names` for the dep check and
|
|
134
|
+
`tarfile`'s `filter='data'` safe extraction where available.)
|