Использование CSP /NONCE в Electron App с node.jsJavascript

Форум по Javascript
Ответить Пред. темаСлед. тема
Anonymous
 Использование CSP /NONCE в Electron App с node.js

Сообщение Anonymous »

Я делаю настольное приложение с помощью Electro и node.js, в котором я пытаюсь реализовать csp /nonce.
До сих пор я разработал скрипт, который должен генерировать Политика безопасности контента: < /p>
const crypto = require('crypto');

class SecurityPolicies {
static NONCE_LENGTH = 32;

static CSP_DIRECTIVES = {
'default-src': ["'self'"],
'script-src': ["'self'", "'unsafe-inline'"],
'style-src': ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
'img-src': ["'self'", "data:", "https:", "blob:"],
'font-src': ["'self'", "data:","https://fonts.gstatic.com"],
'object-src': ["'none'"],
'base-uri': ["'self'"],
'form-action': ["'self'"],
'frame-ancestors': ["'none'"],
'connect-src': ["'self'","ws:", "wss:"],
'media-src': ["'self'", "blob:"],
'worker-src': ["'self'", "blob:"],
'manifest-src': ["'self'"]
};

constructor() {
this.nonce = this.generateNonce();
this.contentSecurityPolicy = this.buildCSP();
}

generateNonce() {
return crypto.randomBytes(SecurityPolicies.NONCE_LENGTH).toString('base64');
}

buildCSP() {
const directives = {...SecurityPolicies.CSP_DIRECTIVES};

directives['script-src'] = [
...directives['script-src'],
`'unsafe-inline'`,
`'nonce-${this.nonce}'`
];

directives['style-src'] = [
...directives['style-src'],
`'unsafe-inline'`,
`'nonce-${this.nonce}'`
];

return Object.entries(directives)
.map(([key, values]) => `${key} ${values.join(' ')}`)
.join('; ');
}

applySecurityPolicy(window) {

window.webContents.session.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': [this.contentSecurityPolicy],
'X-Content-Type-Options': ['nosniff'],
'X-Frame-Options': ['DENY'],
'X-XSS-Protection': ['1; mode=block'],
'Referrer-Policy': ['strict-origin-when-cross-origin'],
'Permissions-Policy': ['camera=(), microphone=(), geolocation=()']
}
});
});

// Disable navigation
window.webContents.on('will-navigate', (event, url) => {
const parsedUrl = new URL(url);
if (parsedUrl.origin !== 'file://') {
event.preventDefault();
}
});

// Block new window creation
window.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));

// Disable all permission requests
window.webContents.session.setPermissionRequestHandler((_, __, callback) => {
callback(false);
});

// Disable remote content
window.webContents.session.setPreloads([]);
}

static initSecurity(window) {
const securityPolicies = new SecurityPolicies();
securityPolicies.applySecurityPolicy(window);
return securityPolicies;
}

getNonce() {
return this.nonce;
}

getCSP() {
return this.contentSecurityPolicy;
}
}

module.exports = SecurityPolicies;

Основная идея состоит в том, чтобы применить Nonce к элементам, которые затем включают мой index.html выглядит следующим образом:






WebStack Deployer for Docker







Maintenance


Check for Updates
Backup Settings
Clear Cache
Reset Preferences

Exit



Settings
Help
About


×



WebStack Deployer for Docker






