Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 11 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:0-3.11",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "latest"
},
"ghcr.io/devcontainers/features/python:1": {},
"ghcr.io/devcontainers-extra/features/black:2": {},
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/azure-cli:1": {
"installBicep": true,
"installUsingPython": true,
"version": "2.72.0",
"bicepVersion": "latest"
},
"ghcr.io/devcontainers/features/terraform:1": {},
"ghcr.io/devcontainers/features/powershell:1": {}
"ghcr.io/devcontainers-extra/features/black:2": {}
"ghcr.io/devcontainers/features/powershell:1": {},
"ghcr.io/azure/azure-dev/azd:latest": {}
},
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
Expand Down
4 changes: 4 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
applyTo: '**'
---

# REPO SPECIFIC INSTRUCTIONS

---
Expand Down
13 changes: 13 additions & 0 deletions .github/instructions/python-lang.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
applyTo: '**'
---

# Python Language Guide

- Files should start with a comment of the file name. Ex: `# functions_personal_agents.py`

- Imports should be grouped at the top of the document after the module docstring, unless otherwise indicated by the user or for performance reasons in which case the import should be as close as possible to the usage with a documented note as to why the import is not at the top of the file.

- Use 4 spaces per indentation level. No tabs.

- Code and definitions should occur after the imports block.
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
applyTo: '**'
---

# Security: Sanitize Settings for Frontend Routes

## Critical Security Requirement

**NEVER send raw settings or configuration data directly to the frontend without sanitization.**

## Rule: Always Sanitize Settings Before Sending to Browser

When building or working with Python frontend routes (Flask routes that render templates or return JSON to the browser), **ALL settings data MUST be sanitized** before being sent to prevent exposure of:
- API keys
- Connection strings
- Secrets and passwords
- Internal configuration details
- Database credentials
- Any other sensitive information

## Required Pattern

### ✅ CORRECT - Sanitize Before Sending
```python
from functions_settings import get_settings, sanitize_settings_for_user

@app.route('/some-page')
def some_page():
# Get raw settings
settings = get_settings()

# Sanitize before sending to frontend
public_settings = sanitize_settings_for_user(settings)

# Use sanitized settings in template
return render_template('some_page.html',
app_settings=public_settings,
settings=public_settings)
```

### ❌ INCORRECT - Never Send Raw Settings
```python
# DANGEROUS - Exposes secrets to browser!
@app.route('/some-page')
def some_page():
settings = get_settings()
return render_template('some_page.html',
app_settings=settings) # ❌ NEVER DO THIS
```

## When This Rule Applies

Apply this rule for:
- **Any route** that renders an HTML template (`render_template()`)
- **Any API endpoint** that returns JSON data containing settings (`jsonify()`)
- **Any frontend route** that passes configuration data to JavaScript
- **Dashboard/admin pages** that display configuration information
- **Settings/configuration pages** where users view system settings

## Implementation Checklist

When creating or modifying frontend routes:
1. ✅ Import `sanitize_settings_for_user` from `functions_settings`
2. ✅ Call `get_settings()` to retrieve raw settings
3. ✅ Call `sanitize_settings_for_user(settings)` to create safe version
4. ✅ Pass only the sanitized version to `render_template()` or `jsonify()`
5. ✅ Verify no raw settings objects bypass sanitization

## Examples from Codebase

### Control Center Route
```python
from functions_settings import get_settings, sanitize_settings_for_user

@app.route('/admin/control-center', methods=['GET'])
@login_required
@admin_required
def control_center():
# Get settings for configuration data
settings = get_settings()
public_settings = sanitize_settings_for_user(settings)

# Get statistics
stats = get_control_center_statistics()

# Send only sanitized settings to frontend
return render_template('control_center.html',
app_settings=public_settings,
settings=public_settings,
statistics=stats)
```

### API Endpoint Pattern
```python
@app.route('/api/get-config', methods=['GET'])
@login_required
def get_config():
settings = get_settings()
public_settings = sanitize_settings_for_user(settings)

return jsonify({
'success': True,
'config': public_settings
})
```

## What Gets Sanitized

The `sanitize_settings_for_user()` function removes or masks:
- Azure OpenAI API keys
- Cosmos DB connection strings
- Azure Search admin keys
- Document Intelligence keys
- Authentication secrets
- Internal endpoint URLs
- Database credentials
- Any field containing 'key', 'secret', 'password', 'connection', etc.

## Security Impact

**Failure to sanitize settings can result in:**
- 🚨 Exposure of API keys in browser DevTools/Network tab
- 🚨 Secrets visible in HTML source code
- 🚨 Credentials leaked in JavaScript variables
- 🚨 Potential unauthorized access to Azure resources
- 🚨 Security vulnerabilities and data breaches

