Skip to content
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

Consider how to incorporate local shield in to the Arcjet SDK #3452

Open
e-moran opened this issue Mar 4, 2025 · 7 comments
Open

Consider how to incorporate local shield in to the Arcjet SDK #3452

e-moran opened this issue Mar 4, 2025 · 7 comments

Comments

@e-moran
Copy link
Contributor

e-moran commented Mar 4, 2025

From our team call yesterday, the leading solution is to consider shield as a product (such as signup protection), made up of multiple primitives (local detection, remote detection)

The main issue that arises from this is that shield is currently the name of a rule. Making it a "product" in the current structure of the SDK would be a large breaking change, as the results would be attributable to, for example, "LOCAL_DETECTION" instead of "SHIELD". So any code to handle the results could break.

@blaine-arcjet proposed a solution where we allow filtering on products as well as primitives.

@blaine-arcjet
Copy link
Contributor

Right, I was thinking that perhaps "products" should have a different top-level reason. Currently, our only product is protectSignup and it's a little strange that the decision.reason will never reference signup protection.

If we made the top-level reason "signup protection", I think it makes sense to deconstruct the primitives in rule results since they all contribute to the top-level decision.

To be clear "LOCAL_DETECTION" will not be a primitive—we'll have a primitive for sqli detection, a primitive for xss detection, and a primitive for remote WAF execution.

Note: Any move from a primitive to a product will be a breaking change but we just need to figure out where it will break and design a solution that won't break as we move into more products.

@davidmytton
Copy link
Contributor

If shield becomes a product and the default rule it applies is waf, being the remote WAF we currently run, then that wouldn't be a breaking change in terms of the behavior. The config might be different, although we could make it so that specifying no additional primitives would default to enabling waf.

Then you can enable the additional primitives like detectMysqli and detectXss if you want them.

For example these would be equivalent, maintain backwards compatibility, and be the same behavior as today:

rules: [
  shield({
    mode: "LIVE"
  })
]
rules: [
  shield({
    waf: { mode: "LIVE" }
  })
]
rules: [
  waf({ mode: "LIVE" })
]

Then for the new functionality as the Shield product

rules: [
  shield({
    waf: { mode: "LIVE" },
    detectMysqli:  { mode: "LIVE" },
    // ...
  })
]

which can also be configured as primitives:

rules: [
  waf({ mode: "LIVE" }),
  detectMysqli({ mode: "LIVE" }),
]

@blaine-arcjet
Copy link
Contributor

@davidmytton except the RuleResult for waf will not be "SHIELD" and any filtering/inspection for it won't be there. This is the breaking change.

@davidmytton
Copy link
Contributor

To maintain backwards compatibility we could overwrite the RuleResult if it's not specified like in my first example. But if they specifically use waf then it would return the RuleResult as waf.

@e-moran
Copy link
Contributor Author

e-moran commented Mar 5, 2025

I imagine that people are more likely to use .isShield() on the rule result, rather than compare the type directly though. If we added .isX() for products like I think @blaine-arcjet suggested then this would be less of a breaking change.

@blaine-arcjet
Copy link
Contributor

suggested then this would be less of a breaking change.

@e-moran Right, "less" but not none. You need to decide if protectSignup is changed to indicate the product so things stay consistent with shield. And then you need to decide if rule results show the primitives or the product.

@e-moran
Copy link
Contributor Author

e-moran commented Mar 6, 2025

And then you need to decide if rule results show the primitives or the product.

I feel like it should be both, there's still value to being able to filter for specific rules from a product. What if we introduced a new productType (naming tbd) field on rule results which contained the product. Then a waf rule result from the shield product would return true for both .isShield() and .isWaf().

The only downside here is that it would break people currently doing comparisons like result.type === "SHIELD", but its probably much more common that they just use .isShield() like we document.

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

No branches or pull requests

3 participants