Skip to content

Commit 8704cb4

Browse files
committed
fix: local mode
1 parent 8db7867 commit 8704cb4

File tree

6 files changed

+103
-71
lines changed

6 files changed

+103
-71
lines changed

__tests__/main.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ describe('action', () => {
253253
});
254254

255255
await main.run();
256-
expect(_setFailedMock).toHaveBeenCalledWith('access-token is required when not in standalone mode');
256+
expect(_setFailedMock).toHaveBeenCalledWith('access-token is required when not in standalone or local mode');
257257
}, 30000);
258258

259259
it('processes dotEnvFile content', async () => {

badges/coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

dist/index.js

Lines changed: 47 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.ts

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,58 +36,75 @@ function sanitizeInput(input: string): string {
3636
return input.replace(/[;&|`$()<>\\]/g, '');
3737
}
3838

39+
/**
40+
* Checks if command contains dangerous characters
41+
*/
42+
function containsDangerousCharacters(command: string): boolean {
43+
const dangerousPatterns = ['&&', '||', ';', '|', '`', '$(', '>', '<'];
44+
return dangerousPatterns.some((pattern) => command.includes(pattern));
45+
}
46+
47+
/**
48+
* Processes a character during command parsing
49+
*/
50+
function processCharacter(
51+
char: string,
52+
index: number,
53+
command: string,
54+
state: { inQuotes: boolean; quoteChar: string; current: string }
55+
): void {
56+
const isQuote = char === '"' || char === "'";
57+
const isEscaped = index > 0 && command[index - 1] === '\\';
58+
59+
if (isQuote && !isEscaped) {
60+
if (!state.inQuotes) {
61+
state.inQuotes = true;
62+
state.quoteChar = char;
63+
} else if (char === state.quoteChar) {
64+
state.inQuotes = false;
65+
state.quoteChar = '';
66+
} else {
67+
state.current += char;
68+
}
69+
} else if (char === ' ' && !state.inQuotes) {
70+
// Space handling is done in the main function
71+
return;
72+
} else {
73+
state.current += char;
74+
}
75+
}
76+
3977
/**
4078
* Validates and parses command arguments safely
4179
*/
4280
function parseCommand(command: string): string[] {
4381
// Basic validation to prevent obvious injection attempts
44-
if (
45-
command.includes('&&') ||
46-
command.includes('||') ||
47-
command.includes(';') ||
48-
command.includes('|') ||
49-
command.includes('`') ||
50-
command.includes('$(') ||
51-
command.includes('>') ||
52-
command.includes('<')
53-
) {
82+
if (containsDangerousCharacters(command)) {
5483
throw new Error('Command contains potentially dangerous characters. Please use simple commands only.');
5584
}
5685

5786
// Split by spaces but respect quoted strings
5887
const args: string[] = [];
59-
let current = '';
60-
let inQuotes = false;
61-
let quoteChar = '';
88+
const state = { current: '', inQuotes: false, quoteChar: '' };
6289

6390
for (let i = 0; i < command.length; i++) {
6491
const char = command[i];
6592

66-
if ((char === '"' || char === "'") && (i === 0 || command[i - 1] !== '\\')) {
67-
if (!inQuotes) {
68-
inQuotes = true;
69-
quoteChar = char;
70-
} else if (char === quoteChar) {
71-
inQuotes = false;
72-
quoteChar = '';
73-
} else {
74-
current += char;
75-
}
76-
} else if (char === ' ' && !inQuotes) {
77-
if (current) {
78-
args.push(current);
79-
current = '';
93+
if (char === ' ' && !state.inQuotes) {
94+
if (state.current) {
95+
args.push(state.current);
96+
state.current = '';
8097
}
8198
} else {
82-
current += char;
99+
processCharacter(char, i, command, state);
83100
}
84101
}
85102

86-
if (current) {
87-
args.push(current);
103+
if (state.current) {
104+
args.push(state.current);
88105
}
89106

90-
if (inQuotes) {
107+
if (state.inQuotes) {
91108
throw new Error('Unclosed quote in command');
92109
}
93110

@@ -259,8 +276,9 @@ export async function run(): Promise<void> {
259276

260277
// Validate inputs for non-standalone mode
261278
const isStandalone = instance === 'standalone';
262-
if (!isStandalone && !accessToken) {
263-
throw new Error('access-token is required when not in standalone mode');
279+
const isLocal = instance === 'local';
280+
if (!isStandalone && !accessToken && !isLocal) {
281+
throw new Error('access-token is required when not in standalone or local mode');
264282
}
265283

266284
// Setup output masking for sensitive values

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"forceConsistentCasingInFileNames": true,
1414
"strict": true,
1515
"skipLibCheck": true,
16-
"newLine": "lf"
16+
"newLine": "lf",
17+
"isolatedModules": true
1718
},
1819
"exclude": ["./dist", "./node_modules", "./__tests__", "./coverage"]
1920
}

0 commit comments

Comments
 (0)