Skip to content

Conversation

@yoff
Copy link
Contributor

@yoff yoff commented Dec 10, 2025

The example shows how to build a barrier guard from a MaD row. Clearly, this should be done in a convenience predicate.

yoff added 5 commits January 20, 2026 17:57
and reinstate previously removed barrier
now as a MaD row
- consider if the model is in the right place
- consider if the barrier kind (sink kind) is the appropriate one
@yoff yoff force-pushed the python/mad-barriers branch from f89dd10 to d5e792d Compare January 20, 2026 17:04
@yoff yoff marked this pull request as ready for review January 20, 2026 17:21
@yoff yoff requested review from a team as code owners January 20, 2026 17:21
Copilot AI review requested due to automatic review settings January 20, 2026 17:21
@yoff yoff requested a review from a team as a code owner January 20, 2026 17:21
@yoff yoff added the no-change-note-required This PR does not need a change note label Jan 20, 2026
Copy link
Contributor

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 pull request adds Models-as-Data (MaD) support for barriers and barrier guards across Python, Ruby, and JavaScript, along with convenience predicates to simplify their usage.

Changes:

  • Introduces barrierModel and barrierGuardModel extensible predicates in all three languages
  • Adds convenience predicates sourceNode, sinkNode, and barrierNode to replace verbose patterns like getASourceNode(kind).asSource()
  • Implements ExternalBarrierGuard and ParameterizedBarrierGuard modules for handling barriers defined via MaD
  • Migrates several existing barriers to the new MaD framework (e.g., Django's url_has_allowed_host_and_scheme, Ruby's Regexp.escape/quote, JavaScript's encodeURIComponent/encodeURI)

Reviewed changes

Copilot reviewed 60 out of 60 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/ruby/javascript: ApiGraphModelsExtensions.qll Adds extensible predicates for barrier and barrier guard models
python/ruby/javascript: ApiGraphModels.qll Implements internal support for barrier models and adds convenience predicates (sourceNode, sinkNode, barrierNode)
python/ruby/javascript: empty.model.yml Registers new extensible predicates in data extension system
python: DataFlowPublic.qll Adds ParameterizedBarrierGuard and ExternalBarrierGuard modules
ruby: DataFlowPublic.qll Adds ParameterizedBarrierGuard and ExternalBarrierGuard modules
ruby: SsaImpl.qll Adds ParameterizedBarrierGuard module at SSA level
javascript: BarrierGuards.qll Adds ExternalBarrierGuard module
python/ruby/javascript: Multiple customization files Migrates from verbose .getASinkNode(kind).asSink() to concise sinkNode(node, kind) pattern
ruby: regexp/model.yml Defines Regexp.escape/quote as barriers for regexp-injection
python: Django.model.yml Defines url_has_allowed_host_and_scheme as barrier guard for url-redirection
javascript: NodeJSLib.model.yml Defines encodeURIComponent/encodeURI as barriers for request-forgery
python: Django.qll Removes hand-coded Django URL validation barrier in favor of MaD model
ruby: RegExpInjectionCustomizations.qll Removes hand-coded Regexp.escape barrier in favor of MaD model
javascript: IncompleteHtmlAttributeSanitizationCustomizations.qll Replaces EncodingSanitizer with MaD-based sanitizer
python: UrlRedirectCustomizations.qll Adds SanitizerFromModel for MaD-defined barriers
Test expectation files Updates MaD IDs due to new extensible predicates

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

this = DataFlow::globalVarRef(["encodeURIComponent", "encodeURI"]).getACall()
}
private class SanitizerFromModel extends Sanitizer {
SanitizerFromModel() { ModelOutput::barrierNode(this, "request-forgery") }
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The barrier kind "request-forgery" appears to be incorrect for this context. This class is in the IncompleteHtmlAttributeSanitization module, where encodeURIComponent/encodeURI were being used as sanitizers for incomplete HTML attribute sanitization vulnerabilities. The barrier kind should likely be something related to HTML injection or incomplete HTML attribute sanitization, not "request-forgery".

Suggested change
SanitizerFromModel() { ModelOutput::barrierNode(this, "request-forgery") }
SanitizerFromModel() { ModelOutput::barrierNode(this, "incomplete-html-attribute-sanitization") }

Copilot uses AI. Check for mistakes.
*/
class SanitizerFromModel extends Sanitizer {
SanitizerFromModel() {
this = DataFlow::ExternalBarrierGuard::getAnExternalBarrierNode("url-redirection")
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to use barrierNode instead.

Suggested change
this = DataFlow::ExternalBarrierGuard::getAnExternalBarrierNode("url-redirection")
ModelOutput::barrierNode(this, "url-redirection")

@aschackmull
Copy link
Contributor

Generally looks good, but I would like to question whether getABarrierNode, getABarrierGuardNode, and ExternalBarrierGuard::getAnExternalBarrierNode all need to be public? Using any of those is likely to be a mistake (as the one I highlighted in the comment above) when all you really need is predicate barrierNode(DataFlow::Node node, string kind). If their public status is mainly an artifact of the current code organisation, then we should at least prefix their qldoc with a big fat INTERNAL: Do not use.

@hvitved
Copy link
Contributor

hvitved commented Jan 21, 2026

Remember to run DCA for relevant languages.

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

Labels

JS no-change-note-required This PR does not need a change note Python Ruby

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants