diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml
new file mode 100644
index 0000000..cfedc46
--- /dev/null
+++ b/.github/codeql-config.yml
@@ -0,0 +1,28 @@
+name: BentoPDF CodeQL config
+
+paths-ignore:
+ - dist
+ - dist-test
+ - coverage
+ - node_modules
+ - vendor
+ - bentopdf-pymupdf-wasm
+ - libreoffice-wasm-package
+ - bentopdf-airgap-bundle
+ - public/pdfjs-viewer
+ - public/pdfjs-annotation-viewer
+ - public/libreoffice-wasm
+ - public/coherentpdf.browser.min.js
+ - public/workers
+ - public/embedpdf
+ - docs/.vitepress
+ - '**/*.min.js'
+ - '**/*.d.ts'
+
+query-filters:
+ - exclude:
+ id: js/log-injection
+ - exclude:
+ id: js/tainted-format-string
+ - exclude:
+ id: js/file-system-race
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index fa3f119..9a0ad2d 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -32,26 +32,8 @@ jobs:
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- queries: security-extended,security-and-quality
- config: |
- paths-ignore:
- - dist
- - dist-test
- - coverage
- - node_modules
- - vendor
- - bentopdf-pymupdf-wasm
- - libreoffice-wasm-package
- - bentopdf-airgap-bundle
- - public/pdfjs-viewer
- - public/pdfjs-annotation-viewer
- - public/libreoffice-wasm
- - public/coherentpdf.browser.min.js
- - public/workers
- - public/embedpdf
- - docs/.vitepress
- - '**/*.min.js'
- - '**/*.d.ts'
+ queries: security-extended
+ config-file: ./.github/codeql-config.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
diff --git a/scripts/generate-i18n-pages.mjs b/scripts/generate-i18n-pages.mjs
index 5a32db8..846cd0a 100644
--- a/scripts/generate-i18n-pages.mjs
+++ b/scripts/generate-i18n-pages.mjs
@@ -145,7 +145,9 @@ function processFileForLanguage(
href.startsWith('#') ||
href.startsWith('mailto:') ||
href.startsWith('tel:') ||
- href.startsWith('javascript:')
+ href.startsWith('javascript:') ||
+ href.startsWith('data:') ||
+ href.startsWith('vbscript:')
) {
return;
}
diff --git a/src/js/i18n/i18n.ts b/src/js/i18n/i18n.ts
index 5513148..4bf6198 100644
--- a/src/js/i18n/i18n.ts
+++ b/src/js/i18n/i18n.ts
@@ -235,7 +235,9 @@ export const rewriteLinks = (): void => {
href.startsWith('mailto:') ||
href.startsWith('tel:') ||
href.startsWith('#') ||
- href.startsWith('javascript:')
+ href.startsWith('javascript:') ||
+ href.startsWith('data:') ||
+ href.startsWith('vbscript:')
) {
return;
}
diff --git a/src/js/logic/form-creator.ts b/src/js/logic/form-creator.ts
index 36692a2..b6d7e09 100644
--- a/src/js/logic/form-creator.ts
+++ b/src/js/logic/form-creator.ts
@@ -754,7 +754,8 @@ function renderField(field: FormField): void {
contentEl.appendChild(img);
} catch (error) {
console.warn(
- `Failed to render barcode preview for field "${field.name}":`,
+ 'Failed to render barcode preview for field:',
+ String(field.name).replace(/[\r\n]+/g, ' '),
error
);
contentEl.innerHTML = `
Invalid data
`;
@@ -2320,11 +2321,17 @@ downloadBtn.addEventListener('click', async () => {
if (existingField) {
radioGroup = existingField as PDFRadioGroup;
radioGroups.set(groupName, radioGroup);
- console.log(`Using existing radio group from PDF: ${groupName}`);
+ console.log(
+ 'Using existing radio group from PDF:',
+ String(groupName).replace(/[\r\n]+/g, ' ')
+ );
} else {
radioGroup = form.createRadioGroup(groupName);
radioGroups.set(groupName, radioGroup);
- console.log(`Created new radio group: ${groupName}`);
+ console.log(
+ 'Created new radio group:',
+ String(groupName).replace(/[\r\n]+/g, ' ')
+ );
}
}
@@ -2690,7 +2697,8 @@ downloadBtn.addEventListener('click', async () => {
pdfPage.drawImage(pngImage, { x, y, width, height });
} catch (e) {
console.warn(
- `Failed to generate barcode for field "${field.name}":`,
+ 'Failed to generate barcode for field:',
+ String(field.name).replace(/[\r\n]+/g, ' '),
e
);
}
diff --git a/src/js/logic/pdf-workflow-page.ts b/src/js/logic/pdf-workflow-page.ts
index 9de0984..a3ad6b6 100644
--- a/src/js/logic/pdf-workflow-page.ts
+++ b/src/js/logic/pdf-workflow-page.ts
@@ -554,7 +554,10 @@ async function addNodeToCanvas(
try {
const node = createNodeByType(type);
if (!node) {
- console.error('Node type not found in registry:', type);
+ console.error(
+ 'Node type not found in registry:',
+ String(type).replace(/[\r\n]+/g, ' ')
+ );
return;
}
await editor.addNode(node);
diff --git a/src/js/workflow/nodes/encrypt-node.ts b/src/js/workflow/nodes/encrypt-node.ts
index 0d50218..7d1bb57 100644
--- a/src/js/workflow/nodes/encrypt-node.ts
+++ b/src/js/workflow/nodes/encrypt-node.ts
@@ -45,7 +45,7 @@ export class EncryptNode extends BaseWorkflowNode {
return {
pdf: await processBatch(pdfInputs, async (input) => {
const qpdf = await initializeQpdf();
- const uid = `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+ const uid = `${Date.now()}_${crypto.randomUUID().slice(0, 7)}`;
const inputPath = `/tmp/input_encrypt_${uid}.pdf`;
const outputPath = `/tmp/output_encrypt_${uid}.pdf`;
diff --git a/src/js/workflow/nodes/linearize-node.ts b/src/js/workflow/nodes/linearize-node.ts
index cadb9f3..b7d9680 100644
--- a/src/js/workflow/nodes/linearize-node.ts
+++ b/src/js/workflow/nodes/linearize-node.ts
@@ -28,7 +28,7 @@ export class LinearizeNode extends BaseWorkflowNode {
return {
pdf: await processBatch(pdfInputs, async (input) => {
const qpdf = await initializeQpdf();
- const uid = `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+ const uid = `${Date.now()}_${crypto.randomUUID().slice(0, 7)}`;
const inputPath = `/tmp/input_linearize_${uid}.pdf`;
const outputPath = `/tmp/output_linearize_${uid}.pdf`;
diff --git a/src/js/workflow/nodes/overlay-node.ts b/src/js/workflow/nodes/overlay-node.ts
index e27b9a0..5c5a53c 100644
--- a/src/js/workflow/nodes/overlay-node.ts
+++ b/src/js/workflow/nodes/overlay-node.ts
@@ -40,7 +40,7 @@ export class OverlayNode extends BaseWorkflowNode {
const mode = modeControl?.value === 'underlay' ? '--underlay' : '--overlay';
const qpdf = await initializeQpdf();
- const uid = `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+ const uid = `${Date.now()}_${crypto.randomUUID().slice(0, 7)}`;
const inputPath = `/tmp/input_overlay_${uid}.pdf`;
const overlayPath = `/tmp/overlay_${uid}.pdf`;
const outputPath = `/tmp/output_overlay_${uid}.pdf`;
diff --git a/src/js/workflow/nodes/repair-node.ts b/src/js/workflow/nodes/repair-node.ts
index 05c882e..3cc0079 100644
--- a/src/js/workflow/nodes/repair-node.ts
+++ b/src/js/workflow/nodes/repair-node.ts
@@ -25,7 +25,7 @@ export class RepairNode extends BaseWorkflowNode {
return {
pdf: await processBatch(pdfInputs, async (input) => {
const qpdf = await initializeQpdf();
- const uid = `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+ const uid = `${Date.now()}_${crypto.randomUUID().slice(0, 7)}`;
const inputPath = `/tmp/input_repair_${uid}.pdf`;
const outputPath = `/tmp/output_repair_${uid}.pdf`;
diff --git a/vite.config.ts b/vite.config.ts
index 4ffb79a..feecd73 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -328,9 +328,10 @@ function createCorsProxyMiddleware(): Connect.NextHandleFunction {
);
proxyReq.on('error', (err) => {
- console.error('[CORS Proxy] Error:', err.message);
+ const msg = String(err.message).replace(/[\r\n]+/g, ' ');
+ console.error('[CORS Proxy] Error:', msg);
res.statusCode = 502;
- res.end(`Proxy error: ${err.message}`);
+ res.end(`Proxy error: ${msg}`);
});
if (body.length > 0) {