Skip to content

Commit 7abe322

Browse files
rcourtmanclaude
andcommitted
fix: enhance security by properly sanitizing sensitive data in diagnostic reports
- Add sanitization for name fields in Proxmox and PBS configurations - Sanitize PBS node_name values to prevent leaking actual node names - Improve URL sanitization to handle URLs without protocols - Use clearer redaction patterns (REDACTED-IP, REDACTED-HOST) - Add more aggressive fallback sanitization for malformed URLs This prevents exposure of sensitive infrastructure details when diagnostic reports are shared for debugging purposes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b4bae69 commit 7abe322

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

server/diagnostics.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,23 @@ class DiagnosticTool {
120120
sanitized.configuration.proxmox = sanitized.configuration.proxmox.map(pve => ({
121121
...pve,
122122
host: this.sanitizeUrl(pve.host),
123+
name: this.sanitizeUrl(pve.name),
123124
// Remove potentially sensitive fields, keep only structure info
124125
tokenConfigured: pve.tokenConfigured,
125126
selfSignedCerts: pve.selfSignedCerts
126127
}));
127128
}
128129

129130
if (sanitized.configuration.pbs) {
130-
sanitized.configuration.pbs = sanitized.configuration.pbs.map(pbs => ({
131+
sanitized.configuration.pbs = sanitized.configuration.pbs.map((pbs, index) => ({
131132
...pbs,
132133
host: this.sanitizeUrl(pbs.host),
134+
name: this.sanitizeUrl(pbs.name),
135+
// Sanitize node_name
136+
node_name: pbs.node_name === 'NOT SET' ? 'NOT SET' : `pbs-node-${index + 1}`,
133137
// Remove potentially sensitive fields, keep only structure info
134138
tokenConfigured: pbs.tokenConfigured,
135-
selfSignedCerts: pbs.selfSignedCerts,
136-
node_name: pbs.node_name
139+
selfSignedCerts: pbs.selfSignedCerts
137140
}));
138141
}
139142
}
@@ -151,10 +154,12 @@ class DiagnosticTool {
151154
}
152155

153156
if (sanitized.permissions.pbs) {
154-
sanitized.permissions.pbs = sanitized.permissions.pbs.map(perm => ({
157+
sanitized.permissions.pbs = sanitized.permissions.pbs.map((perm, index) => ({
155158
...perm,
156159
host: this.sanitizeUrl(perm.host),
157160
name: this.sanitizeUrl(perm.name),
161+
// Sanitize node_name
162+
node_name: perm.node_name === 'NOT SET' ? 'NOT SET' : `pbs-node-${index + 1}`,
158163
// Keep diagnostic info but sanitize error messages
159164
errors: perm.errors ? perm.errors.map(err => this.sanitizeErrorMessage(err)) : []
160165
}));
@@ -761,22 +766,35 @@ class DiagnosticTool {
761766

762767
sanitizeUrl(url) {
763768
if (!url) return 'Not configured';
769+
770+
// Handle URLs that may not have protocol
771+
let urlToParse = url;
772+
if (!url.includes('://')) {
773+
urlToParse = 'https://' + url;
774+
}
775+
764776
try {
765-
const parsed = new URL(url);
777+
const parsed = new URL(urlToParse);
766778
// Anonymize hostname/IP but keep protocol and port structure
767779
const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');
768780

769781
// Check if hostname is an IP address
770782
const isIP = /^(?:\d{1,3}\.){3}\d{1,3}$/.test(parsed.hostname);
771-
const anonymizedHost = isIP ? '[IP-ADDRESS]' : '[HOSTNAME]';
783+
const anonymizedHost = isIP ? 'REDACTED-IP' : 'REDACTED-HOST';
772784

785+
// Only include port if it's non-standard
786+
if ((parsed.protocol === 'https:' && port === '443') ||
787+
(parsed.protocol === 'http:' && port === '80')) {
788+
return `${parsed.protocol}//${anonymizedHost}`;
789+
}
773790
return `${parsed.protocol}//${anonymizedHost}:${port}`;
774791
} catch {
775-
// Fallback for malformed URLs
792+
// Fallback for malformed URLs - sanitize more aggressively
776793
return url
777-
.replace(/\/\/[^:]+:[^@]+@/, '//[USER]:[PASSWORD]@')
778-
.replace(/\b(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?\b/g, '[IP-ADDRESS]')
779-
.replace(/([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}/g, '[HOSTNAME]');
794+
.replace(/\/\/[^:]+:[^@]+@/, '//REDACTED:REDACTED@')
795+
.replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, 'REDACTED-IP')
796+
.replace(/:[0-9]{2,5}/g, ':PORT')
797+
.replace(/[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/g, 'REDACTED-HOST');
780798
}
781799
}
782800
}

0 commit comments

Comments
 (0)