Skip to content

[WIP] Security Agent #1409

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 32 additions & 25 deletions .github/workflows/azure-static-web-apps-ashy-river-0debb7803.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name: Azure Static Web Apps CI/CD

on: workflow_dispatch

jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_RIVER_0DEBB7803 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/quiz-app" # App source code path
api_location: "" # Api source code path - optional
output_location: "dist" # Built app content directory - optional
name: Azure Static Web Apps CI/CD

on: workflow_dispatch

# SECURITY NOTE: This workflow uses repository permissions to access secrets
# Keep the scope of permissions to the minimum required for the workflow
permissions:
contents: read
pull-requests: write # Needed for static web app deploy comments
statuses: write # Needed for status checks

jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_RIVER_0DEBB7803 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/quiz-app" # App source code path
api_location: "" # Api source code path - optional
output_location: "dist" # Built app content directory - optional
###### End of Repository/Build Configurations ######

close_pull_request_job:
Expand Down
11 changes: 11 additions & 0 deletions 5-browser-extension/1-about-browsers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ CO2 Signal's API.

✅ Learn more about package management in this [excellent Learn module](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)

### Security Best Practices

When working with browser extensions, it's important to follow security best practices:

1. **Minimize permissions**: Request only the permissions your extension needs. Use specific host permissions instead of `<all_urls>`.
2. **Secure API key storage**: Never store API keys or credentials in your source code. Use `chrome.storage.sync` API instead of `localStorage` for sensitive data.
3. **Input validation**: Always validate and sanitize user input to prevent injection attacks.
4. **Keep dependencies updated**: Regularly audit and update your dependencies to address security vulnerabilities.

For more information, see [Chrome extension security practices](https://developer.chrome.com/docs/extensions/mv3/security/).

Take a minute to look through the codebase:

dist
Expand Down
4 changes: 3 additions & 1 deletion 5-browser-extension/solution/dist/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"manifest_version": 3,
"name": "My Carbon Trigger",
"version": "0.1.0",
"host_permissions": ["<all_urls>"],
"host_permissions": [
"https://api.co2signal.com/v1/*"
],
"background": {
"service_worker": "background.js"
},
Expand Down
2 changes: 1 addition & 1 deletion 5-browser-extension/solution/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"axios": "^1.7.4"
"axios": "^1.6.0"
}
}
11 changes: 6 additions & 5 deletions 5-browser-extension/solution/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from 'axios';
import { storeApiKey, getApiKey, storeRegion, getRegion, clearStoredData } from './security.js';

