Merge pull request #197 from Pouzor/some-fixes
Security fixes: Dependabot + code scanning alerts
This commit is contained in:
@@ -6,6 +6,9 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
smoke-and-integration:
|
smoke-and-integration:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-scripts:
|
lint-scripts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ on:
|
|||||||
schedule:
|
schedule:
|
||||||
- cron: '0 9 * * 1' # Weekly on Monday
|
- cron: '0 9 * * 1' # Weekly on Monday
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
secrets-scan:
|
secrets-scan:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ htmlcov/
|
|||||||
*.db-shm
|
*.db-shm
|
||||||
*.db-wal
|
*.db-wal
|
||||||
*.db.back
|
*.db.back
|
||||||
|
*.db.back-*
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
.docker/
|
.docker/
|
||||||
|
|||||||
Generated
+3
-3
@@ -6196,9 +6196,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hono": {
|
"node_modules/hono": {
|
||||||
"version": "4.12.18",
|
"version": "4.12.25",
|
||||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz",
|
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.25.tgz",
|
||||||
"integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==",
|
"integrity": "sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
|
|||||||
@@ -37,6 +37,9 @@
|
|||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"zustand": "^5.0.11"
|
"zustand": "^5.0.11"
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"hono": "^4.12.21"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.1",
|
"@eslint/js": "^9.39.1",
|
||||||
"@tailwindcss/vite": "^4.2.1",
|
"@tailwindcss/vite": "^4.2.1",
|
||||||
|
|||||||
@@ -53,6 +53,33 @@ describe('generateMarkdownTable', () => {
|
|||||||
expect(md).toContain('A\\|B')
|
expect(md).toContain('A\\|B')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('escapes backslashes before pipes so the escape char is not ambiguous', () => {
|
||||||
|
const nodes = [makeNode({ label: 'A\\|B' })]
|
||||||
|
const md = generateMarkdownTable(nodes)
|
||||||
|
// backslash doubled, then the literal pipe escaped
|
||||||
|
expect(md).toContain('A\\\\\\|B')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('collapses newlines in cell values so they do not break the table', () => {
|
||||||
|
const nodes = [makeNode({ label: 'line1\nline2', hostname: 'a\r\nb' })]
|
||||||
|
const lines = generateMarkdownTable(nodes).split('\n')
|
||||||
|
// header + separator + exactly one data row (no extra line from the value)
|
||||||
|
expect(lines).toHaveLength(3)
|
||||||
|
expect(lines[2]).toContain('line1 line2')
|
||||||
|
expect(lines[2]).toContain('a b')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('escapes pipe characters inside service names', () => {
|
||||||
|
const nodes = [makeNode({
|
||||||
|
label: 'Server',
|
||||||
|
services: [{ port: 80, protocol: 'tcp', service_name: 'web|proxy' }],
|
||||||
|
})]
|
||||||
|
const lines = generateMarkdownTable(nodes).split('\n')
|
||||||
|
// header + separator + exactly one data row — the pipe must not add a column
|
||||||
|
expect(lines).toHaveLength(3)
|
||||||
|
expect(lines[2]).toContain('web\\|proxy')
|
||||||
|
})
|
||||||
|
|
||||||
it('generates one row per non-groupRect node', () => {
|
it('generates one row per non-groupRect node', () => {
|
||||||
const nodes = [
|
const nodes = [
|
||||||
makeNode({ type: 'server', label: 'A' }, '1'),
|
makeNode({ type: 'server', label: 'A' }, '1'),
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ const EMPTY = '—'
|
|||||||
|
|
||||||
function cell(v: string | null | undefined): string {
|
function cell(v: string | null | undefined): string {
|
||||||
if (!v) return EMPTY
|
if (!v) return EMPTY
|
||||||
// Escape pipe chars so they don't break the table
|
// Escape backslashes first, then pipes, and collapse newlines so they don't break the table
|
||||||
return v.replace(/\|/g, '\\|')
|
return v
|
||||||
|
.replace(/\\/g, '\\\\')
|
||||||
|
.replace(/\|/g, '\\|')
|
||||||
|
.replace(/\r?\n/g, ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateMarkdownTable(nodes: Node<NodeData>[]): string {
|
export function generateMarkdownTable(nodes: Node<NodeData>[]): string {
|
||||||
@@ -27,7 +30,7 @@ export function generateMarkdownTable(nodes: Node<NodeData>[]): string {
|
|||||||
cell(d.ip),
|
cell(d.ip),
|
||||||
cell(d.hostname),
|
cell(d.hostname),
|
||||||
cell(d.status),
|
cell(d.status),
|
||||||
services,
|
cell(services),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user