Skip to content

Implemented changes to add support for HTML templates#199

Open
irsheep wants to merge 13 commits intoAndrewPaglusch:masterfrom
irsheep:html_form
Open

Implemented changes to add support for HTML templates#199
irsheep wants to merge 13 commits intoAndrewPaglusch:masterfrom
irsheep:html_form

Conversation

@irsheep
Copy link
Copy Markdown

@irsheep irsheep commented Nov 4, 2025

Added the functionality to create a template using HTML elements, this allows the user to create a basic form.

Signed-off-by: Luis Tavares <49619346+irsheep@users.noreply.github.com>
@AndrewPaglusch
Copy link
Copy Markdown
Owner

This looks really neat! I'll go ahead and review this with @mattburchett and see if we can get it merged. Thank you!

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds HTML template support to FlashPaper, allowing users to create structured forms with various input types (radio buttons, select boxes, date/time pickers, etc.) for secrets instead of plain text. The feature includes client-side template loading via AJAX, server-side rendering of templates, and API support for HTML-based secrets.

  • Implements client-side template loading with error handling and dynamic form rendering
  • Adds server-side template parsing and HTML generation for both viewing and editing modes
  • Extends the API to support HTML template-based secrets with special handling for HTML_FORM_SECRET marker

Reviewed Changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
js/templates.js Client-side template loading, form rendering, and AJAX utilities
js/flashpaper.js HTTPS warning banner, HTML form detection, and form element resizing logic
index.php Server-side processing to handle HTML form secrets on submission and retrieval
includes/functions.php Template HTML generation with input type support and file parsing utilities
img/copy.svg Copy icon SVG for individual field copy buttons
html/view_secret_html.php View template for displaying HTML-based secrets
html/submit_secret.php Updated submit form with template selector and content container
html/header.php Added CSS/JS includes, moved inline scripts to external files, added error overlay
css/table.css Styling for HTML form elements, animations, and overlay
ajax.php AJAX endpoint for template loading
README.md Documentation for HTML templates feature and API usage
Comments suppressed due to low confidence (1)

includes/functions.php:1

  • Potential undefined index error if 'secret' key doesn't exist in $formdata array. Should use isset() or null coalescing operator to check if the key exists before accessing it.
<?php

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

js/flashpaper.js Outdated
if (typeof type === 'undefined') {type = null;}

var element = null;
var text = null;
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use let or const instead of var for block-scoped variable declarations, consistent with modern JavaScript best practices and the rest of the codebase.

Suggested change
var text = null;
let text = null;

Copilot uses AI. Check for mistakes.
foreach (get_all_lines($file_handle) as $line) {
// Get the name, element and propeties to create the HTML elements
preg_match(
'/(?<name>.+):\s+(?<element>radio|select|number|textarea|datetime|date|time|datetime|checkbox)?(\((?<props>.+)?\))?/',
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word 'datetime' appears twice in the regex pattern, which is redundant. Remove the duplicate occurrence.

Copilot uses AI. Check for mistakes.
@AndrewPaglusch
Copy link
Copy Markdown
Owner

@irsheep I had Copilot do an initial review for some low-hanging fruit like typos and other small things. Would you mind addressing the above items it found? I'll do a full review as soon as I find some free time.

irsheep and others added 10 commits November 6, 2025 22:51
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Luis Tavares <49619346+irsheep@users.noreply.github.com>
Signed-off-by: Luis Tavares <49619346+irsheep@users.noreply.github.com>
$filename = basename($t, '.txt');
$url_filename = urlencode($filename);
echo "<option value=\"?t={$url_filename}\">{$filename}</option>";
echo "<option value=\"{$url_filename}\">{$filename}</option>";
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ability to include the template as part of the URL is something I personally use quite often. I would imagine this is used by others as well. It's useful for sending a template URL to someone to have them fill out and send back

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is still available, but there was an weird behaviour when ?t= was used, also now when specifying the template the combo box is updated with the name of the template.

Signed-off-by: Luis Tavares <49619346+irsheep@users.noreply.github.com>
@AndrewPaglusch
Copy link
Copy Markdown
Owner

Hey @irsheep, I finally got around to doing a deeper review of this PR and I found a stored XSS vulnerability that we'll need to address before merging.

The get_template_html() function doesn't do any output encoding on the values it places into HTML attributes. It relies on htmlentities() being called upstream, but the default flags (ENT_COMPAT) don't encode single quotes and all the generated HTML uses single-quoted attributes. This allows an attacker to break out of the attribute and inject event handlers.

What makes this worse is that any regular text secret can trigger the HTML form rendering path. There's no special flag or marker in the database. It just checks if the decrypted secret content contains secret:HTML_FORM_SECRET. So an attacker doesn't even need to use the HTML form feature. They can just submit a plain text secret with crafted content.

Here's how to reproduce:

  1. Run the following against your branch to submit a secret
curl -s -X POST http://foo.com/ -d "submit=1&json=true" --data-urlencode $'secret=secret:HTML_FORM_SECRET\nselect:Example form\nNumber:\' style=\'animation:pulse 1s\' onanimationstart=\'alert(document.domain)\' x=\''
  1. View the secret

JavaScript executes automatically, and you'll get an alert() popup.

The onanimationstart event fires even on disabled elements, so no user interaction is needed beyond viewing the secret. The pulse CSS animation is already defined in table.css.

I think there are two things that need to happen to fix this:

  1. get_template_html() needs to escape values at output time with htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before embedding them in HTML attributes
  2. We need a better way to distinguish HTML form secrets from regular text secrets. Maybe a separate column in the database rather than inferring it from the content?

Let me know if you have any questions or if you'd like to talk through the fix. Thanks!

Added error handling when parsing HTML form
Removed the requirement for HTML_FORM_SECRET

Signed-off-by: Luis Tavares <49619346+irsheep@users.noreply.github.com>
@irsheep
Copy link
Copy Markdown
Author

irsheep commented Apr 10, 2026

Hi,

HTML values are now escaped for html special characters, when viewing the secret message.

I tried to implement a better way of identifying a HTML secret, but unless the templates are placed on a different directory, have a different extension, I can't think of another way to distinguish them without parsing the content and checking the contents of the template. But I have removed the requirement of the secret:HTML_FORM_SECRET, being posted in the form now setting the select to the name of the HTML form and passing, one or more of the fields, and added some error handling for invalid requests.

curl -s -X POST http://localhost:8080/ -d "submit=1&json=true&select=Example+form" --data-urlencode $'Textarea=HTML form'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants