Codecademy Logo

Secure Coding Practices for Angular

Related learning

  • Learn secure coding for Angular applications. Identify and mitigate threats like XSS, IDOR, prototype pollution, and more. Ideal for Angular developers.
    • With Certificate
    • Intermediate.
      1 hour

Mitigating XSS in JavaScript

Cross-Site Scripting (XSS) in JavaScript can be mitigated by:

  • Escaping user input in the HTML output
  • Validating or sanitizing inputs to remove executable content
  • Implementing Content Security Policy (CSP) headers

AngularJS provides the $sanitize service to clean user inputs and prevent dangerous code execution. Using directives like ng-bind instead of ng-bind-html can also help escape content. CSP headers further secure applications by restricting the sources of executable scripts.

The code example shows using AngularJS’s $sanitize service to sanitize user input and implementing a CSP to control which scripts can run, helping to prevent XSS attacks.

<!-- Example of a CSP header in HTML -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trustedsource.com;">
<script>
angular.module('xssApp', ['ngSanitize'])
.controller('xssController', function($scope, $sanitize) {
$scope.$watch('userInput', function(newVal) {
$scope.safeVal = $sanitize(newVal); // Sanitizes user input
});
});
</script>
<!-- HTML using ng-bind to automatically escape content -->
<div ng-bind="safeVal"></div>

Cross-Site Scripting (XSS) in JavaScript

Cross-site scripting (XSS) in JavaScript occurs when unvalidated or unescaped user input is included in the web application’s output. In AngularJS, XSS vulnerabilities can arise through directives like ng-bind, ng-model, and ng-bind-html that bind user input to the DOM. If user input is not properly sanitized, malicious scripts can be injected and executed. These vulnerabilities often exploit sink points, such as innerHTML and AngularJS expressions, making client-side code susceptible to attack.

<!-- Vulnerable to XSS: Using ng-model and ng-bind-html -->
<input type="text" ng-model="userInput">
<div ng-bind-html="userInput"></div>
<!-- If a user enters <script>alert('XSS!');</script>, it will execute -->

Insecure NPM Packages Vulnerability

Node.js vulnerabilities often arise when server-side code or third-party NPM packages are used with known vulnerabilities, are misconfigured, or lack proper security practices. Insecure NPM packages can expose applications to attacks through transitive dependencies. Even if a top-level package seems secure, vulnerabilities in its dependencies can compromise security.

These vulnerabilities can manifest in any application that uses Node.js in the back end, even if they use a front-end framework like Angular, React, etc.

Mitigating Insecure NPM Packages Vulnerability

Node.js vulnerabilities can be mitigated by keeping the runtime and all dependencies up to date with the latest security patches. Static analysis tools like Snyk, Retire.js, and npm audit can help identify known vulnerabilities in packages.

Additionally, following best package management practices such as:

  • Locking dependencies to specific versions
  • Removing unused packages
  • Regularly reviewing the dependency tree

can reduce risks by ensuring that applications are not exposed to security flaws and inconsistencies.

Insecure Direct Object References in JavaScript

Insecure Direct Object References (IDOR) in JavaScript occur when an application provides direct access to objects without proper authorization checks. This vulnerability allows users to manipulate references and access unauthorized data, leading to privacy breaches and data manipulation. If backend endpoints rely solely on user input to retrieve objects, attackers can exploit these vulnerabilities by modifying request parameters to access other users’ sensitive information.

The code snippet demonstrates how both frontend and backend code can be vulnerable to IDOR by directly accessing user details based on unvalidated user input (userId).

// AngularJS example vulnerable to IDOR
$scope.getUserDetails = function(userId) {
$http.get('/api/user/' + userId).then(function(response) {
console.log(response.data);
});
};
// Express backend endpoint in Node.js Application
app.get('/api/user/:id', (req, res) => {
const userId = req.params.id;
// No authorization check, vulnerable to IDOR
db.getUserById(userId, (err, user) => {
res.json(user);
});
});

Mitigating Insecure Direct Object References (IDOR) in JavaScript

Insecure Direct Object References (IDOR) can be mitigated by adopting the following key strategies that help safeguard sensitive data and ensure robust protection in JavaScript applications:

  • Secure API Design: Avoid exposing direct references to database keys or internal identifiers. Use indirect reference maps or tokens that are validated server-side to obscure sensitive information from the client, ensuring only authorized users can access specific resources.
  • Access Control Mechanisms: Implement robust access control checks to verify a user’s identity and permissions. Use role-based access control (RBAC) or attribute-based access control (ABAC) to restrict access based on user roles or attributes, preventing unauthorized access to sensitive data.
  • Regular Penetration Testing: Conduct regular penetration testing to simulate attacks and identify potential IDOR vulnerabilities. This proactive approach helps discover security weaknesses and allows for timely corrective measures to maintain a strong security posture.

The code snippet mitigates IDOR vulnerabilities by implementing access control checks to ensure that only authorized users can access specific resources.

// Example of access control check in Node.js Express Application
app.get('/api/user/:id', (req, res) => {
const userId = req.params.id;
const authenticatedUserId = req.user.id;
// Check if the user is authorized to access the requested resource
if (userId !== authenticatedUserId) {
return res.status(403).json({ error: 'Access denied' });
}
// Fetch and return user details
db.getUserById(userId, (err, user) => {
res.json(user);
});
});

Prototype Pollution in JavaScript

Prototype pollution in JavaScript occurs when an attacker can modify an object’s prototype properties, affecting all objects that inherit from that prototype.

This happens because almost all objects in JavaScript are instances of Object and share the same prototype. If an attacker modifies the prototype, changes can propagate widely, impacting object behavior across the application.

This pollution can lead to:

  • Denial of service (DoS)
  • Data corruption
  • Remote code execution

The code snippet demonstrates how prototype pollution can occur by modifying the __proto__ property, affecting all objects that inherit from the modified prototype.

// Example of prototype pollution
const obj = {};
obj.__proto__.polluted = 'yes';
const newObj = {};
console.log(newObj.polluted); // Output: 'yes'
// Example in AngularJS using Object.assign with unsanitized input
angular.module('pollutedApp', [])
.controller('PollutedController', function($scope) {
const data = {};
Object.assign(data, JSON.parse('{"__proto__": {"polluted": "yes"}}'));
console.log({}.polluted); // Output: 'yes'
});

Mitigating Prototype Pollution in JavaScript

Prototype pollution in JavaScript can be mitigated by:

  • Validating and sanitizing input to prevent attackers from modifying object prototypes.
  • Avoiding insecure libraries and functions that manipulate object prototypes directly like __proto__.
  • Using libraries that are protected against prototype pollution and follow best practices.

By sanitizing inputs and avoiding dangerous keys, like __proto__, developers can prevent unauthorized modifications to the prototype chain and secure their applications.

The code snippet sanitizes user input to remove the __proto__ property, preventing prototype pollution and securing the application against unauthorized modifications to the prototype chain.

// Function to sanitize input and prevent prototype pollution
function sanitizeInput(input) {
if (input.hasOwnProperty('__proto__')) {
delete input.__proto__;
}
return input;
}
// Usage example with sanitized input
let safeInput = sanitizeInput(JSON.parse('{"__proto__": {"polluted": "yes"}}'));
console.log(safeInput); // Output: {}

Learn more on Codecademy

  • Learn secure coding for Angular applications. Identify and mitigate threats like XSS, IDOR, prototype pollution, and more. Ideal for Angular developers.
    • With Certificate
    • Intermediate.
      1 hour