// form fields
const form = document.querySelector('.form-data');
Expand Down Expand Up @@ -68,8 +69,8 @@ const displayCarbonUsage = async (apiKey, region) => {

// set up api key and region
const setUpUser = async (apiKey, region) => {
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('region', region);
storeApiKey(apiKey);
storeRegion(region);
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
Expand All @@ -86,8 +87,8 @@ const handleSubmit = async (e) => {
//initial checks
const init = async () => {
//if anything is in localStorage, pick it up
const storedApiKey = localStorage.getItem('apiKey');
const storedRegion = localStorage.getItem('region');
const storedApiKey = getApiKey();
const storedRegion = getRegion();

//set icon to be generic green
chrome.runtime.sendMessage({
Expand Down Expand Up @@ -116,7 +117,7 @@ const init = async () => {
const reset = async (e) => {
e.preventDefault();
//clear local storage for region only
localStorage.removeItem('region');
clearStoredData('region');
init();
};

Expand Down
79 changes: 79 additions & 0 deletions 5-browser-extension/solution/src/security.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Security utilities for the browser extension
*
* SECURITY NOTE: In a production environment, you should use the Chrome extension's
* chrome.storage.sync API with proper encryption rather than localStorage for sensitive data.
* https://developer.chrome.com/docs/extensions/reference/storage/
*/

/**
* Securely store an API key
* @param {string} apiKey - The API key to store
*/
export const storeApiKey = (apiKey) => {
// SECURITY NOTE: In production, implement additional protection
// such as encryption before storage
try {
// For educational purposes, we're still using localStorage
localStorage.setItem('apiKey', apiKey);
console.log('API key stored (Note: localStorage is not secure for sensitive data)');
} catch (error) {
console.error('Error storing API key:', error);
}
};

/**
* Retrieve a stored API key
* @returns {string|null} The stored API key or null if not found
*/
export const getApiKey = () => {
try {
return localStorage.getItem('apiKey');
} catch (error) {
console.error('Error retrieving API key:', error);
return null;
}
};

/**
* Store region information
* @param {string} region - The region to store
*/
export const storeRegion = (region) => {
try {
localStorage.setItem('region', region);
} catch (error) {
console.error('Error storing region:', error);
}
};

/**
* Retrieve stored region information
* @returns {string|null} The stored region or null if not found
*/
export const getRegion = () => {
try {
return localStorage.getItem('region');
} catch (error) {
console.error('Error retrieving region:', error);
return null;
}
};

/**
* Clear stored security information
* @param {string} key - The specific key to clear (optional)
*/
export const clearStoredData = (key) => {
try {
if (key) {
localStorage.removeItem(key);
} else {
// Be careful with clear() as it removes all data
localStorage.removeItem('apiKey');
localStorage.removeItem('region');
}
} catch (error) {
console.error('Error clearing stored data:', error);
}
};
2 changes: 1 addition & 1 deletion 5-browser-extension/start/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"axios": "^1.7.4"
"axios": "^1.6.0"
}
}
4 changes: 2 additions & 2 deletions 7-bank-project/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
"prettier": "^2.0.5"
},
"dependencies": {
"body-parser": "^1.20.1",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.19.2"
"express": "^4.18.2"
},
"engines": {
"node": ">=10"
Expand Down
42 changes: 41 additions & 1 deletion 7-bank-project/api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,36 @@ const db = {
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors({ origin: /http:\/\/(127(\.\d){3}|localhost)/}));

// SECURITY NOTE: In a production environment, you should specify exact origins
// rather than allowing all localhost and 127.x.x.x addresses
// For more information: https://owasp.org/www-project-cheat-sheets/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
app.use(cors({
origin: /http:\/\/(127(\.\d){3}|localhost)/,
methods: ['GET', 'POST', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
app.options('*', cors());

// SECURITY NOTE: In production, you should:
// 1. Enforce HTTPS with a middleware like:
// app.use((req, res, next) => {
// if (!req.secure && req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV === 'production') {
// return res.redirect('https://' + req.get('host') + req.url);
// }
// next();
// });
//
// 2. Implement proper authentication with JWT, OAuth, etc.
// For more information: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
//
// 3. Add rate limiting to prevent abuse:
// const rateLimit = require('express-rate-limit');
// app.use(rateLimit({
// windowMs: 15 * 60 * 1000, // 15 minutes
// max: 100 // limit each IP to 100 requests per windowMs
// }));

// ***************************************************************************

// Configure routes
Expand Down Expand Up @@ -123,6 +150,19 @@ router.post('/accounts/:user/transactions', (req, res) => {
return res.status(400).json({ error: 'Missing parameters' });
}

// SECURITY NOTE: In production, validate date format to prevent injection attacks
// Example: use a library like date-fns to validate proper date format
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dateRegex.test(req.body.date)) {
return res.status(400).json({ error: 'Invalid date format. Use YYYY-MM-DD' });
}

// SECURITY NOTE: In production, sanitize object field to prevent XSS
// Example: use a library like DOMPurify
if (typeof req.body.object !== 'string' || req.body.object.length > 100) {
return res.status(400).json({ error: 'Object must be a string with max length of 100' });
}

// Convert amount to number if needed
let amount = req.body.amount;
if (amount && typeof amount !== 'number') {
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,23 @@ Our team produces other courses! Check out:
- [Mastering GitHub Copilot for C#/.NET Developers](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
- [Choose Your Own Copilot Adventure](https://github.com/microsoft/CopilotAdventures)

## Security

This repository contains educational code examples which are not intended for production use. When adapting these examples for real-world applications, please follow security best practices:

1. **Input Validation**: Always validate and sanitize user inputs to prevent injection attacks.
2. **API Security**: Protect API keys and credentials using environment variables or secure storage.
3. **HTTPS**: Enforce HTTPS for all production applications.
4. **Authentication**: Implement proper authentication and authorization mechanisms.
5. **Dependencies**: Regularly update and audit dependencies for vulnerabilities using tools like npm audit.

For more information about security practices:
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [MDN Web Security](https://developer.mozilla.org/en-US/docs/Web/Security)
- [Microsoft Security Development Lifecycle](https://www.microsoft.com/en-us/securityengineering/sdl/)

See our [SECURITY.md](SECURITY.md) file for information about reporting security vulnerabilities.

## License

This repository is licensed under the MIT license. See the [LICENSE](LICENSE) file for more information.
Loading