feat: taint checking and security#197
feat: taint checking and security#197ambrishrawat wants to merge 45 commits intogenerative-computing:mainfrom
Conversation
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
|
@nrfulton quick clarifications -
|
We should infer automatically where-ever possible. I nthis case, I'm not sure how you would infer taint. I guess you assumption here is that |
|
Yes, that was the thinking. Making it configurable may make more sense for taint. Any thoughts on the best way to expose that? Would love your take on the code too. |
|
If there is a tainted variable in the context, everything downstream should get tainted. As for how variables get tainted in the first place, a common way people do this is to define sources, sinks, and (optionally) washers. These are wrappers around interfaces that produce sensitive data (e.g. HR database api), or where it enters an unsafe place (e.g. sending to a UI). |
4798f64 to
d1b09e1
Compare
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
d5f8033 to
5466c31
Compare
docs/dev/taint_analysis.md
Outdated
| component = CBlock("user input") | ||
| component.mark_tainted() # Sets SecLevel.tainted_by(component) |
There was a problem hiding this comment.
- CBlocks should be immutable.
- Naming a variable
Ccmponentand assigning it to aCBlockis confusing. - The cyclic reference here is a bit confusing and invites buggy code. Use
tainted_by(None)instead oftainted_by(self)for the root node.
c = CBlock("user input", sec_level=SecLevel.tained_by(None))There was a problem hiding this comment.
Updated this; tainted_by(None) for root now
docs/dev/taint_analysis.md
Outdated
| component = CBlock("user input") | ||
| component.mark_tainted() # Sets SecLevel.tainted_by(component) | ||
|
|
||
| if component._meta["_security"].is_tainted(): |
There was a problem hiding this comment.
Defined it as a property and now this works as c.sec_level.is_tainted()
| print(f"Original CBlock is tainted: {not tainted_desc.is_safe()}") | ||
|
|
||
| # Create session | ||
| session = MelleaSession(OllamaModelBackend("llama3.2")) |
There was a problem hiding this comment.
Unless the example critically depends on using a particular model, always use session = start_session() instead. This makes the examples easier to maintain.
|
|
||
| # The result should be tainted | ||
| print(f"Result is tainted: {not result.is_safe()}") | ||
| if not result.is_safe(): |
There was a problem hiding this comment.
We should use is_tainted instead of is_safe. The meaning of safe is very ambiguous.
There was a problem hiding this comment.
Removed all instances of is_safe
mellea/security/core.py
Outdated
| Returns: | ||
| The CBlock or Component that tainted this content, or None | ||
| """ | ||
| if self.level_type == "tainted_by": |
There was a problem hiding this comment.
Especially in a module called security.core, we should avoid use of magic strings.
mellea/security/core.py
Outdated
| sources.append(action) | ||
|
|
||
| # For Components, check their constituent parts for taint | ||
| if hasattr(action, 'parts'): |
There was a problem hiding this comment.
Instead us something like:
match action:
case Component...
case CBlock...(If type(action) :> Component then check is not necessary because the Component protocol has a parts() method. )
There was a problem hiding this comment.
Updated it to use match/case
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
|
Thanks for the review @nrfulton ! |
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
|
hi ambrish! |
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Signed-off-by: Ambrish Rawat <ambrish.rawat@ie.ibm.com>
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
| def wrapper(*args, **kwargs): | ||
| # Check all arguments for marked content (tainted or classified) | ||
| for arg in args: | ||
| if isinstance(arg, TaintChecking): |
There was a problem hiding this comment.
I'm wondering if there's an issue with here in not looking recursively (ie via taint_sources() )? the args may be ok, but we could have a tainted Component?
There was a problem hiding this comment.
Ah I see that, yes need to call taint_sources here and do a recursive check for classified sources as well. I will update this.
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
|
|
||
|
|
||
| def declassify(cblock: "CBlock") -> "CBlock": | ||
| """Create a declassified version of a CBlock (non-mutating). |
There was a problem hiding this comment.
Only CBlocks or any subclass? If the latter, we return a CBlock which would lose the subclass info?
For example could it be an ImageBlock?
Also note that ImageBlock never calls super().init() which means the value that is being copied does not exist == crash?
There was a problem hiding this comment.
Right, this particular declassify is merely illustrative, hence only applicable to CBlocks. One would need bespoke declassification methods for applications to sparsify taint information across the code. That was my initial thinking
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
This PR introduces a minimal proof-of-concept for taint and security propagation across CBlock, ModelOutputThunk, and session flows, as discussed in generative-computing/mellea#189
.