## Code Review Checklist

When reviewing code, verify:
- [ ] No `get_settings()` result is sent directly to frontend
- [ ] `sanitize_settings_for_user()` is called before rendering
- [ ] Template variables receiving settings use sanitized version
- [ ] API responses containing config use sanitized data
- [ ] No raw config objects in `render_template()` or `jsonify()` calls

## Related Functions

- `get_settings()` - Returns raw settings (DO NOT send to frontend)
- `sanitize_settings_for_user(settings)` - Returns safe settings (OK to send to frontend)
- Location: `functions_settings.py`
10 changes: 0 additions & 10 deletions .github/workflows/docker_image_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,6 @@ jobs:
login-server: ${{ secrets.ACR_LOGIN_SERVER }}

- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Ajv
run: npm install ajv@^8.0.0 ajv-cli@^5.0.0
- name: Install Ajv
run: npm install ajv@^8.0.0 ajv-formats
- name: Generate standalone JSON schema validators
run: node scripts/generate-validators.mjs
- name: Build the Docker image
run:
docker build . --file application/single_app/Dockerfile --tag ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat:$(date +'%Y-%m-%d')_$GITHUB_RUN_NUMBER;
Expand Down
8 changes: 0 additions & 8 deletions .github/workflows/docker_image_publish_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ jobs:
login-server: ${{ secrets.ACR_LOGIN_SERVER }}

- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Ajv
run: npm install ajv@^8.0.0 ajv-formats
- name: Generate standalone JSON schema validators
run: node scripts/generate-validators.mjs
- name: Build the Docker image
run:
docker build . --file application/single_app/Dockerfile --tag ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:$(date +'%Y-%m-%d')_$GITHUB_RUN_NUMBER;
Expand Down
38 changes: 22 additions & 16 deletions .github/workflows/docker_image_publish_nadoyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
push:
branches:
- nadoyle
- feature/group-agents-actions
- security/containerBuild
- feature/aifoundryagents
- azureBillingPlugin

workflow_dispatch:

Expand All @@ -19,24 +23,26 @@ jobs:
uses: Azure/docker-login@v2
with:
# Container registry username
username: ${{ secrets.ACR_USERNAME }}
username: ${{ secrets.ACR_USERNAME_NADOYLE }}
# Container registry password
password: ${{ secrets.ACR_PASSWORD }}
password: ${{ secrets.ACR_PASSWORD_NADOYLE }}
# Container registry server url
login-server: ${{ secrets.ACR_LOGIN_SERVER }}

login-server: ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}

- name: Normalize branch name for tag
run: |
REF="${GITHUB_REF_NAME}"
SAFE=$(echo "$REF" \
| tr '[:upper:]' '[:lower:]' \
| sed 's#[^a-z0-9._-]#-#g' \
| sed 's/^-*//;s/-*$//' \
| cut -c1-128)
echo "BRANCH_TAG=$SAFE" >> "$GITHUB_ENV"

- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Ajv
run: npm install ajv@^8.0.0 ajv-formats
- name: Generate standalone JSON schema validators
run: node scripts/generate-validators.mjs
- name: Build the Docker image
run:
docker build . --file application/single_app/Dockerfile --tag ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:$(date +'%Y-%m-%d')_$GITHUB_RUN_NUMBER;
docker tag ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:$(date +'%Y-%m-%d')_$GITHUB_RUN_NUMBER ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:latest;
docker push ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:$(date +'%Y-%m-%d')_$GITHUB_RUN_NUMBER;
docker push ${{ secrets.ACR_LOGIN_SERVER }}/simple-chat-dev:latest;
docker build . --file application/single_app/Dockerfile --tag ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}/simple-chat-dev:$(date +'%Y-%m-%d')_${BRANCH_TAG}_$GITHUB_RUN_NUMBER;
docker tag ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}/simple-chat-dev:$(date +'%Y-%m-%d')_${BRANCH_TAG}_$GITHUB_RUN_NUMBER ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}/simple-chat-dev:latest;
docker push ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}/simple-chat-dev:$(date +'%Y-%m-%d')_${BRANCH_TAG}_$GITHUB_RUN_NUMBER;
docker push ${{ secrets.ACR_LOGIN_SERVER_NADOYLE }}/simple-chat-dev:latest;
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ flask_session
application/single_app/static/.DS_Store
application/external_apps/bulkloader/map.csv

flask_session
flask_session
**/abd_proto.py
**/my_chart.png
**/sample_pie.csv
**/sample_stacked_column.csv
Loading
Loading