fix(server): security audit JSON parse error on duplicate sshd_config directives#4889
Open
reikjarloekl wants to merge 1 commit into
Open
fix(server): security audit JSON parse error on duplicate sshd_config directives#4889reikjarloekl wants to merge 1 commit into
reikjarloekl wants to merge 1 commit into
Conversation
Duplicate directives in sshd_config (e.g. two active PermitRootLogin lines from Match blocks or provisioning scripts) made the grep|awk captures multi-line. The embedded newline ended up inside a JSON string literal, so JSON.parse failed with "Bad control character in string literal" and the Security tab showed a red banner plus default values. Take the first match (mirroring sshd's first-match-wins semantics) and strip carriage returns from CRLF-edited configs.
reikjarloekl
marked this pull request as ready for review
July 22, 2026 03:32
AminDhouib
added a commit
to DevinoSolutions/dokploy-community
that referenced
this pull request
Jul 22, 2026
port: fix security audit parse error on duplicate sshd_config directives (upstream Dokploy#4889)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this PR about?
The Security tab for remote servers fails with a red banner —
Failed to parse output: Bad control character in string literal in JSON at position 148 (line 1 column 149)— whenever the remote/etc/ssh/sshd_configcontains more than one active line for the same directive (e.g. a globalPermitRootLoginplus one added by a provisioning/hardening script or aMatchblock). All values in the tab then fall back to defaults, which also explains the "false negatives" reported in #2478.Root cause:
serverAudit()builds JSON on the remote host by interpolating rawgrep | awkoutput into string literals:permitRootLogin=$(sudo grep -i "^PermitRootLogin" "$sshd_config" | grep -v "#" | awk '{print $2}')With two matching lines this yields
prohibit-password\nyes. Command substitution strips only trailing newlines, so the interior newline lands inside a JSON string literal andJSON.parserejects it.Fix: append
| head -n1 | tr -d '\r'to the value captures (permitRootLogin,passwordAuth,usePam, ufwdefaultIncoming) and| head -n1to thepubkey_linecheck.head -n1mirrors sshd's own first-match-wins semantics, so the reported value is the one actually in effect;tr -d '\r'guards against CRLF-edited config files causing the same parse error.How this was tested
1. Local instance against a real affected server. Ran a local dev instance (canary + this patch), added a remote Ubuntu server whose
sshd_confighas two activePermitRootLoginlines (line 42prohibit-password, line 132yes), and opened the Security tab — see before/after screenshots below.2. Byte-for-byte reproduction of the generated script. Extracted the exact bash that
serverAudit()generates from the TypeScript source, ran it against a replica of that sshd_config, and fed the output toJSON.parseexactly asserver-audit.tsdoes.Before (byte-for-byte the reported error):
After:
permitRootLogincorrectly reportsprohibit-password— the first match, which is the value sshd actually applies.What this intentionally does not cover
The audit reads only the main
sshd_config, not files pulled in viaInclude /etc/ssh/sshd_config.d/*.conf(mentioned in a comment on #2478, e.g. cloud-init's50-cloud-init.confsettingPasswordAuthentication yes). Resolving effective values (e.g. viasudo sshd -T) would be a good follow-up, but is a separate accuracy concern — this PR is scoped to the parse failure that breaks the tab entirely.Checklist
Before submitting this PR, please make sure that:
canarybranch.Issues related (if applicable)
Fixes the JSON parse error and the resulting default/false values reported in #2478 (the
sshd_config.dinclude handling from that issue is noted above as a follow-up).Screenshots (if applicable)
Before — parse error banner, every field showing false defaults:
After (same server) — real state rendered: UFW detected, SSH enabled, key auth on: