Browse Source
fix: resolve security vulnerabilities from code scanning (#11641)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
pull/11644/head
afc163
6 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with
61 additions and
8 deletions
-
.github/workflows/deploy.yml
-
.github/workflows/emoji-helper.yml
-
.github/workflows/issue-labeled.yml
-
.github/workflows/issue-open-check.yml
-
.github/workflows/preview-deploy.yml
-
.gitignore
-
mock/listTableList.ts
-
src/pages/user/login/index.tsx
-
src/service-worker.js
|
|
|
@ -5,6 +5,10 @@ on: |
|
|
|
branches: |
|
|
|
- all-blocks |
|
|
|
|
|
|
|
permissions: |
|
|
|
contents: write |
|
|
|
pages: write |
|
|
|
|
|
|
|
jobs: |
|
|
|
build-and-deploy: |
|
|
|
runs-on: ubuntu-latest |
|
|
|
|
|
|
|
@ -4,6 +4,9 @@ on: |
|
|
|
release: |
|
|
|
types: [published] |
|
|
|
|
|
|
|
permissions: |
|
|
|
contents: write |
|
|
|
|
|
|
|
jobs: |
|
|
|
emoji: |
|
|
|
runs-on: ubuntu-latest |
|
|
|
|
|
|
|
@ -4,6 +4,9 @@ on: |
|
|
|
issues: |
|
|
|
types: [labeled] |
|
|
|
|
|
|
|
permissions: |
|
|
|
issues: write |
|
|
|
|
|
|
|
jobs: |
|
|
|
reply-helper: |
|
|
|
runs-on: ubuntu-latest |
|
|
|
|
|
|
|
@ -4,6 +4,9 @@ on: |
|
|
|
issues: |
|
|
|
types: [opened, edited] |
|
|
|
|
|
|
|
permissions: |
|
|
|
issues: write |
|
|
|
|
|
|
|
jobs: |
|
|
|
check-issue: |
|
|
|
runs-on: ubuntu-latest |
|
|
|
|
|
|
|
@ -26,7 +26,14 @@ jobs: |
|
|
|
|
|
|
|
- name: save PR id |
|
|
|
id: pr |
|
|
|
run: echo "::set-output name=id::$(<pr-id.txt)" |
|
|
|
run: | |
|
|
|
PR_ID=$(<pr-id.txt) |
|
|
|
# Validate PR ID is numeric to prevent code injection |
|
|
|
if [[ ! "$PR_ID" =~ ^[0-9]+$ ]]; then |
|
|
|
echo "Invalid PR ID: $PR_ID" |
|
|
|
exit 1 |
|
|
|
fi |
|
|
|
echo "id=$PR_ID" >> "$GITHUB_OUTPUT" |
|
|
|
|
|
|
|
- name: download dist artifact |
|
|
|
uses: dawidd6/action-download-artifact@v6 |
|
|
|
@ -84,7 +91,14 @@ jobs: |
|
|
|
|
|
|
|
- name: save PR id |
|
|
|
id: pr |
|
|
|
run: echo "::set-output name=id::$(<pr-id.txt)" |
|
|
|
run: | |
|
|
|
PR_ID=$(<pr-id.txt) |
|
|
|
# Validate PR ID is numeric to prevent code injection |
|
|
|
if [[ ! "$PR_ID" =~ ^[0-9]+$ ]]; then |
|
|
|
echo "Invalid PR ID: $PR_ID" |
|
|
|
exit 1 |
|
|
|
fi |
|
|
|
echo "id=$PR_ID" >> "$GITHUB_OUTPUT" |
|
|
|
|
|
|
|
- name: The job failed |
|
|
|
uses: actions-cool/maintain-one-comment@v1.2.1 |
|
|
|
|
|
|
|
@ -42,3 +42,6 @@ screenshot |
|
|
|
.firebase |
|
|
|
|
|
|
|
build |
|
|
|
|
|
|
|
# worktrees |
|
|
|
.worktrees |
|
|
|
|
|
|
|
@ -106,11 +106,6 @@ function getRule(req: Request, res: Response, u: string) { |
|
|
|
} |
|
|
|
|
|
|
|
function postRule(req: Request, res: Response, u: string, b: Request) { |
|
|
|
let realUrl = u; |
|
|
|
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { |
|
|
|
realUrl = req.url; |
|
|
|
} |
|
|
|
|
|
|
|
const body = b?.body || req.body; |
|
|
|
const { method, name, desc, key } = body; |
|
|
|
|
|
|
|
|
|
|
|
@ -118,6 +118,27 @@ const Login: React.FC = () => { |
|
|
|
const { message } = App.useApp(); |
|
|
|
const intl = useIntl(); |
|
|
|
|
|
|
|
/** |
|
|
|
* Validate redirect URL to prevent open redirect attacks |
|
|
|
* Only allow same-origin relative paths starting with '/' |
|
|
|
*/ |
|
|
|
const getSafeRedirectUrl = (redirect: string | null): string => { |
|
|
|
if (!redirect || !redirect.startsWith('/')) return '/'; |
|
|
|
|
|
|
|
// Block protocol-relative URLs (//example.com)
|
|
|
|
if (redirect.startsWith('//')) return '/'; |
|
|
|
|
|
|
|
try { |
|
|
|
const parsed = new URL(redirect, window.location.origin); |
|
|
|
// Only allow same-origin URLs
|
|
|
|
if (parsed.origin !== window.location.origin) return '/'; |
|
|
|
// Return the path with query and hash preserved
|
|
|
|
return `${parsed.pathname}${parsed.search}${parsed.hash}`; |
|
|
|
} catch { |
|
|
|
return '/'; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const fetchUserInfo = async () => { |
|
|
|
const userInfo = await initialState?.fetchUserInfo?.(); |
|
|
|
if (userInfo) { |
|
|
|
@ -142,7 +163,8 @@ const Login: React.FC = () => { |
|
|
|
message.success(defaultLoginSuccessMessage); |
|
|
|
await fetchUserInfo(); |
|
|
|
const urlParams = new URL(window.location.href).searchParams; |
|
|
|
window.location.href = urlParams.get('redirect') || '/'; |
|
|
|
const redirectUrl = getSafeRedirectUrl(urlParams.get('redirect')); |
|
|
|
window.location.href = redirectUrl; |
|
|
|
return; |
|
|
|
} |
|
|
|
console.log(msg); |
|
|
|
|
|
|
|
@ -45,6 +45,12 @@ workbox.routing.registerRoute( |
|
|
|
|
|
|
|
/** Response to client after skipping waiting with MessageChannel */ |
|
|
|
addEventListener('message', (event) => { |
|
|
|
// Security: Verify origin to prevent cross-origin attacks
|
|
|
|
// Use self.location.origin for dynamic origin validation (works across all deployment domains)
|
|
|
|
if (event.origin !== self.location.origin) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const replyPort = event.ports[0]; |
|
|
|
const message = event.data; |
|
|
|
if (replyPort && message && message.type === 'skip-waiting') { |
|
|
|
|