-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use literal-string
for Document::fromString()
$markup
#32
Conversation
Using the exploit example kind of kills the very idea using a templating engine to begin with - nothing templado could be doing here for the rescue... ;) That being said, I do agree with the notion of having using Thanks! |
Codecov ReportPatch and project coverage have no change.
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. Additional details and impacted files@@ Coverage Diff @@
## main #32 +/- ##
===========================================
Coverage 100.00% 100.00%
Complexity 269 269
===========================================
Files 24 24
Lines 941 941
===========================================
Hits 941 941
☔ View full report in Codecov by Sentry. |
Thanks @theseer.
What I usually find is a senior developer uses the templating engine (good), then several months/years later a junior developer is asked to make a change, and they will sometimes put it into the template string, and it's not caught, often because it's one tiny change amongst many... and yes, I know, small commits, code reviews, etc; but I'm often only with a team for a week or two, and can't expect the senior to always pick up these things - that's what static analysis tools are good at :-) |
I'm totally understanding where you're coming from. Unfortunately, I'm no longer convinced I can merge the change. Quoting the psalm documentation on literal-string
While the general intention makes perfect sense, the fact it won't allow |
I just gave it a try locally, despite expecting it to not work. I do not see a way, for As nice as the idea was, I don't see a means of supporting it. I'll just reject the PR. Feel free to add additional comments and thoughts though :) |
For the record: Templado 4 does not use |
Ref developers using For Redis or MySQL, you're right, those cannot be trusted, and Templado shouldn't add loaders for them (you cannot provide the security guarantees needed). Personally I would provide a method like As to Templado 4 using Thanks for considering anyway, if I work with a team who is using Templado, I can always get them to make a wrapper for Templado, or create a stub, to add this security check. |
Sorry :-) Maybe I'll re-add some helpers for that. But it's additional complexity for the main engine which should focus on, well, engine related things ;)
I believe to understand your idea. But it just adds complexity to the engine component. And one, I cannot actually write tests for as PHP doesn't see the difference between
That fragement is an example on how to extract something to pass along. It's not what Templado is doing in general.
I see :) |
Yep, the location of the complexity is important, although I would hope that a
I suppose having 3 methods to load the template (from string, from file, or from an unsafe source) would be adding some kind of complexity.
I spent many years trying to get taint checking to work, specifically trying to get the taint PECL extension to understand context. But I gave up, it's far too complicated. I've given several talks on this subject, and how taint checking is flawed (see also the limitations section of the psalm manual). But I learnt about the "developer defined string" idea from Christoph Kern and Mike Samuel, and how it solves the problem - as in, it's impossible to have an Injection Vulnerability when the string does not contain user data. Instead you either keep user values separate (parameterised queries), or use a library to do context aware escaping (consistently, correctly, well tested, with domain expert knowledge). That's why I created the is_literal() RFC, and while it failed the vote, the main feedback I got was the need to include Phase 2, which is to have a |
Curious what's going to come from that. I never understood the hype about taint modes. It's just a broken concept, as said before. I'm also not sure I'm fully buying into the literal movement as of yet. For a simple reason: What does "defined in code" mean in a scripting language that parses files at runtime? file_put_contents('test.php', sprintf('<?php return "%s"; ?>', $_GET['foo']));
$var = require('test.php'); Is There is just no technical solution to a social problem. |
Agreed, I tried to make
May I suggest Anyway, yes, a developer could do that, but it's not something I've ever typed by accident, or found in the wilds. And I don't think we should worry about developers being intentionally malicious; instead I'm focusing on the fact that developers make mistakes all the time, even if they have been taught how to do things "correctly" (why this issue remains in the OWASP Top 10).
Don't see how a social change can stop these mistakes, unless you're thinking that we beat developers any time they make a mistake? so they are extra careful? personally I think this simple technical solution is better ;-) And, because I want to make sure I'm not proposing a flawed solution, I'll also check your other questions:
|
To me, the last part is the "killer argument": How do you load a template? |
Templado simply provides 3 methods (+15 lines):
|
Just taking a quick look at the Templado Documentation, for Engine 4, it looks like you used
DOMDocument::loadHTML()
andDOMDocument::loadXML()
directly.With Engine 5, it looks like you might be adding an abstraction for this, with Document::fromString()?
To ensure developers create their HTML/XML for their templates/snippets correctly, they should not include untrusted user data (those values should be provided separately, so Templado can encode them correctly).
This means the HTML/XML should either come from files on the disk (i.e. files created by the developer), or from "developer defined strings", known as the
literal-string
type in Static Analysis tools PHPStan and Psalm (also supported by PhpStorm 2022.3).The
literal-string
type can used with variables, and supports concatenation; e.g.Try it with PHPStan or Psalm.
It simply allows developers to check (via static analysis) they haven't made a classic mistake like this:
(note, hopefully senior developers won't make these mistakes, but juniors developers do).
The
literal-string
type works for all kinds of Injection vulnerabilities (SQL, HTML, CLI, etc), and why database abstractions like Nette, Propel, RedBean uses it - and it does find mistakes.As an aside, Pradeep Srinivasan and Graham Bleaney (Facebook/Meta) introduced the LiteralString type in Python 3.11; and this technique can be used in other programming languages.