{"id":20836298,"url":"https://github.com/igrigorik/contextual","last_synced_at":"2026-04-06T01:32:00.058Z","repository":{"id":1760061,"uuid":"2655059","full_name":"igrigorik/contextual","owner":"igrigorik","description":"runtime contextual HTML autoescaper","archived":false,"fork":false,"pushed_at":"2012-05-24T18:19:22.000Z","size":1171,"stargazers_count":10,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-11-27T15:21:02.624Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"flosch/pongo2","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igrigorik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-10-27T01:00:22.000Z","updated_at":"2019-08-13T14:51:53.000Z","dependencies_parsed_at":"2022-09-17T21:01:44.997Z","dependency_job_id":null,"html_url":"https://github.com/igrigorik/contextual","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/igrigorik/contextual","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fcontextual","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fcontextual/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fcontextual/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fcontextual/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igrigorik","download_url":"https://codeload.github.com/igrigorik/contextual/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fcontextual/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31456629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"ssl_error","status_checked_at":"2026-04-05T21:22:51.943Z","response_time":75,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T00:29:26.771Z","updated_at":"2026-04-06T01:32:00.043Z","avatar_url":"https://github.com/igrigorik.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Runtime Contextual Autoescaper\n\nA JRuby wrapper for [Mike Samuel's contextual HTML autoescaper](https://github.com/mikesamuel/html-contextual-autoescaper-java). Same one as [used by Google's Closure Templates](http://code.google.com/closure/templates/docs/security.html).\n\n## Example\n\nFirst, let's define an Erb template:\n\n```erb\n\u003c% def helper(obj); \"Hello, #{obj['world']}\"; end %\u003e\n\n\u003cdiv style=\"color: \u003c%= object['color'] %\u003e\"\u003e\n\u003ca href=\"/\u003c%= object['color'] %\u003e?q=\u003c%= object['world'] %\u003e\" onclick=\"alert('\u003c%= helper(object) %\u003e');return false\"\u003e\u003c%= helper(object) %\u003e\u003c/a\u003e\n\u003cscript\u003e(function () {  // Sleepy developers put sensitive info in comments.\n var o = \u003c%= object %\u003e,\n w = \"\u003c%= object['world'] %\u003e\";\n})();\u003c/script\u003e\n\u003c/div\u003e\n```\n\nLet's load the template and execute it:\n\n```ruby\ntemplate = Erubis::ContextualEruby.new(template_string)\n\nobject = {\"world\" =\u003e \"\u003cCincinnati\u003e\", \"color\" =\u003e \"blue\"}\nputs template.result(binding())\n```\n\nOutput:\n\n```html\n\u003cdiv style=\"color: blue\"\u003e\n\u003ca href=\"/blue?q=%3cCincinnati%3e\" onclick=\"alert('Hello, \\x3cCincinnati\\x3e');return false\"\u003eHello, \u0026lt;Cincinnati\u0026gt;\u003c/a\u003e\n\u003cscript\u003e(function () {\n var o = {'world':'\\x3cCincinnati\\x3e','color':'blue'},\n w = \"\\x3cCincinnati\\x3e\";\n})();\u003c/script\u003e\n\u003c/div\u003e\n```\n\nThe safe parts are treated as literal chunks of HTML/CSS/JS, the query string parameters are auto URI encoded, same data is also auto escaped within the JS block, and the rendered object within the javascript block is automatically converted to JSON! Additionally, extra comments are removed, data is properly HTML escaped, and so forth.\n\nContextual will also automatically strip variety of injection cases for JS, CSS, and HTML, and give you a [dozen other features](https://github.com/mikesamuel/html-contextual-autoescaper-java/tree/master/src/tests/com/google/autoesc) for free.\n\n### License\n\n(MIT License) - Copyright (c) 2012 Ilya Grigorik","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fcontextual","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figrigorik%2Fcontextual","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fcontextual/lists"}