|
7 | 7 |
|
8 | 8 | private import python |
9 | 9 | private import semmle.python.ApiGraphs |
| 10 | +private import semmle.python.dataflow.new.DataFlow |
10 | 11 |
|
11 | 12 | /** |
12 | 13 | * Provides models for agents SDK (instances of the `agents.Runner` class etc). |
@@ -86,3 +87,32 @@ module OpenAI { |
86 | 87 | ) |
87 | 88 | } |
88 | 89 | } |
| 90 | + |
| 91 | +/** |
| 92 | + * Provides attribute-name-based sink detection for `chat.completions.create` calls. |
| 93 | + * This does not rely on API graph type resolution and thus works even when |
| 94 | + * the receiver cannot be traced back to a known constructor (e.g. due to `or` expressions). |
| 95 | + */ |
| 96 | +module ChatCompletionsCreate { |
| 97 | + /** |
| 98 | + * Gets a `DataFlow::Node` that is the `content` value inside a message dict |
| 99 | + * passed to a `*.chat.completions.create(messages=[{..., "content": <HERE>}])` call, |
| 100 | + * matched purely by attribute names in the call chain. |
| 101 | + */ |
| 102 | + DataFlow::Node getAMessageContentSink() { |
| 103 | + exists( |
| 104 | + DataFlow::MethodCallNode createCall, DataFlow::AttrRead completionsAttr, |
| 105 | + DataFlow::AttrRead chatAttr |
| 106 | + | |
| 107 | + // Match *.chat.completions.create(...) |
| 108 | + createCall.getMethodName() = "create" and |
| 109 | + completionsAttr = createCall.getObject().getALocalSource() and |
| 110 | + completionsAttr.getAttributeName() = "completions" and |
| 111 | + chatAttr = completionsAttr.getObject().getALocalSource() and |
| 112 | + chatAttr.getAttributeName() = "chat" |
| 113 | + | |
| 114 | + // The messages keyword argument value (the list itself, or individual dict content values) |
| 115 | + result = createCall.getArgByName("messages") |
| 116 | + ) |
| 117 | + } |
| 118 | +} |
0 commit comments