Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 16449e75a2 | |||
| d82000ab7f | |||
| 2b092592cb | |||
| 116b04ddc1 |
+14
-14
@@ -27,9 +27,9 @@ jobs:
|
|||||||
name: Ruff Lint & Format
|
name: Ruff Lint & Format
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -48,9 +48,9 @@ jobs:
|
|||||||
name: Alembic Migration Chain Check
|
name: Alembic Migration Chain Check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
- name: Validate migration chain
|
- name: Validate migration chain
|
||||||
@@ -60,9 +60,9 @@ jobs:
|
|||||||
name: HTML Accessibility Lint
|
name: HTML Accessibility Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -78,9 +78,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [lint]
|
needs: [lint]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -93,9 +93,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [lint]
|
needs: [lint]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -116,10 +116,10 @@ jobs:
|
|||||||
ports: ["5672:5672", "15672:15672"]
|
ports: ["5672:5672", "15672:15672"]
|
||||||
options: --health-cmd "rabbitmq-diagnostics -q ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
options: --health-cmd "rabbitmq-diagnostics -q ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -154,7 +154,7 @@ jobs:
|
|||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
- name: Generate Build Metadata
|
- name: Generate Build Metadata
|
||||||
run: |
|
run: |
|
||||||
chmod +x scripts/generate_build_metadata.sh
|
chmod +x scripts/generate_build_metadata.sh
|
||||||
@@ -212,7 +212,7 @@ jobs:
|
|||||||
echo "tag=main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
|
echo "tag=main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
|
||||||
echo "image=ghcr.io/${{ github.repository_owner }}/docuelevate:main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
|
echo "image=ghcr.io/${{ github.repository_owner }}/docuelevate:main-${SHORT_SHA}" >> "$GITHUB_OUTPUT"
|
||||||
- name: Checkout k8s-cluster-state
|
- name: Checkout k8s-cluster-state
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
repository: christianlouis/k8s-cluster-state
|
repository: christianlouis/k8s-cluster-state
|
||||||
token: ${{ secrets.GH_PAT }}
|
token: ${{ secrets.GH_PAT }}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
build-mode: none
|
build-mode: none
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v4
|
uses: github/codeql-action/init@v4
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.11'
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout PR branch
|
- name: Checkout PR branch
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.head_ref }}
|
ref: ${{ github.head_ref }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5.4.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.11"
|
python-version: "3.11"
|
||||||
|
|
||||||
|
|||||||
@@ -28,3 +28,7 @@
|
|||||||
**Vulnerability:** The `/process-url` endpoint used `httpx.AsyncClient(follow_redirects=True)` after validating the initial user-provided URL against SSRF protections. However, it did not validate the target URLs of any subsequent HTTP redirects, allowing an attacker to provide a safe URL that redirects to an internal/private IP, bypassing the security check.
|
**Vulnerability:** The `/process-url` endpoint used `httpx.AsyncClient(follow_redirects=True)` after validating the initial user-provided URL against SSRF protections. However, it did not validate the target URLs of any subsequent HTTP redirects, allowing an attacker to provide a safe URL that redirects to an internal/private IP, bypassing the security check.
|
||||||
**Learning:** Initial URL validation is insufficient when the HTTP client is configured to follow redirects automatically. The client must be explicitly configured to validate every redirect target.
|
**Learning:** Initial URL validation is insufficient when the HTTP client is configured to follow redirects automatically. The client must be explicitly configured to validate every redirect target.
|
||||||
**Prevention:** When using `httpx.AsyncClient(follow_redirects=True)` for user-provided URLs, always implement a redirect validator hook function (e.g., using `event_hooks={'response': [validate_redirect]}`) that resolves the `Location` header and passes it through the same SSRF validation logic before the redirect is followed.
|
**Prevention:** When using `httpx.AsyncClient(follow_redirects=True)` for user-provided URLs, always implement a redirect validator hook function (e.g., using `event_hooks={'response': [validate_redirect]}`) that resolves the `Location` header and passes it through the same SSRF validation logic before the redirect is followed.
|
||||||
|
## 2026-05-27 - DOM-based XSS in upload.js
|
||||||
|
**Vulnerability:** The `upload.js` frontend file directly injected the user-controlled `file.name` into a string literal passed to `row.innerHTML`. This allowed a malicious filename (e.g., `<img src=x onerror=alert(1)>`) to execute arbitrary JavaScript in the victim's browser context (DOM-based XSS).
|
||||||
|
**Learning:** Even internal or local files uploaded by a user can contain malicious filenames. Any data dynamically interpolated into an HTML string that is subsequently rendered via `innerHTML` must be strictly sanitized.
|
||||||
|
**Prevention:** Implement and apply an HTML escaping function (e.g., `_escapeHtml`) to replace dangerous characters (`&`, `<`, `>`, `"`, `'`) with their corresponding HTML entities before injecting user-controlled data into the DOM.
|
||||||
|
|||||||
@@ -293,13 +293,25 @@ function processFiles(files, progressContainer, statusMessage) {
|
|||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _escapeHtml(unsafe) {
|
||||||
|
if (!unsafe) return '';
|
||||||
|
return String(unsafe)
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
// Pre-create one progress row per file.
|
// Pre-create one progress row per file.
|
||||||
const queueItems = fileArray.map((file) => {
|
const queueItems = fileArray.map((file) => {
|
||||||
const row = document.createElement('div');
|
const row = document.createElement('div');
|
||||||
row.className = 'flex flex-col mb-2';
|
row.className = 'flex flex-col mb-2';
|
||||||
|
const safeFileName = _escapeHtml(file.name);
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-sm truncate" title="${file.name}">${file.name}</span>
|
<span class="text-sm truncate" title="${safeFileName}">${safeFileName}</span>
|
||||||
<span class="text-xs text-gray-500">${formatFileSize(file.size)}</span>
|
<span class="text-xs text-gray-500">${formatFileSize(file.size)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full bg-gray-200 h-2 rounded-full mt-1">
|
<div class="w-full bg-gray-200 h-2 rounded-full mt-1">
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
fastapi[all] # Web framework with all extras
|
fastapi[all]!=0.136.3 # Web framework with all extras
|
||||||
uvicorn # ASGI server
|
uvicorn # ASGI server
|
||||||
celery # Task queue
|
celery # Task queue
|
||||||
redis # Message broker for Celery
|
redis # Message broker for Celery
|
||||||
|
|||||||
Reference in New Issue
Block a user