Как вы можете видеть, я реализовал этот токен , который должен быть заменен сгенерированной nonce nonce.
я предположил, что могу использовать загрузчик контента: < /p>
async loadContent() {
const isDev = process.env.NODE_ENV === 'development';
const nonce = this.securityPolicies.getNonce();

if (isDev) {
await this.mainWindow.loadURL('http://localhost:3000');
} else {
const htmlPath = path.join(__dirname, '../index.html');
let htmlContent = readFileSync(htmlPath, 'utf8');
htmlContent = htmlContent.replace(//g, nonce);

await this.mainWindow.loadFile(htmlPath, {
query: {nonce: nonce}
});
}
}

Вот где проблема заключается в том, что если я уже видел, что я генерирую htmlcontent и я не использую ее ... это потому, что для его использования я должен Сгенерировать URI, но я всегда получаю ошибку о уродливом URI, каким другим способом я могу его реализовать? Strong> < /p>
const { BrowserWindow } = require('electron');
const path = require('node:path');
const SecurityPolicies = require('../security/SecurityPolicies');
const {readFileSync} = require("node:fs");

class WindowManager {
constructor() {
this.mainWindow = null;
this.securityPolicies = null;
}

async createMainWindow() {
this.mainWindow = new BrowserWindow({
width: 1200,
height: 800,
frame: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
webSecurity: true,
preload: path.join(__dirname, '../preload.js'),
sandbox: true
}
});

this.securityPolicies = SecurityPolicies.initSecurity(this.mainWindow);
this.mainWindow.maximize();
await this.loadContent();

return new Promise((resolve) => {
this.mainWindow.once('ready-to-show', () => {
resolve(this.mainWindow);
});

this.mainWindow.on('closed', () => {
this.mainWindow = null;
this.securityPolicies = null;
});
});
}

async loadContent() {
const isDev = process.env.NODE_ENV === 'development';
const nonce = this.securityPolicies.getNonce();

if (isDev) {
await this.mainWindow.loadURL('http://localhost:3000');
} else {
const htmlPath = path.join(__dirname, '../index.html');
let htmlContent = readFileSync(htmlPath, 'utf8');
htmlContent = htmlContent.replace(//g, nonce);

await this.mainWindow.loadFile(htmlPath, {
query: {nonce: nonce}
});
}
}

getMainWindow() {
return this.mainWindow;
}

getSecurityPolicies() {
return this.securityPolicies;
}
}

module.exports = WindowManager;

main.js class:
const {app} = require('electron');
const AppConfig = require('./models/AppConfig');
const BackendController = require('./controllers/BackendController');
const WindowManager = require('./views/WindowManager');
const IpcController = require('./controllers/IpcController');
const ApplicationSetup = require('./core/ApplicationSetup');
const DevToolsManager = require('./core/DevToolsManager');
const AppLifecycle = require('./core/AppLifecycle');

class Application {
constructor() {
this.appConfig = new AppConfig();
this.backendController = new BackendController();
this.windowManager = null;
this.mainWindow = null;
this.ipcController = null;
}

async initialize() {
ApplicationSetup.configureCommandLineFlags();
app.setPath('userData', this.appConfig.getUserDataPath());

// Enable sandbox for all renderers
app.enableSandbox();

// Disable navigation outside the app
app.on('web-contents-created', (_, contents) => {
contents.on('will-navigate', (event) => {
event.preventDefault();
});
contents.setWindowOpenHandler(() => ({ action: 'deny' }));
});

try {
await this.backendController.initializeFetch();
await this.setupAppEvents();
return this.ipcController;
} catch (error) {
console.error('Initialization error:', error);
throw error;
}
}

async setupAppEvents() {
await app.whenReady();

try {
await this.backendController.startGoBackend();

this.windowManager = new WindowManager();
this.mainWindow = await this.windowManager.createMainWindow();

if (this.mainWindow) {
this.ipcController = new IpcController(
this.windowManager,
this.backendController,
this.appConfig
);

// Only enable DevTools in development
//if (process.env.NODE_ENV === 'development') {
DevToolsManager.setupDevToolsHandlers(this.mainWindow);
//}
}

AppLifecycle.setupAppEventHandlers(this.windowManager, this.backendController);
ApplicationSetup.setupProcessEventHandlers(this.backendController);

} catch (error) {
console.error('Setup error:', error);
throw error;
}
}
}

const application = new Application();
application.initialize().catch(err => {
console.error('Application initialization failed:', err);
app.quit();
});

module.exports = application;


Подробнее здесь: https://stackoverflow.com/questions/794 ... th-node-js
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Динамический Nonce: ошибка при использовании динамического nonce в .htaccess Content-Security-Policy (CSP) и PHP.
    Anonymous » » в форуме Php
    0 Ответы
    36 Просмотры
    Последнее сообщение Anonymous
  • Скрыть nonce CSP в консоли браузера
    Anonymous » » в форуме Php
    0 Ответы
    8 Просмотры
    Последнее сообщение Anonymous
  • Fullcalendar.io не работает с CSP nonce в браузере Safari
    Anonymous » » в форуме IOS
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • Как я могу получить доступ к пользовательскому $ nonce для CSP в шаблонах всех видов?
    Anonymous » » в форуме Php
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • Как я могу получить доступ к пользовательскому $ nonce для CSP в шаблонах всех видов?
    Anonymous » » в форуме Php
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Javascript»