Skip to content

Commit 313c678

Browse files
authored
Revert "chore: refine the user inputs for RCE potentials"
1 parent b5ce421 commit 313c678

File tree

2 files changed

+8
-116
lines changed

2 files changed

+8
-116
lines changed

.github/actions/validate-template/action.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,5 @@ runs:
2828

2929
- name: Validate template
3030
id: validate-template
31-
env:
32-
INPUT_PATH: ${{ inputs.path }}
33-
INPUT_DIRECTORY: ${{ inputs.directory }}
34-
ACTION_PATH: ${{ github.action_path }}
35-
run: |
36-
result=$(deno run --allow-read "${ACTION_PATH}/src/main.ts" "${INPUT_PATH}" "${INPUT_DIRECTORY}")
37-
echo "result=${result}" >> "$GITHUB_OUTPUT"
31+
run: echo "::set-output name=result::$(deno run --allow-read ${{ github.action_path }}/src/main.ts ${{ inputs.path }} ${{ inputs.directory }})"
3832
shell: bash
Lines changed: 7 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,19 @@
11
import { writeAllSync } from 'https://deno.land/[email protected]/streams/mod.ts';
2-
import { resolve, normalize } from 'https://deno.land/[email protected]/path/mod.ts';
32
import validate from './validate.ts';
43

54
const DEFAULT_TEMPLATE_DIRECTORY = 'templates';
65

7-
/**
8-
* Validates that a path component is safe and does not contain:
9-
* - Path traversal sequences (../)
10-
* - Null bytes
11-
* - Shell metacharacters that could be used for injection
12-
* - Absolute paths when not expected
13-
*/
14-
const validatePathComponent = (input: string | undefined, name: string, required: boolean): string | undefined => {
15-
if (input === undefined || input === '') {
16-
if (required) {
17-
throw new Error(`${name} is required but was not provided`);
18-
}
19-
return undefined;
20-
}
21-
22-
// Check for null bytes (can be used to bypass security checks)
23-
if (input.includes('\0')) {
24-
throw new Error(`${name} contains invalid null bytes`);
25-
}
26-
27-
// Check for path traversal attempts
28-
const normalized = normalize(input);
29-
if (normalized.includes('..') || input.includes('..')) {
30-
throw new Error(`${name} contains path traversal sequences (..)`);
31-
}
32-
33-
// Check for dangerous shell metacharacters
34-
const dangerousChars = /[;&|`$(){}[\]<>!#*?~\n\r]/;
35-
if (dangerousChars.test(input)) {
36-
throw new Error(`${name} contains potentially dangerous characters`);
37-
}
38-
39-
// Check for excessively long paths (DoS prevention)
40-
const MAX_PATH_LENGTH = 4096;
41-
if (input.length > MAX_PATH_LENGTH) {
42-
throw new Error(`${name} exceeds maximum allowed length of ${MAX_PATH_LENGTH} characters`);
43-
}
44-
45-
return input;
46-
};
47-
48-
/**
49-
* Validates that the resolved path is within the expected base directory
50-
*/
51-
const validatePathWithinBase = (basePath: string, targetPath: string): void => {
52-
const resolvedBase = resolve(basePath);
53-
const resolvedTarget = resolve(targetPath);
54-
55-
if (!resolvedTarget.startsWith(resolvedBase)) {
56-
throw new Error(`Target path escapes the project root directory`);
57-
}
58-
};
59-
60-
/**
61-
* Validates that the path exists and is a directory
62-
*/
63-
const validateDirectoryExists = (path: string): void => {
64-
try {
65-
const stat = Deno.statSync(path);
66-
if (!stat.isDirectory) {
67-
throw new Error(`Path exists but is not a directory: ${path}`);
68-
}
69-
} catch (error) {
70-
if (error instanceof Deno.errors.NotFound) {
71-
throw new Error(`Directory does not exist: ${path}`);
72-
}
73-
throw error;
74-
}
75-
};
76-
77-
const outputError = (message: string): void => {
78-
const result = { status: 'error', detail: message };
6+
const main = () => {
7+
const PROJECT_ROOT = Deno.args[0];
8+
const TEMPLATE_DIRECTORY = Deno.args[1];
9+
const TEMPLATES_PATH = `${PROJECT_ROOT}/${
10+
TEMPLATE_DIRECTORY ?? DEFAULT_TEMPLATE_DIRECTORY
11+
}`;
12+
const result = validate(TEMPLATES_PATH);
7913
writeAllSync(
8014
Deno.stdout,
8115
new TextEncoder().encode(JSON.stringify(result)),
8216
);
8317
};
8418

85-
const main = () => {
86-
try {
87-
// Validate PROJECT_ROOT
88-
const PROJECT_ROOT = validatePathComponent(Deno.args[0], 'Project root path', true);
89-
if (!PROJECT_ROOT) {
90-
throw new Error('Project root path is required');
91-
}
92-
93-
// Validate TEMPLATE_DIRECTORY (optional)
94-
const TEMPLATE_DIRECTORY = validatePathComponent(Deno.args[1], 'Template directory', false)
95-
?? DEFAULT_TEMPLATE_DIRECTORY;
96-
97-
// Validate the template directory name itself
98-
validatePathComponent(TEMPLATE_DIRECTORY, 'Template directory', false);
99-
100-
// Construct and validate the full templates path
101-
const TEMPLATES_PATH = `${PROJECT_ROOT}/${TEMPLATE_DIRECTORY}`;
102-
103-
// Ensure the templates path stays within the project root
104-
validatePathWithinBase(PROJECT_ROOT, TEMPLATES_PATH);
105-
106-
// Verify the directory exists
107-
validateDirectoryExists(TEMPLATES_PATH);
108-
109-
const result = validate(TEMPLATES_PATH);
110-
writeAllSync(
111-
Deno.stdout,
112-
new TextEncoder().encode(JSON.stringify(result)),
113-
);
114-
} catch (error) {
115-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
116-
outputError(errorMessage);
117-
Deno.exit(1);
118-
}
119-
};
120-
12119
main();

0 commit comments

Comments
 (0)