Skip to content

refactoring(check_pr): Move script in github_scripts dir#138

Closed
cap-ang wants to merge 1 commit intomainfrom
refactoring-check_pr
Closed

refactoring(check_pr): Move script in github_scripts dir#138
cap-ang wants to merge 1 commit intomainfrom
refactoring-check_pr

Conversation

@cap-ang
Copy link
Contributor

@cap-ang cap-ang commented Feb 11, 2026

List of Changes

Motivation and Context

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

@cap-ang cap-ang self-assigned this Feb 11, 2026
@cap-ang cap-ang requested a review from a team as a code owner February 11, 2026 10:15
@cap-ang cap-ang added the skip label Feb 11, 2026
@github-actions
Copy link

Comment this PR with update_code to update openapi.json and format the code. Consider to use pre-commit to format the code.

const execSync = require('child_process').execSync;
for (const file of IGNORED_FILES.trim().split(',')) {

const ignored_additions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})

Check warning

Code scanning / CodeQL

Indirect uncontrolled command line Medium

This command depends on an unsanitized
environment variable
.

Copilot Autofix

AI 3 days ago

In general, the fix is to stop passing untrusted data (like environment variables) into shell commands via string concatenation. Instead, use an API that does not invoke a shell and accepts the command and its arguments as an array (e.g., child_process.execFileSync or spawnSync), or, if a shell is unavoidable, properly escape any untrusted values before interpolation.

For this specific file, the problematic parts are lines 14–15, where execSync is called with a shell command string containing BRANCH_NAME and a pipeline to grep/cut. We can replace the use of execSync with execFileSync and pass the arguments as an array so that BRANCH_NAME is not interpreted by a shell. To preserve existing behavior (which uses grep and cut to process the git diff --numstat output), we can instead: (1) call git directly via execFileSync with arguments ['--no-pager','diff','--numstat',\origin/main..origin/${BRANCH_NAME}`], (2) parse the resulting text in JavaScript to extract additions and deletions for each ignored file, and (3) compute the totals as before. This avoids any shell, gets rid of grep/cut, and keeps functionality equivalent. Concretely, inside .github/workflows/github_scripts/check_size.js, we will: add a require('child_process').execFileSyncalongside (or replacing)execSync, call it once to obtain the diff output, then for each fileinignored_files`, parse that shared diff output and sum the additions/deletions for matching lines. Lines 11–22 will be updated accordingly, with no changes to surrounding logic.

Suggested changeset 1
.github/workflows/github_scripts/check_size.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/github_scripts/check_size.js b/.github/workflows/github_scripts/check_size.js
--- a/.github/workflows/github_scripts/check_size.js
+++ b/.github/workflows/github_scripts/check_size.js
@@ -8,19 +8,19 @@
     const ignored_files = IGNORED_FILES.trim().split(',').filter(word => word.length > 0);
     if (ignored_files.length > 0) {
         var ignored = 0
-        const execSync = require('child_process').execSync;
-        for (const file of IGNORED_FILES.trim().split(',')) {
+        const execFileSync = require('child_process').execFileSync;
+        const diffOutput = execFileSync('git', ['--no-pager', 'diff', '--numstat', 'origin/main..origin/' + BRANCH_NAME], {encoding: 'utf-8'});
+        for (const file of ignored_files) {
+            const lines = diffOutput.split('\n').filter(l => l.includes(file));
+            const ignored_additions = lines
+                .map(l => l.trim().split('\t')[0])
+                .map(val => parseInt(val || 0))
+                .reduce((accumulator, currentValue) => accumulator + currentValue, 0);
+            const ignored_deletions = lines
+                .map(l => l.trim().split('\t')[1])
+                .map(val => parseInt(val || 0))
+                .reduce((accumulator, currentValue) => accumulator + currentValue, 0);
 
-            const ignored_additions_str = execSync('git --no-pager  diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})
-            const ignored_deletions_str = execSync('git --no-pager  diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 2', {encoding: 'utf-8'})
-
-            const ignored_additions = ignored_additions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
-                (accumulator, currentValue) => accumulator + currentValue,
-                0);
-            const ignored_deletions = ignored_deletions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
-                (accumulator, currentValue) => accumulator + currentValue,
-                0);
-
             ignored += ignored_additions + ignored_deletions;
         }
         changes -= ignored
EOF
@@ -8,19 +8,19 @@
const ignored_files = IGNORED_FILES.trim().split(',').filter(word => word.length > 0);
if (ignored_files.length > 0) {
var ignored = 0
const execSync = require('child_process').execSync;
for (const file of IGNORED_FILES.trim().split(',')) {
const execFileSync = require('child_process').execFileSync;
const diffOutput = execFileSync('git', ['--no-pager', 'diff', '--numstat', 'origin/main..origin/' + BRANCH_NAME], {encoding: 'utf-8'});
for (const file of ignored_files) {
const lines = diffOutput.split('\n').filter(l => l.includes(file));
const ignored_additions = lines
.map(l => l.trim().split('\t')[0])
.map(val => parseInt(val || 0))
.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
const ignored_deletions = lines
.map(l => l.trim().split('\t')[1])
.map(val => parseInt(val || 0))
.reduce((accumulator, currentValue) => accumulator + currentValue, 0);

const ignored_additions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})
const ignored_deletions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 2', {encoding: 'utf-8'})

const ignored_additions = ignored_additions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
(accumulator, currentValue) => accumulator + currentValue,
0);
const ignored_deletions = ignored_deletions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
(accumulator, currentValue) => accumulator + currentValue,
0);

ignored += ignored_additions + ignored_deletions;
}
changes -= ignored
Copilot is powered by AI and may make mistakes. Always verify output.
for (const file of IGNORED_FILES.trim().split(',')) {

const ignored_additions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})
const ignored_deletions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 2', {encoding: 'utf-8'})

