Security
CSP Compliance
Jspreadsheet and its extensions can run under a Content Security Policy (CSP) without requiring unsafe-inline
or unsafe-eval
.
Two main points help ensure compliance:
- Formula Pro – provides the recommended formula engine, avoiding inline execution.
- Nonce support – Jspreadsheet accepts a
nonce
property so dynamic styles (e.g., conditional formatting) are CSP-compliant.
Example: basic CSP + CDN
<head>
<meta charset="utf-8">
<!-- Content Security Policy (example) -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
object-src 'none';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net 'nonce-704a9427-e2f5-41e1-ba92-f99256b9638d';
font-src https://fonts.gstatic.com;
img-src 'self' data:;">
<title>Jspreadsheet</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/jspreadsheet.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/jsuites.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/studio/dist/style.min.css" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jsuites@5/dist/jsuites.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/[email protected]/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/validations/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@jspreadsheet/formula-pro@5/dist/index.min.js"></script>
</head>
<body>
<div id="root"></div>
<script src="./csp.js"></script>
</body>
JavaScript
// Set your JSS license key (The following key only works for one day)
jspreadsheet.setLicense('MzliNGNjZjFjM2MwNzA3Njk3OTMyZGJjMzY3MzJlZGI2MGUwM2MzYmY2NzhmMzYzZjgwNmIwNGNkOGMzMmRmZjFkNTEwMGI2ZGJlNzQzZTVlM2Q3NDBhY2EzNzU5MzhhZDdjYjNjZDliZTQ4ZTQ0Y2U1NDUwZTAwNWNjNGZkMzUsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVM05qY3dOemM0TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');
// Load the extensions
jspreadsheet.setExtensions({ validations, formula });
jspreadsheet(document.getElementById('root'), {
nonce: '704a9427-e2f5-41e1-ba92-f99256b9638d',
toolbar: true,
tabs: true,
worksheets: [{
data: [
[10,"=A1*2"],
[20,"=A2*2"],
[30,"=A3*2"],
],
minDimensions: [6, 6],
}],
validations: [{
range: 'Sheet1!A1:A3',
action: "warning",
criteria: "between",
type: "number",
value: [10, 30],
}]
});
Best Practices
When working with CSP and Jspreadsheet:
- Always generate a random, cryptographically strong nonce for each request, never reuse or hard-code it.
- Keep your CSP policy minimal and only allow trusted sources (e.g., your own domain + required CDNs).
- Avoid adding
unsafe-inline
orunsafe-eval
as quick fixes — use thenonce
property instead. - Pin specific versions of external libraries to prevent unexpected changes.
Contact
If you find a feature that does not follow CSP best practices, please report it. Security-related contacts are always prioritized.