pi-git-auth 1.0.1 → 1.1.0
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 +5 -0
- package/index.ts +20 -0
- package/package.json +3 -5
- package/redact.ts +32 -0
- package/preview.png +0 -0
package/README.md
CHANGED
|
@@ -36,6 +36,10 @@ TypeScript directly.
|
|
|
36
36
|
- A `tool_call` hook watches every `bash` invocation. When an active
|
|
37
37
|
account exists and the command runs `git`, the command is rewritten to
|
|
38
38
|
authenticate that account's host (see [git auth](#git-auth)).
|
|
39
|
+
- A `tool_result` hook masks token-shaped strings (GitHub/GitLab PATs,
|
|
40
|
+
URL-embedded credentials) in **every** tool output before it enters
|
|
41
|
+
the transcript — an accidental `env` dump or config echo can never
|
|
42
|
+
print the live token into the conversation.
|
|
39
43
|
|
|
40
44
|
## Layout
|
|
41
45
|
|
|
@@ -50,6 +54,7 @@ github.ts GitHub REST client
|
|
|
50
54
|
gitlab.ts GitLab REST client
|
|
51
55
|
details.ts read-only repo details overlay (tree + commits + metadata)
|
|
52
56
|
git-gate.ts command rewriting that injects the token for a host
|
|
57
|
+
redact.ts secret redaction of tool outputs (PAT / URL-credential patterns)
|
|
53
58
|
```
|
|
54
59
|
|
|
55
60
|
## Usage
|
package/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { loadStore, activeAccount } from "./store";
|
|
|
5
5
|
import { SERVICES } from "./forge";
|
|
6
6
|
import { findAccounts, setActiveAccount, statusDetail } from "./auth";
|
|
7
7
|
import { instrumentGit } from "./git-gate";
|
|
8
|
+
import { redactSecrets } from "./redact";
|
|
8
9
|
import { handleAuthCommand } from "./commands";
|
|
9
10
|
|
|
10
11
|
export default function (pi: ExtensionAPI) {
|
|
@@ -20,6 +21,25 @@ export default function (pi: ExtensionAPI) {
|
|
|
20
21
|
event.input.command = instrumentGit(event.input.command, host, acc.accessToken);
|
|
21
22
|
});
|
|
22
23
|
|
|
24
|
+
// ------------------------------------------------------------------
|
|
25
|
+
// Secret redaction: never let token-shaped strings reach the
|
|
26
|
+
// transcript. The gate keeps the token out of argv and off disk,
|
|
27
|
+
// but any bash output (env dump, config echo) would otherwise land
|
|
28
|
+
// in the session file and the conversation.
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
pi.on("tool_result", (event) => {
|
|
31
|
+
let changed = false;
|
|
32
|
+
const content = event.content.map((block) => {
|
|
33
|
+
if (block.type !== "text") return block;
|
|
34
|
+
const text = redactSecrets(block.text);
|
|
35
|
+
if (text === block.text) return block;
|
|
36
|
+
changed = true;
|
|
37
|
+
return { ...block, text };
|
|
38
|
+
});
|
|
39
|
+
if (!changed) return;
|
|
40
|
+
return { content };
|
|
41
|
+
});
|
|
42
|
+
|
|
23
43
|
// ------------------------------------------------------------------
|
|
24
44
|
// /auth command
|
|
25
45
|
// ------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-git-auth",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "pi coding-agent extension: git auth for GitHub and GitLab: keyring-stored login tokens, account switching, transparent git auth, repo list/create with details overlay",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Carlo Onofrio",
|
|
@@ -22,8 +22,7 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
"*.ts",
|
|
24
24
|
"README.md",
|
|
25
|
-
"LICENSE"
|
|
26
|
-
"preview.png"
|
|
25
|
+
"LICENSE"
|
|
27
26
|
],
|
|
28
27
|
"engines": {
|
|
29
28
|
"node": ">=20"
|
|
@@ -36,7 +35,6 @@
|
|
|
36
35
|
"pi": {
|
|
37
36
|
"extensions": [
|
|
38
37
|
"./index.ts"
|
|
39
|
-
]
|
|
40
|
-
"image": "https://raw.githubusercontent.com/comicrocharly/pi-git-auth/main/preview.png"
|
|
38
|
+
]
|
|
41
39
|
}
|
|
42
40
|
}
|
package/redact.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction for tool results.
|
|
3
|
+
*
|
|
4
|
+
* The git gate keeps the active token out of argv and off disk, but a
|
|
5
|
+
* bash command (an `env` dump, a `git config` echo, a `printenv`) can
|
|
6
|
+
* still print it into the tool output, which then lands in the session
|
|
7
|
+
* transcript. This module masks token-shaped strings in tool results
|
|
8
|
+
* before they are stored, so an accidental echo can never put the live
|
|
9
|
+
* token into the conversation — and there is nothing to rotate because
|
|
10
|
+
* of it.
|
|
11
|
+
*
|
|
12
|
+
* Patterns (masked to a short fingerprint, e.g. `ghp_…7SAQ`):
|
|
13
|
+
* - GitHub classic PATs: gh[pousr]_ + 20+ base62
|
|
14
|
+
* - GitHub fine-grained PATs: github_pat_ + 30+
|
|
15
|
+
* - GitLab PATs: glpat- + 16+
|
|
16
|
+
* - URL-embedded credentials: user:secret@ — the secret part only
|
|
17
|
+
*
|
|
18
|
+
* Masking is idempotent: a masked string never matches the patterns
|
|
19
|
+
* again, so repeated passes are a no-op.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
function maskTail(match: string, head: number): string {
|
|
23
|
+
return match.length <= head + 4 ? "***" : `${match.slice(0, head)}…${match.slice(-4)}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function redactSecrets(text: string): string {
|
|
27
|
+
return text
|
|
28
|
+
.replace(/\bgh[pousr]_[A-Za-z0-9]{20,}/g, (m) => maskTail(m, 4))
|
|
29
|
+
.replace(/\bgithub_pat_[A-Za-z0-9_]{30,}/g, (m) => maskTail(m, 10))
|
|
30
|
+
.replace(/\bglpat-[A-Za-z0-9_-]{16,}/g, (m) => maskTail(m, 6))
|
|
31
|
+
.replace(/(\/\/[^/\s:@]+:)([^@\s]{4,})(@)/g, "$1***$3");
|
|
32
|
+
}
|
package/preview.png
DELETED
|
Binary file
|