reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
# Extension verification — desensitization and leak scans
|
||||
|
||||
Covers the pass that added `skills/apk-reverse/scripts/scan_leaks.py` and
|
||||
`skills/apk-reverse/references/desensitization-and-leak-scans.md`, plus the precedent library
|
||||
under `skills/apk-reverse/references/precedents/`.
|
||||
|
||||
Strength labels follow `docs/tool-verification/README.md`: **observed** (the exact command and
|
||||
its output are reproduced here), **inferred** (follows from observed facts; the step itself was
|
||||
not executed), **unverified** (assumed or reported elsewhere and not independently confirmed).
|
||||
|
||||
Reference environment: Windows 11 host, Python 3.14.0, repository root on branch
|
||||
`main`. **No device, no network and no target sample were involved** — this pass is entirely
|
||||
machine-local, because the thing worth measuring is what a scanner reports against a tree whose
|
||||
contents are already known. Every identifier in the fixture and in every transcript below is
|
||||
synthetic; the repository's convention of `<PKG>` / `<DEVICE>` / `<serial>` is used wherever a
|
||||
real one would have appeared.
|
||||
|
||||
Date of the recorded runs: 2026-09-21. The numbers in §3b and §4a were measured on that date, on
|
||||
the tree this pass leaves behind; those two sections' transcripts are the ones this pass produced.
|
||||
|
||||
**Headline: the planted-leak corpus is reported in full (30 findings, 10 further shapes admitted
|
||||
through the exemption path), and the repository scan converges to zero strong/certain findings —
|
||||
the residue is four `endpoint/weak` hits, all four an RFC 5737 documentation address, which is a
|
||||
class this scanner reports on purpose. The first version of this file was itself the
|
||||
counter-example to its own subject: it quoted the planted values to prove the rules fire, and the
|
||||
scanner found that as a leak (§3b). The corpus keeps its values, because a corpus that cannot be
|
||||
found proves nothing; the published document keeps none. The gate is not wired into anything yet;
|
||||
that is the largest gap, and it is a Lead-side action.**
|
||||
|
||||
---
|
||||
|
||||
## 1. What was built, and what it was measured against
|
||||
|
||||
| Artifact | Role | Measured? |
|
||||
|---|---|---|
|
||||
| `skills/apk-reverse/scripts/scan_leaks.py` | the scanner: 17 rules in 6 categories, exemption table, four `RESULT=` tokens, `--fail-on strong\|any` | **observed** — every run below |
|
||||
| `tools/_work/leak-precedent/gen_fixtures.py` | generates the planted corpus and the exemption corpus | **observed** — 7 files, re-runnable |
|
||||
| `tools/_work/leak-precedent/fixture/` | the corpus itself (git-ignored work area) | **observed** |
|
||||
| `skills/apk-reverse/references/desensitization-and-leak-scans.md` | the reasoning, the do-not-anonymize table, the failure modes | not executable |
|
||||
| `skills/apk-reverse/references/precedents/**` | the case library, distilled from this repository's existing evidence | see the per-case strength tables |
|
||||
|
||||
The fixture exists so the claim "the scanner reports planted leaks" is reproducible rather than
|
||||
a transcript pasted once:
|
||||
|
||||
```
|
||||
$ python tools/_work/leak-precedent/gen_fixtures.py
|
||||
wrote tools/_work/leak-precedent\fixture\planted\package.txt (411 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\planted\device.txt (218 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\planted\token.txt (261 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\planted\appkey.txt (212 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\planted\endpoint.txt (146 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\planted\path.txt (175 bytes)
|
||||
wrote tools/_work/leak-precedent\fixture\exempt\benign.txt (1396 bytes)
|
||||
== 7 fixture file(s) ==
|
||||
```
|
||||
|
||||
## 2. `--help`, and the rule table — observed
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --help
|
||||
usage: scan_leaks.py [-h] [--root ROOT] [--only ONLY] [--exclude EXCLUDE]
|
||||
[--format {text,json}] [--show-exempt] [--list-rules]
|
||||
[--max MAX] [--quiet] [--fail-on {strong,any}]
|
||||
[--no-color]
|
||||
|
||||
Scan a skills repository for target identity that should not be published (bundle ids, device serials, tokens, SDK keys, literal endpoints, user paths). Exit 0 clean / 1 leaks_found / 2 error; prints RESULT=<token> last. `--fail-on strong` (default) keeps the gate green when the only hits are documentation-range addresses.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--root ROOT repository root to scan (default: the repo this script
|
||||
lives in)
|
||||
--only ONLY comma-separated categories to restrict to, e.g.
|
||||
pat,appkey
|
||||
--exclude EXCLUDE extra directory name to skip (repeatable)
|
||||
--format {text,json}
|
||||
--show-exempt also print findings that were suppressed by an
|
||||
exemption
|
||||
--list-rules print the rule table and exit
|
||||
--max MAX stop after N findings (0 = no limit)
|
||||
--quiet print only the RESULT token
|
||||
--fail-on {strong,any}
|
||||
which findings make the exit code non-zero: `strong`
|
||||
(default) fails only on strong/certain findings, `any`
|
||||
also fails on `weak` ones such as an address from the
|
||||
RFC 5737 documentation range
|
||||
--no-color accepted for compatibility
|
||||
|
||||
Categories: package, device, token, appkey, endpoint, path
|
||||
Exemptions (tool names, library names, CVE ids, hardening products, public
|
||||
crackme names, <PKG>-style placeholders, loopback/emulator addresses) are built
|
||||
in and audited with --show-exempt.
|
||||
```
|
||||
|
||||
`--list-rules` prints the table the exemption functions are attached to, which is what makes the
|
||||
scanner arguable rather than opaque. It exits 0 and prints `RESULT=clean` (no files were read),
|
||||
and the top of its output is:
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --list-rules
|
||||
== rules ==
|
||||
bundle_pkg_attr package strong a `package=` bundle id in a manifest or transcript
|
||||
bundle_pkg_decl package strong a bundle id in a `<manifest>` line
|
||||
bundle_pm_path package strong a bundle id in a `pm`/`am`/`monkey` invocation
|
||||
bundle_process_line package strong a bundle id in a `ps`/`pidof`/`top` capture
|
||||
bundle_component package strong a bundle id in a `component=`/`-n` activity reference
|
||||
device_serial device strong an `adb devices`-shaped device serial
|
||||
device_serial_context device strong a serial next to a device/install/`su` context word
|
||||
device_serial_tabular device strong a bare 16-char token in a device-listing table
|
||||
token_github_pat token certain a GitHub fine-grained personal access token
|
||||
token_github_classic token certain a GitHub classic token
|
||||
token_env_assignment token strong an inline API-key/token/secret assignment
|
||||
token_authorization_header token strong a literal Authorization header value
|
||||
appkey_assignment appkey strong an SDK appkey/appsecret assignment with a literal value
|
||||
plain_addr endpoint weak a non-loopback literal IP:port
|
||||
plain_addr_ipliteral endpoint weak a non-loopback bare IPv4 literal
|
||||
user_path_posix path strong an absolute POSIX user-home path
|
||||
user_path_windows path strong an absolute Windows user-profile path
|
||||
RESULT=clean (exit 0)
|
||||
```
|
||||
|
||||
## 3. The planted corpus — observed, every rule fires
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --root tools/_work/leak-precedent/fixture --format json
|
||||
{ "root": "...\\tools\\_work\\leak-precedent\\fixture", "files_scanned": 7,
|
||||
"findings": [ ... 30 ... ], "exempted": [], "errors": [], "result": "leaks_found" }
|
||||
RESULT=leaks_found (exit 1)
|
||||
```
|
||||
|
||||
aggregated (the `findings` array of the same JSON run, grouped by category):
|
||||
|
||||
```
|
||||
files 7
|
||||
findings 30 {'appkey': 4, 'token': 5, 'device': 8, 'endpoint': 5, 'package': 5, 'path': 3}
|
||||
```
|
||||
|
||||
and the 30 hits by position, rule and value **shape** — every field of the report except the
|
||||
literal itself. Rule name, category, strength, position and count are the evidence; the quoted
|
||||
value is a copy of the leak, and copying it into a published document re-creates what the scan
|
||||
exists to prevent (§3b is where that rule was paid for):
|
||||
|
||||
```
|
||||
planted/package.txt:2:16 bundle_pkg_decl 4-segment all-lowercase reverse domain
|
||||
planted/package.txt:2:26 bundle_pkg_attr the same value, second rule on the same line
|
||||
planted/package.txt:3:1 bundle_pm_path 3-segment all-lowercase reverse domain, after `pm path`
|
||||
planted/package.txt:5:1 bundle_process_line 4-segment all-lowercase reverse domain, after `pidof`
|
||||
planted/package.txt:6:15 bundle_component 4-segment all-lowercase reverse domain, after `component=`
|
||||
|
||||
planted/device.txt:4:1 device_serial 16×[A-Z0-9], tab-separated from the word `device`
|
||||
planted/device.txt:4:1 device_serial_tabular the same value, second rule on the same line
|
||||
planted/device.txt:5:3 device_serial_context 16×[A-Z0-9], after `$ adb -s `
|
||||
planted/device.txt:5:10 device_serial the same value, second rule on the same line
|
||||
planted/device.txt:6:2 device_serial_context 16×[A-Z0-9], after `[serial `
|
||||
planted/device.txt:6:9 device_serial the same value, second rule on the same line
|
||||
planted/device.txt:7:1 device_serial_context 16×[A-Z0-9], after `device serial: ` (a second value)
|
||||
planted/device.txt:7:16 device_serial the same value, second rule on the same line
|
||||
|
||||
planted/token.txt:2:14 token_github_pat fixed provider prefix + 62×[A-Za-z0-9_]
|
||||
planted/token.txt:3:15 token_github_classic fixed 4-char provider prefix + 36×[A-Za-z0-9]
|
||||
planted/token.txt:4:1 token_env_assignment 20-char `AKIA`-prefixed key id after a key assignment
|
||||
planted/token.txt:5:9 token_authorization_header 32×[A-Za-z0-9] after an `Authorization:` keyword
|
||||
planted/appkey.txt:5:1 token_env_assignment the same 40-char secret, second rule on the same line
|
||||
|
||||
planted/appkey.txt:2:1 appkey_assignment 24×[0-9a-f] after an appkey assignment
|
||||
planted/appkey.txt:3:1 appkey_assignment 24×[0-9a-f], quoted, after a camelCase app-secret assignment
|
||||
planted/appkey.txt:4:1 appkey_assignment 7 dash-separated 4-character uppercase groups
|
||||
planted/appkey.txt:5:1 appkey_assignment 40-char mixed-case secret after a `SECRET_KEY` assignment
|
||||
|
||||
planted/endpoint.txt:2:7 plain_addr an RFC 5737 documentation address, with `:port`
|
||||
planted/endpoint.txt:2:7 plain_addr_ipliteral the bare form of the same address
|
||||
planted/endpoint.txt:3:16 plain_addr an RFC 1918 private-range address, with `:port`
|
||||
planted/endpoint.txt:3:16 plain_addr_ipliteral the bare form of the same address
|
||||
planted/endpoint.txt:4:12 plain_addr_ipliteral an RFC 5737 documentation address, bare
|
||||
|
||||
planted/path.txt:2:10 user_path_posix two-segment personal name after `/home/`
|
||||
planted/path.txt:3:6 user_path_posix one-word personal name after `/Users/`
|
||||
planted/path.txt:4:6 user_path_windows capitalized personal name after `C:\Users\`
|
||||
```
|
||||
|
||||
Two rules firing on one line (`SECRET_KEY=` matches both an appkey and a token pattern) is kept
|
||||
deliberately and is visible in the count; identical duplicates (same rule, same value, same
|
||||
line) are collapsed. Eight of the 30 findings share their line with a second rule — one package
|
||||
line, all four serial lines, the `SECRET_KEY` line and the two endpoint lines — which is why 30
|
||||
findings cover 22 distinct values (counted from the `findings` array of the JSON run above, not
|
||||
by hand).
|
||||
|
||||
### 3a. The exemption corpus — observed, and it is the half that is easy to get wrong
|
||||
|
||||
The same run with `--show-exempt` shows what was *not* reported from
|
||||
`fixture/exempt/benign.txt`, and the reason:
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --root tools/_work/leak-precedent/fixture --show-exempt
|
||||
== suppressed by exemption: 10 ==
|
||||
exempt/benign.txt:13 [user_path_windows] <user> -> placeholder user
|
||||
exempt/benign.txt:17 [plain_addr] 127.0.0.1:27042 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:17 [plain_addr_ipliteral] 127.0.0.1 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:17 [plain_addr] 0.0.0.0:8080 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:17 [plain_addr_ipliteral] 0.0.0.0 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:17 [plain_addr] 10.0.2.2:8080 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:17 [plain_addr_ipliteral] 10.0.2.2 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:18 [plain_addr] 127.0.0.1:8787 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:18 [plain_addr_ipliteral] 127.0.0.1 -> loopback/unspecified/emulator address
|
||||
exempt/benign.txt:18 [plain_addr_ipliteral] 169.254.169.254 -> loopback/unspecified/emulator address
|
||||
```
|
||||
|
||||
The earlier pass recorded 6 suppressed hits, all `plain_addr`; the current run reports the paired
|
||||
`plain_addr_ipliteral` for each exempt address as well, which is what the two same-line rules
|
||||
look like when nothing is being collapsed. The count moved from 6 to 10 for that reason and not
|
||||
because the exemption table changed — nothing in it was touched by this pass.
|
||||
|
||||
Everything else on that file — tool names, library names, function names, dex/ELF constant
|
||||
identifiers, protocol field names, CVE ids, hardening product names, the public crackme and its
|
||||
URL, platform and SDK packages, `com.example.*` / `probe.synthetic.*` and the `<PKG>`/`<DEVICE>`/
|
||||
`<hash>` placeholders — produced **no finding at all**, which is the intended outcome for the
|
||||
do-not-anonymize list and is also the check that the two synthetic fixture prefixes named in
|
||||
`references/desensitization-and-leak-scans.md` really are exempt: `com.example.app` sits on line
|
||||
83 of that file and is absent from both the findings and the suppressed list, because
|
||||
`BENIGN_PACKAGE_PREFIXES` contains `com.example`, `org.example`, `net.example`, `io.example` and
|
||||
`probe.synthetic`. The file was written to hold every category of that list, one line each, so a
|
||||
regression there shows up as a new finding rather than as a silent behavioural drift.
|
||||
|
||||
`169.254.169.254` (the cloud metadata endpoint) is exempted **only** in this documented-endpoint
|
||||
form. It is a real address that matters in a different context; the exemption is a judgement
|
||||
recorded in `BENIGN_IP_PREFIXES`, not a pattern match, and it is the entry most worth
|
||||
re-examining if this list is ever copied to another repository.
|
||||
|
||||
### 3b. The leak this file carried — found by the scanner it documents
|
||||
|
||||
The first version of this section listed all 30 hits **with their values**, quoted out of the
|
||||
JSON, because a report with the value in it is the concrete kind. The Lead then ran the tool
|
||||
against the repository and got `RESULT=leaks_found`, exit 1, with **26 strong/certain findings
|
||||
and 14 weak ones — all 26 strong ones inside this file**, at lines 113–146 of the version that
|
||||
existed then: the 5 bundle-id hits, 2 distinct device serials (12 hits), 2 provider-format tokens,
|
||||
2 inline assignment values, 2 SDK appkeys and 3 host user names it had just finished quoting.
|
||||
Nothing else in the tracked surface produced a strong hit.
|
||||
|
||||
That is the failure mode this whole pass exists to prevent, committed by the pass itself, and it
|
||||
states the boundary in one line: **the corpus is where identity is allowed; the published surface
|
||||
is not.** `tools/_work/leak-precedent/` is git-ignored and excluded from the default scan root so
|
||||
that it *can* hold the values — a corpus that does not contain them cannot demonstrate the rules
|
||||
firing. This file is not in that category: it is tracked, it is read, and every string in it is
|
||||
published.
|
||||
|
||||
The correction, applied in this pass:
|
||||
|
||||
1. The hit list in §3 now carries rule, category, strength, position, count and a **structural
|
||||
description** of each value, in the repository's own placeholder notation. No evidence was
|
||||
dropped: all 30 positions, all 17 rule ids, both strength labels and the per-category counts
|
||||
are still here, and the corpus still produces all 30 when it is scanned directly (§3).
|
||||
2. The two version-shaped literals in §4's false-positive table are now written in
|
||||
`<N>.<N>.<N>.<N>` form. They are legitimate values, but leaving them would put two *different*
|
||||
classes in the weak residue instead of one, and an unexplained second class is how a weak hit
|
||||
starts getting ignored.
|
||||
3. `references/desensitization-and-leak-scans.md` records the rule this produced — a report is a
|
||||
copy of what it found, so the report is scanned like any other published surface — and its
|
||||
exit table now carries the `leaks_found_strong_only` state.
|
||||
|
||||
The scanner's own verdict on the corrected tree is in §4a. The lesson is the one the reference
|
||||
file already made about entry points, applied to an evidence file: **run the scan on the file you
|
||||
are about to publish, not on the file you started from** — and then do not paste the thing it
|
||||
found back into that file.
|
||||
|
||||
## 4. The repository scan — observed, and the false positives that produced it
|
||||
|
||||
The first run against the real tree reported **28 findings**, of which 27 were wrong. The
|
||||
sequence is recorded in full because the corrections are the useful part: every one of them was
|
||||
found by running the scanner, not by reasoning about it.
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py # first run
|
||||
== leak scan: 118 file(s) scanned under the repository root ==
|
||||
findings by category: device=4, endpoint=20, package=4
|
||||
== result: 28 finding(s) == RESULT=leaks_found (exit 1)
|
||||
```
|
||||
|
||||
| # | Reported | Why it was wrong | Fix |
|
||||
|---|---|---|---|
|
||||
| 1 | a `jdk`-version-shaped run (`…\jdk-<N>.<N>.<N>.<N>`) ×19, across eight files in `docs/tool-verification/` | it is the JDK version in the toolchain's own path; the token `jdk` sits immediately before the match | a 30-character context window before the literal must not end in a version word (`jdk\|java\|python\|frida\|…`) |
|
||||
| 2 | `0000000040001000`, `0000000000714240` | tombstone register/`pc` values — 16 hex digits, all digits | an all-digit 16-character token is suppressed; a real platform serial carries at least one letter |
|
||||
| 3 | `0807060504030201` ×3 | a protobuf `fixed64` fixture in `EXTENSION-protobuf-raw.md` and in `scripts/protobuf_decode_raw.py` | same rule as #2 |
|
||||
| 4 | `sg.vantagepoint.uncrackable3` | the published package name of an OWASP MASTG crackme | `PUBLIC_TARGET_PREFIXES` (public crackme/benchmark families are reuse, not identity) |
|
||||
| 5 | `probe.synthetic.vmpdiff` | the synthetic manifest inside `vmp_diff_harness.py` | added `probe.synthetic` to the fixture prefixes |
|
||||
| 6 | `args.package.spli` (twice truncated to `spli`) | a property lookup in `scripts/spawn_patch_detach.py`; the exemption window was measured from the *match* start, which an unbounded `[^\n]*?` prefix pushes past the `args.` | the window starts at the **capture group** (`m.start(group)`), and the exemption reason is printed so the path can be audited |
|
||||
| 7 | `<N>.<N>.<N>.<N>` | an SDK version *directory* (`…/com.kwad.components.tachikoma/<N>.<N>.<N>.<N>/base-1_apk`) inside a private-storage path | a version-directory rule: a `.`-separated digit run enclosed in path separators is not an address |
|
||||
|
||||
Two rows in that table are quoted in placeholder form rather than as the literal the first run
|
||||
printed — row 1's four-part JDK version run and row 7's four-part SDK version run. Neither names
|
||||
anybody: both are version numbers, and both were rewritten in this pass for the reason given in
|
||||
§3b, because leaving them would put a second class (version runs, not addresses) into the weak
|
||||
residue, where an unexplained class is the first thing a reader learns to skip. The shape is what
|
||||
each row is about, and it survives the rewrite intact.
|
||||
|
||||
### 4a. What this pass inherited, and what it leaves — observed
|
||||
|
||||
Inherited state, reproduced at the start of this pass (same tree, before the §3b correction):
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py
|
||||
== leak scan: 128 file(s) scanned under the repository root ==
|
||||
findings by category: appkey=2, device=12, endpoint=14, package=5, path=3, token=4
|
||||
== result: 40 finding(s) -- each one is a line to look at, not a verdict ==
|
||||
RESULT=leaks_found (exit 1)
|
||||
```
|
||||
|
||||
26 of the 40 are strong/certain (`package` 5, `device` 12, `token` 4, `appkey` 2, `path` 3) and
|
||||
every one of those 26 is a line of this file's former §3 hit list, at lines 113–146. The other 14
|
||||
are weak: 5 more lines of that same block (its endpoint rows), 2 version strings in §4's own
|
||||
table, 3 RFC 5737 range literals in
|
||||
`skills/apk-reverse/references/desensitization-and-leak-scans.md`, and `scripts/tls_check.py`'s
|
||||
usage example.
|
||||
|
||||
Post-correction, on the tree this pass leaves behind:
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --quiet
|
||||
RESULT=leaks_found_strong_only (exit 0)
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py
|
||||
== leak scan: 129 file(s) scanned under the repository root ==
|
||||
findings by category: endpoint=4
|
||||
|
||||
skills/apk-reverse/references/desensitization-and-leak-scans.md:81:10 [endpoint/weak] plain_addr_ipliteral
|
||||
match: <RFC 5737 literal>
|
||||
skills/apk-reverse/references/desensitization-and-leak-scans.md:81:26 [endpoint/weak] plain_addr_ipliteral
|
||||
match: <RFC 5737 literal>
|
||||
skills/apk-reverse/references/desensitization-and-leak-scans.md:81:45 [endpoint/weak] plain_addr_ipliteral
|
||||
match: <RFC 5737 literal>
|
||||
skills/apk-reverse/scripts/tls_check.py:44:23 [endpoint/weak] plain_addr_ipliteral
|
||||
match: <RFC 5737 literal>
|
||||
|
||||
== result: 4 finding(s) -- each one is a line to look at, not a verdict ==
|
||||
all are `weak` (the documented address ranges); the gate is green under the default --fail-on strong, and `--fail-on any` is the strict pass
|
||||
RESULT=leaks_found_strong_only
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --quiet --fail-on any
|
||||
RESULT=leaks_found (exit 1)
|
||||
```
|
||||
|
||||
The four residual hits, by position, rule and class. Their individual values are deliberately not
|
||||
reprinted here — that is §3b's correction, and re-printing them is how this file leaked the first
|
||||
time. All four are the same class:
|
||||
|
||||
| position | rule / strength | class |
|
||||
|---|---|---|
|
||||
| `skills/apk-reverse/references/desensitization-and-leak-scans.md:81` ×3 | `plain_addr_ipliteral` / weak | the three RFC 5737 documentation blocks, named inside that file's own statement that they are *not* exempt |
|
||||
| `skills/apk-reverse/scripts/tls_check.py:44` | `plain_addr_ipliteral` / weak | the script's usage example, an RFC 5737 address |
|
||||
|
||||
Reading: **zero strong/certain findings and zero unexplained hits on the tracked surface; four
|
||||
weak ones, one class, both sources named.** The residue is the price of the design decision
|
||||
recorded in §"Deliberately *not* exempt" of the reference file: the documentation that states the
|
||||
decision has to name the ranges, and the ranges are exactly what the rule reports. That is why
|
||||
the gate's pass condition lives in `--fail-on` and not in the exemption table, and why
|
||||
`--fail-on any` stays red on this repository on purpose.
|
||||
|
||||
The file count is 129 here, 128 in the inherited run above and 119 in the first pass: the tracked
|
||||
surface grows while several writers work on it, and this pass added no file to the scanned
|
||||
surface, so the count is a property of the run rather than of the leak. The number that is
|
||||
comparable across the runs is the strong/certain one: **26 inherited, 0 now**. The inherited
|
||||
figure also reproduces the Lead's own catch (§3b) exactly, which is the point of quoting the
|
||||
transcript rather than the conclusion.
|
||||
|
||||
Two work artifacts of this pass live beside the corpus in the same git-ignored directory, and
|
||||
neither is part of the scanned surface: `EXTENSION-desensitization.before.md` (the pre-correction
|
||||
snapshot of this file, kept so that the correction is auditable in both directions) and
|
||||
`fixture-scan-before.txt` (a captured run of the fixture scan). Both contain the planted values
|
||||
by construction, exactly like the corpus, and both are excluded from every default run — the work
|
||||
area is where identity is allowed to exist; that is the whole of §3b's boundary.
|
||||
|
||||
## 5. The exit-code contract — observed, all four states
|
||||
|
||||
```
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --root LICENSE --quiet
|
||||
RESULT=clean (exit 0)
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --quiet
|
||||
RESULT=leaks_found_strong_only (exit 0) # the repository tree, weak hits only
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --quiet --fail-on any
|
||||
RESULT=leaks_found (exit 1) # the same tree, strict pass
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --root tools/_work/leak-precedent/fixture --quiet
|
||||
RESULT=leaks_found (exit 1)
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --root tools/_work/nope-not-here
|
||||
error: root does not exist: tools/_work/nope-not-here [stderr]
|
||||
RESULT=error (exit 2)
|
||||
|
||||
$ python skills/apk-reverse/scripts/scan_leaks.py --only nope
|
||||
error: unknown category (or categories): nope [stderr]
|
||||
RESULT=error (exit 2)
|
||||
```
|
||||
|
||||
The token and the exit code are deliberately separate channels: a wrapper that only greps
|
||||
stdout cannot tell "clean" from "the scanner never ran", and one that only reads `$?` cannot
|
||||
explain itself in a log.
|
||||
|
||||
`--fail-on` is what keeps those two channels from contradicting each other on a tree that is
|
||||
documentation-shaped. Under the default (`strong`) a tree whose only findings are `weak` reports
|
||||
`leaks_found_strong_only` and exits 0: the findings are still printed in full, they simply do not
|
||||
fail the gate. Under `--fail-on any` the same tree reports `leaks_found` and exits 1, which is the
|
||||
right verdict at publish time and the wrong one for a habit that runs on every change — a gate
|
||||
that is red on its own design documentation is a gate people disable.
|
||||
|
||||
## 6. What was not done
|
||||
|
||||
- **The `RESULT=` token convention was undocumented when this pass started, and it is documented
|
||||
now.** The Lead added `references/long-task-discipline.md` §Every script answers with a token,
|
||||
not with prose during this pass, so the scanner is no longer the convention's only user. That
|
||||
section's vocabulary is generic (`clean`, `patched`, `success`, `crash`, `timeout`,
|
||||
`unavailable`, …) and does not spell out `leaks_found` / `leaks_found_strong_only`; whether
|
||||
they belong in the enumeration is a Lead call. Verified with
|
||||
`grep -n "RESULT=" skills/apk-reverse/references/long-task-discipline.md` → one match, line 70.
|
||||
- **Nothing is wired into a gate.** No pre-commit hook, no CI job, no line in the maintenance
|
||||
three-command habit. The scanner has never run automatically; every result above is a manual
|
||||
invocation. Recorded as `unverified` in the sense that matters: whether it *would* be run is
|
||||
untested.
|
||||
- **No scan of the git-tracked list specifically.** The scan walks a filesystem root, so its
|
||||
coverage is "the default surface under this root", not "the files that exist in HEAD". A file
|
||||
that is present locally but ignored, or tracked but absent, is not distinguished.
|
||||
- **No check of binary or archive content.** `*.apk`, `*.png`, `*.pcap` and `*.zip` are not
|
||||
opened. Identity inside a screenshot or a capture file is real and this pass does not address
|
||||
it.
|
||||
- **No git-history scan.** A string deleted from the working tree remains in the history; nothing
|
||||
here inspects commits. This pass did check the one case it created: `git status --short` shows
|
||||
`docs/tool-verification/EXTENSION-desensitization.md` as `??` (untracked), so the values §3b
|
||||
removed were never committed and nothing was written into history. That is a check of this
|
||||
file, not a history scan.
|
||||
- **No second-language rule set.** Identifiers that are not reverse-domain shaped (a nickname, a
|
||||
local-part email, a CJK app name) are not covered. The rules are shape-based by construction.
|
||||
- **No cross-repository validation of the exemption list.** The benign prefixes were derived from
|
||||
this tree's own contents (a grep over its Markdown for reverse-domain tokens). Whether the same
|
||||
list is right for another repository is `unverified`, and the reference file says so.
|
||||
- **The `--max` / `--only` / `--exclude` paths were exercised only in the forms shown above.**
|
||||
`--max` was not driven at all.
|
||||
|
||||
## 7. One-line deliverable statement, and the open items
|
||||
|
||||
**Deliverable (verified):** `python skills/apk-reverse/scripts/scan_leaks.py` scans a repository
|
||||
root for six categories of target identity, reports each hit with a limited context window and a
|
||||
strength label, exits 0/1/2 with a matching `RESULT=` token, reports all 30 planted leaks in the
|
||||
reproducible corpus at `tools/_work/leak-precedent/fixture` (7 files, 10 further shapes admitted
|
||||
through the exemption path), and against this repository's 129-file tracked surface returns zero
|
||||
strong/certain findings — the residue is four `endpoint/weak` hits, all RFC 5737, both sources
|
||||
named in §4a — so the default gate is green (`RESULT=leaks_found_strong_only`, exit 0) while
|
||||
`--fail-on any` stays available as the strict pass (`RESULT=leaks_found`, exit 1).
|
||||
|
||||
**Open items for the Lead:**
|
||||
|
||||
1. Wire the scan into the maintenance gate (`check_repo.py`, `check_refs.py`, `scan_leaks.py`)
|
||||
and record in `README.md` that the third one's exit 1 is a *content* finding, not a
|
||||
mechanical failure like the other two.
|
||||
2. Decide on a history scan. Nothing in this pass looked at commits, and a leak removed from the
|
||||
tree is still in them.
|
||||
Reference in New Issue
Block a user