How do I stop a coding assistant from using innerHTML?
Name the ban and its replacement in the prompt itself, for example "write text with textContent, never innerHTML", and say how to build structure instead. Repeat the rule in the rules file your tool reads, such as AGENTS.md, then back it with a lint rule, because an instruction alone guarantees nothing. Search every answer before you paste it.
Cite
CodeLifter Forum, "How do I stop a coding assistant from using innerHTML?", https://forum.codelifter.com/posts/how-do-i-stop-a-coding-assistant-from-using-innerhtml/, accessed 2026-10-16.- CodeLifter editorsStaffStaff, CodeLifter ·
Why innerHTML is the one to ban
Assigning a string to
innerHTMLparses that string as HTML. MDN's innerHTML reference calls the property "probably the most common vector for cross-site scripting (XSS) attacks", where unsafe strings from a user reach the DOM without being sanitized. The same page gives the plain alternative:Node.textContentshould be used when you know the content should be plain text, because that prevents it being parsed as HTML.Most snippets an assistant writes for a small page only need to show text, set an attribute or add an element. None of those needs HTML parsing, so a ban costs you nothing and removes a whole class of bug.
The prompt lines that do the work
A bare "don't use innerHTML" leaves the assistant to guess what to do instead. Name the replacement for each job. These lines are copied from the CodeLifter prompt pages, where the editors tested the code each prompt asks for:
Job in the code Prompt line What it produces Show changing text "Write with textContent, never innerHTML" (mouse position) el.textContent = valueAdd a link or other markup "build the link with createElement, never innerHTML" (random quote generator) document.createElement("a"), then sethrefand textSet an image "Set the large image's src and alt as properties, never by writing HTML" (image popup) img.src = url; img.alt = textTwo things make these lines work better than a general warning. First, each one pairs the ban with the method to use, which is what the Gemini prompting guide means when it says you can tell the model what to do and not to do. Second, they sit next to the task they apply to, so the instruction is still in view when the model writes that part.
Close the side doors too.
outerHTML,insertAdjacentHTML()anddocument.write()parse strings in the same way, and Mozilla's lint plugin, below, treats them as the same family. Add one line such as "Do not use innerHTML, outerHTML, insertAdjacentHTML or document.write" if you are prompting for anything larger than a snippet.The CodeLifter prompts have not been run against a named assistant, so treat every line here as a request that you still verify. For how a full prompt is put together, see How to write a coding prompt.
Put the rule where every session reads it
Typing the same line into every chat is easy to forget. Most coding agents read a standing rules file from the repository.
Create
AGENTS.mdin the root of your repository.Add a short section, for example:
## Code - Write text with textContent, never innerHTML. - Build elements with createElement; set attributes as properties. - Do not use outerHTML, insertAdjacentHTML or document.write.If your tool reads a different file by default, point it at the same rules. The file names differ by tool:
Tool File it reads GitHub Copilot .github/copilot-instructions.md, andAGENTS.mdCursor .cursor/rules, andAGENTS.mdClaude Code CLAUDE.md, orAGENTS.mdwhen there is noCLAUDE.mdGemini CLI GEMINI.md, orAGENTS.mdonce set ascontext.fileNamein.gemini/settings.jsonAider CONVENTIONS.mdloaded withaider --read CONVENTIONS.mdGitHub documents that the nearest AGENTS.md in the directory tree takes precedence, so a file in a subfolder can override the root one. The full list, with links to each vendor's page, is in the coding agents directory.
Make it fail the build
A rule in a Markdown file is advice. A lint error is a gate. Mozilla publishes eslint-plugin-no-unsanitized, which disallows assignments to
innerHTMLand calls such asinsertAdjacentHTML()unless the value goes through an escaping function.Install it:
npm install --save-dev eslint-plugin-no-unsanitizedIn
eslint.config.mjs, add the recommended config (adapted from the README):import nounsanitized from "eslint-plugin-no-unsanitized"; export default [nounsanitized.configs.recommended];Run
npx eslint .before each commit, or in CI.
Know its limits. The README lists
foo.innerHTML = 5and a fixed string literal as allowed, because neither can carry user input. If you want a total ban, add a plain search as well:grep -rnE "innerHTML|outerHTML|insertAdjacentHTML|document\.write" src/An empty result means none of those names appears in
src/.When you really need markup
Sometimes you are rendering HTML from a source you control, such as your own Markdown converter. MDN's advice for that case is to sanitize the input and assign a
TrustedHTMLobject rather than a string, with Trusted Types enforced by a Content Security Policy. If you go that way, say so in the prompt and name the sanitizer, or the assistant will pick one for you. Otherwise keep the ban.Check every answer
- Search the answer for the four names above before you paste it.
- Where you find one, ask for the replacement by name: "Rewrite this with textContent and createElement."
- Run the lint rule and fix what it reports.
- Test the result with the keyboard as well; the keyboard prompting thread has the lines for that.
If you run a local model, the same checks apply, and the local models thread covers what differs there.
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email belongs to a forum team account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.