Check warning

Code scanning / CodeQL

Indirect uncontrolled command line Medium

This command depends on an unsanitized
environment variable
.

Copilot Autofix

AI 3 days ago

In general, the problem should be fixed by avoiding shell command construction with string concatenation for untrusted data, and instead using APIs that accept an argument array and do not invoke a shell (child_process.execFileSync or spawnSync with shell: false). This prevents shell metacharacters in BRANCH_NAME (or in file) from being interpreted by a shell.

The best fix here is to (1) switch from execSync to execFileSync and (2) replace the grep/cut pipeline with logic implemented in JavaScript: run git diff --numstat as git with arguments, capture its stdout, then filter lines and extract columns in Node. This removes all shell parsing and still preserves behavior.

Concretely, in .github/workflows/github_scripts/check_size.js:

  • At line 11, change the import from execSync to execFileSync.
  • Replace the two execSync('git --no-pager diff ... | grep ... | cut -f N', ...) calls at lines 14–15 with a single execFileSync('git', [...]) call that gets the full --numstat output once per loop iteration (or once total; but to avoid broader refactoring, keep it per loop), then:
    • Split the output into lines.
    • For each line that includes file, split on whitespace to get additions, deletions, and filename.
    • Accumulate additions and deletions into ignored_additions_str and ignored_deletions_str-equivalents (or directly into numbers).
  • Maintain the rest of the logic (parsing, reducing) so functionality stays the same.

No extra external libraries are needed; we only use the standard child_process module and string processing.

Suggested changeset 1
.github/workflows/github_scripts/check_size.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/github_scripts/check_size.js b/.github/workflows/github_scripts/check_size.js
--- a/.github/workflows/github_scripts/check_size.js
+++ b/.github/workflows/github_scripts/check_size.js
@@ -8,19 +8,38 @@
     const ignored_files = IGNORED_FILES.trim().split(',').filter(word => word.length > 0);
     if (ignored_files.length > 0) {
         var ignored = 0
-        const execSync = require('child_process').execSync;
+        const execFileSync = require('child_process').execFileSync;
         for (const file of IGNORED_FILES.trim().split(',')) {
 
-            const ignored_additions_str = execSync('git --no-pager  diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})
-            const ignored_deletions_str = execSync('git --no-pager  diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 2', {encoding: 'utf-8'})
+            const numstatOutput = execFileSync(
+                'git',
+                ['--no-pager', 'diff', '--numstat', `origin/main..origin/${BRANCH_NAME}`],
+                {encoding: 'utf-8'}
+            );
 
-            const ignored_additions = ignored_additions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
-                (accumulator, currentValue) => accumulator + currentValue,
-                0);
-            const ignored_deletions = ignored_deletions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
-                (accumulator, currentValue) => accumulator + currentValue,
-                0);
+            const matchingLines = numstatOutput
+                .split('\n')
+                .filter(line => line && line.includes(file));
 
+            const additionsList = [];
+            const deletionsList = [];
+
+            for (const line of matchingLines) {
+                const parts = line.trim().split(/\s+/);
+                if (parts.length >= 3) {
+                    additionsList.push(parts[0]);
+                    deletionsList.push(parts[1]);
+                }
+            }
+
+            const ignored_additions = additionsList
+                .map(elem => parseInt(elem || 0))
+                .reduce((accumulator, currentValue) => accumulator + currentValue, 0);
+
+            const ignored_deletions = deletionsList
+                .map(elem => parseInt(elem || 0))
+                .reduce((accumulator, currentValue) => accumulator + currentValue, 0);
+
             ignored += ignored_additions + ignored_deletions;
         }
         changes -= ignored
EOF
@@ -8,19 +8,38 @@
const ignored_files = IGNORED_FILES.trim().split(',').filter(word => word.length > 0);
if (ignored_files.length > 0) {
var ignored = 0
const execSync = require('child_process').execSync;
const execFileSync = require('child_process').execFileSync;
for (const file of IGNORED_FILES.trim().split(',')) {

const ignored_additions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 1', {encoding: 'utf-8'})
const ignored_deletions_str = execSync('git --no-pager diff --numstat origin/main..origin/' + BRANCH_NAME + ' | grep ' + file + ' | cut -f 2', {encoding: 'utf-8'})
const numstatOutput = execFileSync(
'git',
['--no-pager', 'diff', '--numstat', `origin/main..origin/${BRANCH_NAME}`],
{encoding: 'utf-8'}
);

const ignored_additions = ignored_additions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
(accumulator, currentValue) => accumulator + currentValue,
0);
const ignored_deletions = ignored_deletions_str.split('\n').map(elem => parseInt(elem || 0)).reduce(
(accumulator, currentValue) => accumulator + currentValue,
0);
const matchingLines = numstatOutput
.split('\n')
.filter(line => line && line.includes(file));

const additionsList = [];
const deletionsList = [];

for (const line of matchingLines) {
const parts = line.trim().split(/\s+/);
if (parts.length >= 3) {
additionsList.push(parts[0]);
deletionsList.push(parts[1]);
}
}

const ignored_additions = additionsList
.map(elem => parseInt(elem || 0))
.reduce((accumulator, currentValue) => accumulator + currentValue, 0);

const ignored_deletions = deletionsList
.map(elem => parseInt(elem || 0))
.reduce((accumulator, currentValue) => accumulator + currentValue, 0);

ignored += ignored_additions + ignored_deletions;
}
changes -= ignored
Copilot is powered by AI and may make mistakes. Always verify output.
@sonarqubecloud
Copy link

@cap-ang cap-ang closed this Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant