Skip to content

Commit 4ccd3b2

Browse files
authored
fix: remediate code scanning alerts (#15)
1 parent bf61382 commit 4ccd3b2

4 files changed

Lines changed: 53 additions & 6 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on:
66
pull_request:
77
branches: [main]
88

9+
permissions:
10+
contents: read
11+
912
jobs:
1013
test:
1114
runs-on: ubuntu-latest

packages/core/__tests__/core/sanitize.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from "vitest";
2-
import { sanitizeToolName } from "@execbox/core";
2+
import { sanitizeIdentifier, sanitizeToolName } from "@execbox/core";
33

44
describe("sanitizeToolName", () => {
55
it("replaces punctuation and spaces with underscores", () => {
@@ -18,3 +18,17 @@ describe("sanitizeToolName", () => {
1818
expect(sanitizeToolName("")).toBe("_");
1919
});
2020
});
21+
22+
describe("sanitizeIdentifier", () => {
23+
it("removes leading and trailing replacement underscores", () => {
24+
expect(sanitizeIdentifier(" ---tool name--- ")).toBe("tool_name");
25+
});
26+
27+
it("preserves internal underscores while trimming the edges", () => {
28+
expect(sanitizeIdentifier("tool---name")).toBe("tool_name");
29+
});
30+
31+
it("falls back to an underscore when all characters are trimmed away", () => {
32+
expect(sanitizeIdentifier("---")).toBe("_");
33+
});
34+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { readFileSync } from "node:fs";
2+
import { describe, expect, it } from "vitest";
3+
4+
describe("ci workflow", () => {
5+
it("declares least-privilege GITHUB_TOKEN permissions", () => {
6+
const workflow = readFileSync(
7+
new URL("../../../../.github/workflows/ci.yml", import.meta.url),
8+
"utf8",
9+
);
10+
11+
expect(workflow).toContain("permissions:");
12+
expect(workflow).toContain("contents: read");
13+
});
14+
});

packages/core/src/identifier.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@ const RESERVED_WORDS = new Set([
3939
"yield",
4040
]);
4141

42+
const UNDERSCORE_CHAR_CODE = 95;
43+
44+
function trimEdgeUnderscores(value: string): string {
45+
let start = 0;
46+
let end = value.length;
47+
48+
while (start < end && value.charCodeAt(start) === UNDERSCORE_CHAR_CODE) {
49+
start += 1;
50+
}
51+
52+
while (end > start && value.charCodeAt(end - 1) === UNDERSCORE_CHAR_CODE) {
53+
end -= 1;
54+
}
55+
56+
return value.slice(start, end);
57+
}
58+
4259
/**
4360
* Returns whether the value is a valid JavaScript identifier.
4461
*/
@@ -69,12 +86,11 @@ export function assertValidIdentifier(
6986
* Converts a raw identifier-like value into a safe JavaScript identifier.
7087
*/
7188
export function sanitizeIdentifier(value: string): string {
72-
const sanitized = value
73-
.trim()
74-
.replace(/[^A-Za-z0-9_$]+/g, "_")
75-
.replace(/^_+|_+$/g, "");
89+
const sanitized = value.trim().replace(/[^A-Za-z0-9_$]+/g, "_");
90+
91+
const trimmed = trimEdgeUnderscores(sanitized);
7692

77-
let safeName = sanitized.length > 0 ? sanitized : "_";
93+
let safeName = trimmed.length > 0 ? trimmed : "_";
7894

7995
if (/^[0-9]/.test(safeName)) {
8096
safeName = `_${safeName}`;

0 commit comments

Comments
 (0)