Skip to content

Commit 5aa9c5e

Browse files
committed
Updated script and tests, added README
1 parent 7d3252c commit 5aa9c5e

4 files changed

Lines changed: 48 additions & 11 deletions

File tree

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ Optionally, filter by a particular action, possibly including a commit SHA of in
1313

1414
## Usage
1515

16-
Set a `GITHUB_TOKEN` in the environment with appropriate access to the audit log on your org or Enterprise.
16+
For all scripts, you must set a `GITHUB_TOKEN` in the environment with appropriate access to the audit log on your org or Enterprise, or the repository you are interested in.
1717

1818
For Enterprise Server or Data Residency users, please set `GITHUB_BASE_URL` in your environment, e.g. `https://github.acme-inc.com/api/v3`
1919

20+
### audit_workflow_runs.js
21+
2022
```text
2123
node audit_workflow_runs.js <org or enterprise name> <ent|org|repo> <start date> <end date> [<action>] [<commit SHA>]
2224
```
@@ -29,6 +31,24 @@ For example:
2931
node audit_workflow_runs.js github org 2025-03-13 2025-03-15 tj-actions/changed-files 0e58ed8671d6b60d0890c21b07f8835ace038e67
3032
```
3133

34+
### find_compromised_secrets.js
35+
36+
This script takes the output of `audit_workflow_runs.js` and searches for secrets that were used in a workflow run.
37+
38+
Take the output from the single-line JSON file for any known compromised Actions and run it through this script.
39+
40+
```text
41+
node find_compromised_secrets.js < <path sljson file>
42+
```
43+
44+
Results are printed to the console, and written to a file in the current directory, named `compromised_secrets.sljson`.
45+
46+
For example:
47+
48+
```bash
49+
node find_compromised_secrets.js < workflow_audit_results.sljson
50+
```
51+
3252
## Changelog
3353

3454
### 2025-05-20 15:10Z

find_compromised_secrets.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ async function main() {
101101
continue;
102102
}
103103
}
104+
105+
for (const secret of all_secrets) {
106+
// write to a file
107+
fs.appendFileSync("compromised_secrets.sljson", JSON.stringify(secret) + "\n");
108+
}
104109
}
105110

106111
await main();

find_compromised_secrets_helper.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11

22
// base64 strings were used to leak the secrets
3-
export const base64Regex =
4-
/^(?:[A-Za-z0-9+/]{4}){5,}(?:|[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)$/;
3+
export const base64Regex1 =
4+
/^(?:[A-Za-z0-9+/]{4}){16,}(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)\s*$/;
55

6-
export function findSecretsInLines(lines, base64Regex) {
6+
export const base64Regex2 =
7+
/^(?:[A-Za-z0-9+/]{4}){10,}(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)\s*$/;
8+
9+
export function findSecretsInLines(lines) {
710
const secrets = [];
811

912
for (const line of lines) {
@@ -18,7 +21,7 @@ export function findSecretsInLines(lines, base64Regex) {
1821
continue;
1922
}
2023

21-
const match = base64Regex.exec(data);
24+
const match = base64Regex1.exec(data);
2225
if (!match) {
2326
continue;
2427
}
@@ -28,8 +31,9 @@ export function findSecretsInLines(lines, base64Regex) {
2831
try {
2932
const decodedOnce = Buffer.from(secret, "base64").toString();
3033

31-
const match2 = base64Regex.exec(decodedOnce);
34+
const match2 = base64Regex2.exec(decodedOnce);
3235
if (!match2) {
36+
console.log("Failed to match base64 data after first decode: " + decodedOnce);
3337
continue;
3438
}
3539

@@ -42,6 +46,7 @@ export function findSecretsInLines(lines, base64Regex) {
4246
secrets.push(jsonDecoded);
4347
}
4448
} catch (error) {
49+
console.log("Failed to decode JSON data after second decode: " + decoded);
4550
continue;
4651
}
4752
} catch (error) {
@@ -50,4 +55,4 @@ export function findSecretsInLines(lines, base64Regex) {
5055
}
5156

5257
return secrets;
53-
}
58+
}

test_find_compromised_secrets.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import assert from "assert";
2-
import { findSecretsInLines, base64Regex } from "./find_compromised_secrets_helper.js";
2+
import { findSecretsInLines, base64Regex1 } from "./find_compromised_secrets_helper.js";
33

44
function testFindSecretsInLines() {
55
console.log("Running test for findSecretsInLines...");
66

77
// Simulate reading lines from a file
88
const lines = [
99
"2025-03-20T12:01:00Z SW1kcGRHaDFZbDkwYjJ0bGJpSTZleUoyWVd4MVpTSTZJbWRvYzE4d01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREF3TURBd01EQXdNREFpTENBaWFYTlRaV055WlhRaU9pQjBjblZsZlFvPQo=",
10+
"2025-03-20T12:00:00Z SWpBaU9uc2lkbUZzZFdVaU9pSmhJaXdnSW1selUyVmpjbVYwSWpwMGNuVmxmUW89Cg==",
1011
"2025-03-20T12:00:00Z Some log message",
1112
"2025-03-20T12:02:00Z Another log message",
1213
"",
1314
];
1415

15-
const data = "AAAAAAAAAAAAAAAA";
16+
const data = "SWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1617

17-
const match = base64Regex.exec(data);
18+
const match = base64Regex1.exec(data);
1819

1920
assert(match, "Failed to match base64 data");
2021

@@ -25,11 +26,17 @@ function testFindSecretsInLines() {
2526
isSecret: true,
2627
value: 'ghs_000000000000000000000000000000000'
2728
}
29+
},
30+
{
31+
"0": {
32+
isSecret: true,
33+
value: 'a'
34+
}
2835
}
2936
];
3037

3138
// Call the function
32-
const secrets = findSecretsInLines(lines, base64Regex);
39+
const secrets = findSecretsInLines(lines);
3340

3441
// Assert the results
3542
assert.deepStrictEqual(

0 commit comments

Comments
 (0)