feat: Modernize project with Vite and modular structure#846
feat: Modernize project with Vite and modular structure#846google-labs-jules[bot] wants to merge 3 commits intodevfrom
Conversation
This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler. - **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing. - **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure. - **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic. - **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`. - **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases. - **Cleanup:** Removed old, unused, and garbage files.
This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler. - **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing. - **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure. - **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic. - **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`. - **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases. - **Cleanup:** Removed old, unused, and garbage files. **CI Fix:** - Restored `Update.json` which was deleted during refactoring but is required by the `UpdateVersion` CI job. - Updated `Update/UpdateVersion.js` to look for the built userscript in the `dist` directory. - Added a build step to the `UpdateVersion.yml` workflow to ensure the userscript is built before the versioning script is run.
| } | ||
| console.log("Submitting problem " + PID); | ||
| Submitted = true; | ||
| AutoCheatButton.innerHTML = "正在提交 " + PID; |
Check warning
Code scanning / CodeQL
DOM text reinterpreted as HTML Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
General Approach:
- Do not pass potentially attacker-controlled or unsanitized DOM text directly into
.innerHTML. - Instead, either (a) set safe text using the
.innerTextor.textContentproperty, or (b) escape any special HTML characters before assigning to.innerHTML.
Detailed Best Fix:
- On line 189, change the assignment from
AutoCheatButton.innerHTML = "正在提交 " + PID;to usingAutoCheatButton.innerText = "正在提交 " + PID;.- This completely avoids HTML interpretation, so even if
PIDcontains malicious code or markup, it is printed as plain text. - Existing functionality (displaying the loading message) is preserved.
- This completely avoids HTML interpretation, so even if
File/Lines to Change:
- Only one line needs to be changed: in
src/pages/contest.js, update line 189.
Implementation Needs:
- No new imports or extra functions are required, just change
.innerHTMLto.innerText.
| @@ -186,7 +186,7 @@ | ||
| } | ||
| console.log("Submitting problem " + PID); | ||
| Submitted = true; | ||
| AutoCheatButton.innerHTML = "正在提交 " + PID; | ||
| AutoCheatButton.innerText = "正在提交 " + PID; | ||
| let SID = 0; | ||
| await fetch("https://www.xmoj.tech/status.php?problem_id=" + PID + "&jresult=4") | ||
| .then((Result) => { |
| } | ||
| } | ||
| if (document.getElementById(ID) !== null) { | ||
| document.getElementById(ID).innerHTML = HTMLData; |
Check failure
Code scanning / CodeQL
Client-side cross-site scripting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
To fix this DOM-based XSS vulnerability, all direct insertions of untrusted Username data into HTML markup should be properly escaped or replaced with safe alternatives. When concatenating user data (such as Username) into HTML attribute values (e.g., within <a href=...>), the value must be HTML-escaped to prevent breaking out of attributes or tags. Similarly, any use of user data within inline CSS or within badge contents should also be encoded/sanitized if not controlled.
Specifically, within GetUsernameHTML in src/utils.js, we should:
- Use the provided
escapeHTMLfunction to encodeUsernamebefore inserting it into thehrefattribute and elsewhere in the markup string. - Optionally, also encode other possibly user-controllable strings (such as colors in
<span style>, although if these are only from trusted badge data this may not be necessary). - Replace all
${Username}interpolations within markup strings with${escapeHTML(Username)}.
No new dependencies are needed, as the existing escapeHTML implementation suffices.
| @@ -204,7 +204,7 @@ | ||
| } | ||
| HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`; | ||
| } | ||
| HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 ` | ||
| HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 ` | ||
| if (UtilityEnabled("Rating")) { | ||
| let Rating = UserInfo.Rating; | ||
| // if(AdminUserList.includes(Username)){ |
| } | ||
| } | ||
| if (document.getElementById(ID) !== null) { | ||
| document.getElementById(ID).innerHTML = HTMLData; |
Check warning
Code scanning / CodeQL
DOM text reinterpreted as HTML Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 7 months ago
To address the vulnerability, we need to ensure untrusted input (Username) is properly escaped before inclusion as HTML. The best fix is to apply the escapeHTML utility function to Username whenever it is interpolated into HTML markup destined for innerHTML. Specifically, in GetUsernameHTML, this affects the anchor href attribute and elsewhere Username is embedded directly in markup. Since attribute contexts (href) should not be vulnerable to tag-breaking if properly escaped (with escapeHTML), the fix will replace e.g. ${Username} in any HTML string construction for innerHTML with ${escapeHTML(Username)}.
Required changes:
- Update
GetUsernameHTMLinsrc/utils.js. - Use
escapeHTMLfor all interpolations ofUsernameinside HTML assigned viainnerHTML. - Ensure the fix does not alter usages where data is added as a text node (already safe).
Method/imports needed:
No imports required—escapeHTML is already defined in the same file.
| @@ -204,7 +204,7 @@ | ||
| } | ||
| HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`; | ||
| } | ||
| HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 ` | ||
| HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 ` | ||
| if (UtilityEnabled("Rating")) { | ||
| let Rating = UserInfo.Rating; | ||
| // if(AdminUserList.includes(Username)){ | ||
| @@ -230,7 +230,7 @@ | ||
| } | ||
| let BadgeInfo = await GetUserBadge(Username); | ||
| if (BadgeInfo.Content != "") { | ||
| HTMLData += `<span class="badge ms-2" style="background-color: ${BadgeInfo.BackgroundColor}; color: ${BadgeInfo.Color}">${BadgeInfo.Content}</span>`; | ||
| HTMLData += `<span class="badge ms-2" style="background-color: ${escapeHTML(BadgeInfo.BackgroundColor)}; color: ${escapeHTML(BadgeInfo.Color)}">${escapeHTML(BadgeInfo.Content)}</span>`; | ||
| } | ||
| } | ||
| if (document.getElementById(ID) !== null) { |
This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler. - **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing. - **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure. - **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic. - **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`. - **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases. - **Cleanup:** Removed old, unused, and garbage files. **CI Fix:** - Restored `Update.json` with full historical data, which was deleted during refactoring but is required by the `UpdateVersion` CI job. - Updated `Update/UpdateVersion.js` to look for the built userscript in the `dist` directory. - Added a build step to the `UpdateVersion.yml` workflow to ensure the userscript is built before the versioning script is run.
This refactoring modernizes the XMOJ-Script project by introducing Vite as a bundler, modularizing the codebase, and adopting a standard project structure. It also includes updates to the CI/CD workflow and dependency management.