rulereceipt 0.1.21 → 0.1.22
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 +8 -0
- package/dist/report/generateHtmlReport.js +26 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -116,6 +116,14 @@ function writeHtmlReport(results, meta, cwd, target) {
|
|
|
116
116
|
writeFileSync(outPath, html, "utf-8");
|
|
117
117
|
console.log(`\nShareable report written to ${outPath}`);
|
|
118
118
|
console.log("Open it in a browser, attach it to an email, or print it to PDF. It's a single self-contained file.");
|
|
119
|
+
// Found by dogfooding on a real session (2026-08-31): this file
|
|
120
|
+
// reproduces rule text and quoted evidence verbatim, which is exactly
|
|
121
|
+
// what makes it useful — and means it inherits whatever is in the
|
|
122
|
+
// rules file. A real CLAUDE.md turned out to contain an employer
|
|
123
|
+
// name, an office email, and absolute paths. Home paths are redacted
|
|
124
|
+
// automatically; nothing else can be, so say so plainly at the moment
|
|
125
|
+
// the file is created rather than burying it in a policy page.
|
|
126
|
+
console.log("Read it before you send it: it quotes your rule text and session evidence verbatim, so anything sensitive in your CLAUDE.md is in there too. (Home paths are shortened to ~.)");
|
|
119
127
|
}
|
|
120
128
|
catch (err) {
|
|
121
129
|
console.log(`\n(--html: couldn't write ${outPath} — ${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
+
import { homedir } from "node:os";
|
|
2
3
|
import { computeTranscriptHash } from "./generateReport.js";
|
|
3
4
|
/**
|
|
4
5
|
* Escapes the five characters that can break out of either an HTML text
|
|
@@ -21,9 +22,33 @@ function escapeHtml(value) {
|
|
|
21
22
|
function stripControlChars(value) {
|
|
22
23
|
return value.replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Replaces the user's home directory with `~`.
|
|
27
|
+
*
|
|
28
|
+
* Found by dogfooding on a real session (2026-08-31): the shareable
|
|
29
|
+
* report is the one output explicitly designed to be emailed to someone
|
|
30
|
+
* else, and it was printing absolute paths like
|
|
31
|
+
* /Users/<realname>/Desktop/... in both the project header and inside
|
|
32
|
+
* quoted evidence. For anyone publishing under a pseudonym — or simply
|
|
33
|
+
* anyone who would rather not hand a stranger their username and
|
|
34
|
+
* directory layout — that is a leak in the one artifact most likely to
|
|
35
|
+
* leave the machine.
|
|
36
|
+
*
|
|
37
|
+
* This is a mechanical, judgment-free redaction: it removes the home
|
|
38
|
+
* prefix and nothing else. It is NOT a general secret scrubber, and must
|
|
39
|
+
* not be described as one. Rule text and evidence are still reproduced
|
|
40
|
+
* verbatim, because that is what makes the report useful — which is why
|
|
41
|
+
* the CLI warns the user to read the file before sending it.
|
|
42
|
+
*/
|
|
43
|
+
function redactHome(value) {
|
|
44
|
+
const home = homedir();
|
|
45
|
+
if (!home || home === "/" || home.length < 4)
|
|
46
|
+
return value;
|
|
47
|
+
return value.split(home).join("~");
|
|
48
|
+
}
|
|
24
49
|
/** Single choke point: nothing untrusted reaches the document except through this. */
|
|
25
50
|
function clean(value) {
|
|
26
|
-
return escapeHtml(stripControlChars(value));
|
|
51
|
+
return escapeHtml(stripControlChars(redactHome(value)));
|
|
27
52
|
}
|
|
28
53
|
function bucketOf(result) {
|
|
29
54
|
if (result.status === "FAIL")
|