Summary
install.sh builds the installed admin view by piping the extension's admin.view source through bash's echo -e:
# scripts/commands/extensions/install.sh:1168 (main, beta-2026-06)
echo -e "$(<".blueprint/tmp/$admin_view")\n@endsection" >> "$AdminBladeConstructor"
echo -e expands backslash escapes, so any backslash in an extension's admin view is silently rewritten on the way to disk. Every other packaged file is copied verbatim; this one is not, and nothing warns the developer.
This is not theoretical — it took our panel down. A fully-qualified class name in our admin view, \Pterodactyl\BlueprintFramework\Extensions\<id>\Branding, put an ESC byte (0x1B) and a backspace (0x08) into the installed Blade, and /admin/extensions/<id> returned 500 on every request:
production.ERROR: syntax error, unexpected character 0x1B
(View: resources/views/admin/extensions/<id>/index.blade.php)
A fully-qualified class name is a completely ordinary thing to write in a Blade view, and the source file on disk is clean — the corrupt bytes only exist after install.
Minimal repro
Reproduces on any bash, including 3.2. \c is the worst of the three cases: it truncates the rest of the file and eats the appended @endsection, with no error at all.
$ printf '<p>@if($x)yes@endif</p>\n<p>{{ $path }}</p>\n<p>C:\\code\\thing</p>\n<p>tail of the view</p>\n' > view.blade.php
$ wc -c < view.blade.php
88
$ echo -e "$(<view.blade.php)\n@endsection" | cat -v
<p>@if($x)yes@endif</p>
<p>{{ $path }}</p>
<p>C:
$ echo -e "$(<view.blade.php)\n@endsection" | wc -c
48
40 bytes of the view are gone, @endsection was never appended, and the install reports success.
The other two:
\b → BS 0x08 (bash 3.2+)
\e / \E → ESC 0x1B (bash 4.2+) — this is what produced the 500 above
- also
\a \f \n \r \t \v \\ \0NNN \xHH \uHHHH \UHHHHHHHH
$ printf '<p>{{ \\Pterodactyl\\BlueprintFramework\\Extensions\\breeze\\Branding::x() }}</p>\n' > v.blade.php
$ echo -e "$(<v.blade.php)\n@endsection" | xxd | sed -n '4p'
00000030: 0872 6565 7a65 5c42 7261 6e64 696e 673a .reeze\Branding:
# ^^ 0x08, was 0x5C 0x62
Suggested fix
Append the bytes instead of echoing them. This preserves the file exactly and still handles a source file with no trailing newline:
cat ".blueprint/tmp/$admin_view" >> "$AdminBladeConstructor"
printf '\n@endsection\n' >> "$AdminBladeConstructor"
Verified against the repro above — 88 bytes in, 88 + \n@endsection\n out, backslashes intact.
printf '%s\n@endsection\n' "$(<file)" also works, but keeps the command substitution's trailing-newline stripping; cat avoids that too.
Notes
- Present on
main at scripts/commands/extensions/install.sh:1168, and in beta-2026-01 at blueprint/scripts/commands/extensions/install.sh:1192.
- Our own workaround, until this is fixed upstream, is to forbid backslashes in the admin view outright and enforce it with a byte-level test over the packaged file set — the admin view gets no backslash at all, and anything needing a class name moves into
admin.controller, which Blueprint copies verbatim. Happy to open a PR for the cat change if that's the direction you'd want.
Summary
install.shbuilds the installed admin view by piping the extension'sadmin.viewsource through bash'secho -e:echo -eexpands backslash escapes, so any backslash in an extension's admin view is silently rewritten on the way to disk. Every other packaged file is copied verbatim; this one is not, and nothing warns the developer.This is not theoretical — it took our panel down. A fully-qualified class name in our admin view,
\Pterodactyl\BlueprintFramework\Extensions\<id>\Branding, put an ESC byte (0x1B) and a backspace (0x08) into the installed Blade, and/admin/extensions/<id>returned 500 on every request:A fully-qualified class name is a completely ordinary thing to write in a Blade view, and the source file on disk is clean — the corrupt bytes only exist after install.
Minimal repro
Reproduces on any bash, including 3.2.
\cis the worst of the three cases: it truncates the rest of the file and eats the appended@endsection, with no error at all.40 bytes of the view are gone,
@endsectionwas never appended, and the install reports success.The other two:
\b→ BS 0x08 (bash 3.2+)\e/\E→ ESC 0x1B (bash 4.2+) — this is what produced the 500 above\a \f \n \r \t \v \\ \0NNN \xHH \uHHHH \UHHHHHHHHSuggested fix
Append the bytes instead of echoing them. This preserves the file exactly and still handles a source file with no trailing newline:
Verified against the repro above — 88 bytes in, 88 +
\n@endsection\nout, backslashes intact.printf '%s\n@endsection\n' "$(<file)"also works, but keeps the command substitution's trailing-newline stripping;catavoids that too.Notes
mainatscripts/commands/extensions/install.sh:1168, and inbeta-2026-01atblueprint/scripts/commands/extensions/install.sh:1192.admin.controller, which Blueprint copies verbatim. Happy to open a PR for thecatchange if that's the direction you'd want.