WCAG (Web Content Accessibility Guidelines): International standards
for making web content accessible to people with disabilities.
Four Principles (POUR):
Perceivable: Users must be able to perceive information
Example: Alt text for images, captions for videos
Operable: Users must be able to operate UI
Example: Keyboard navigation, sufficient time to complete tasks
Understandable: Information and operation must be clear
Example: Clear instructions, consistent navigation
Robust: Content works with assistive technologies
Example: Semantic HTML, ARIA labels
Implementing Accessibility
Submit
Color Contrast & Visual Design
WCAG Requirement: Text must have sufficient contrast ratio with background.
✗ Poor Contrast:
Light grey text on light background (ratio: 1.4:1) - FAILS
✓ Good Contrast:
Black text on white background (ratio: 21:1) - PASSES
WCAG 2.1 Requirements:
Level AA: 4.5:1 for normal text, 3:1 for large text
Level AAA: 7:1 for normal text, 4.5:1 for large text
Tool: Use WebAIM Contrast Checker to test your colors
Ethical Considerations for AI/ML Projects
Key Concerns:
Fairness: Ensure fair treatment across demographics
Example: Credit scoring shouldn't discriminate by protected characteristics
Transparency: Users should understand how decisions are made
Example: Explain why loan application was rejected
Privacy: Training data may contain sensitive information
Example: Anonymize data, don't memorize personal details
Action: Check training data for biases, test model fairness across groups,
document model limitations.
Environmental Impact of Software
Digital Carbon Footprint: Software consumes energy through servers,
data centers, and user devices.
Considerations:
Efficient Code: Optimize algorithms to reduce compute time
Data Storage: Don't hoard unnecessary data
Image/Video: Compress media files appropriately
Cloud Providers: Choose providers using renewable energy
Unnecessary Features: Every feature has environmental cost
Project Ethical Checklist
Ask Your Team:
✓ Do we collect only necessary data?
✓ Is personal data secured (hashed passwords, encrypted connections)?
✓ Can users delete their data?
✓ Do we have a privacy policy (even simple one)?
✓ Is our UI accessible (alt text, keyboard navigation, contrast)?
✓ Do we validate all user inputs (prevent injection attacks)?
✓ Are errors handled gracefully (don't leak system info)?
✓ If using ML, have we checked for bias in training data?
✓ Do we have proper authorization (users can't access others' data)?
✓ Are we transparent about how the system works?
Task 1: Conduct Ethical Audit of Project
Instructions (Work in your project teams):
Review Your Project (10 min):
What data do you collect?
How is it stored and secured?
Who can access what?
Identify Issues (15 min): Use the ethical checklist
Security issues (plain text passwords, no input validation)
Privacy issues (collecting unnecessary data, no delete option)
Accessibility issues (missing alt text, poor contrast, no keyboard nav)
Fairness/bias issues (if using ML/automation)
Prioritize Fixes (10 min):
Critical (security vulnerabilities)
Important (GDPR violations, major accessibility issues)
Nice-to-have (minor improvements)
Document Findings (10 min):
Create docs/ethical-audit.md
List issues found and proposed fixes
Time: 45 minutes
Deliverable: Ethical audit document with prioritized issues
Break Time
15 Minutes
Take a break. Next: Implementing ethical fixes!
Part B: Ethical Fix Sprint
Part B: Implementing Ethical Improvements
Theory → Practice! Now you'll implement concrete ethical improvements to your project.
Today's Goal:
Fix at least 2-3 ethical issues from your audit
Focus on high-priority items (security, privacy, accessibility)
Document what you changed and why
Test improvements work correctly
Implementation: Secure Password Hashing
Issue: Passwords stored in plain text or insecurely hashed
// BAD: Plain text password ❌
const user = {
email: 'Tom@example.com',
password: 'password123' // NEVER DO THIS!
};
// GOOD: Hashed with bcrypt ✓
const bcrypt = require('bcrypt');
async function createUser(email, password) {
const hashedPassword = await bcrypt.hash(password, 10);
const user = {
email,
password: hashedPassword // Stored as hash
};
return db.insert('users', user);
}
async function verifyPassword(plainPassword, hashedPassword) {
return await bcrypt.compare(plainPassword, hashedPassword);
}
Implementation: SQL Injection Prevention
Issue: User input directly concatenated into SQL queries
// BAD: SQL Injection vulnerable ❌
app.get('/user', (req, res) => {
const userId = req.query.id;
const query = `SELECT * FROM users WHERE id = ${userId}`;
// Attacker could send: id=1 OR 1=1 (returns all users!)
db.query(query, (err, result) => res.json(result));
});
// GOOD: Parameterized query ✓
app.get('/user', (req, res) => {
const userId = req.query.id;
const query = 'SELECT * FROM users WHERE id = $1';
db.query(query, [userId], (err, result) => {
if (err) return res.status(500).json({ error: 'Server error' });
res.json(result);
});
});
Implementation: User Data Deletion
Requirement: Users must be able to delete their data (Right to Erasure)
// Backend: Delete user endpoint
app.delete('/api/user/:id', authenticateUser, async (req, res) => {
const userId = req.params.id;
// Verify user can only delete their own account
if (req.user.id !== userId) {
return res.status(403).json({ error: 'Unauthorized' });
}
try {
// Delete user and all associated data
await db.query('DELETE FROM orders WHERE user_id = $1', [userId]);
await db.query('DELETE FROM user_data WHERE user_id = $1', [userId]);
await db.query('DELETE FROM users WHERE id = $1', [userId]);
res.json({ message: 'Account deleted successfully' });
} catch (err) {
res.status(500).json({ error: 'Deletion failed' });
}
});
Implementation: Accessibility Fixes
Submit
We'll never share your email
Implementation: Authorization Checks
Issue: Users can access/modify other users' data
// BAD: No authorization check ❌
app.get('/api/order/:orderId', async (req, res) => {
const order = await db.query(
'SELECT * FROM orders WHERE id = $1',
[req.params.orderId]
);
res.json(order); // Any user can view any order!
});
// GOOD: Verify ownership ✓
app.get('/api/order/:orderId', authenticateUser, async (req, res) => {
const order = await db.query(
'SELECT * FROM orders WHERE id = $1 AND user_id = $2',
[req.params.orderId, req.user.id]
);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
res.json(order);
});
Implementation: Environment Variables
Issue: API keys and secrets hardcoded in source code
// BAD: Hardcoded secrets ❌
const db = new Database({
host: 'localhost',
password: 'mySecretPassword123' // Committed to Git!
});
const apiKey = 'sk_live_abc123xyz'; // Exposed in code!
// GOOD: Environment variables ✓
// .env file (NOT committed to Git)
DB_HOST=localhost
DB_PASSWORD=mySecretPassword123
API_KEY=sk_live_abc123xyz
// .gitignore (ensure .env is ignored)
.env
.env.local
// Application code
require('dotenv').config();
const db = new Database({
host: process.env.DB_HOST,
password: process.env.DB_PASSWORD
});
const apiKey = process.env.API_KEY;
Creating a Simple Privacy Policy
GDPR Requirement: Inform users what data you collect and why
Minimum Privacy Policy Sections:
What data we collect: e.g., "Name, email, password (hashed)"
Why we collect it: e.g., "To provide account functionality"
How we use it: e.g., "Send login notifications"
How we store it: e.g., "Encrypted PostgreSQL database"
Your rights: e.g., "You can delete your account anytime"
Contact: How to reach you with questions
Tip: Create docs/privacy-policy.md and link from your app footer
Testing Your Ethical Improvements
Verification Checklist:
Security:
Try SQL injection attacks (in safe test environment)
Verify passwords are hashed in database
Test authorization (can User A access User B's data?)
Accessibility:
Navigate site using only keyboard (Tab, Enter)
Use screen reader (NVDA, VoiceOver)
Check color contrast with WebAIM tool
GDPR:
Create account, delete it, verify data removed from DB
Check privacy policy is accessible
Task 2: Implement Ethical Improvements
Instructions (Work in your project teams):
Select Fixes (5 min):
Choose 2-3 high-priority issues from your audit
Ensure achievable in session
Assign Tasks (5 min):
Divide fixes among team members
Create Git branches
Implement Fixes (30 min):
Write code for your assigned fix
Test that it works
Commit with clear message (e.g., "security: hash passwords with bcrypt")
Document Changes (5 min):
Update docs/ethical-audit.md with "Fixed" status
Add comments in code explaining ethical considerations
Time: 45 minutes
Deliverable: Implemented and tested ethical improvements
Lecture 6 Summary
Software developers have ethical responsibilities to society
BCS Code of Conduct provides professional ethical framework
GDPR protects user data and privacy rights
WCAG standards ensure web accessibility for all users
Security basics: hash passwords, validate inputs, use HTTPS