undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
This commit is contained in:
parent
0a580b313d
commit
db29a08762
1311 changed files with 371202 additions and 1188 deletions
|
|
@ -0,0 +1,40 @@
|
|||
From: agent-blackops <blackops@unturf.com>
|
||||
Date: Thu, 26 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] playbook/role: replace seen list with identity-keyed set in get_vars()
|
||||
|
||||
CWE-407: Algorithmic complexity via O(D^2) linear scan deduplication in
|
||||
get_vars(). `seen` was a plain list used for membership testing inside
|
||||
an O(D) outer loop over get_all_dependencies(), producing O(D^2) total
|
||||
equality comparisons when D transitive dependencies exist.
|
||||
|
||||
Role defines __eq__ for value-based comparison but not __hash__, so a
|
||||
plain set() would raise TypeError at runtime. Fix: use id(dep) as the
|
||||
identity key — a parallel seen_ids set of integers gives O(1) average
|
||||
membership test and insertion. The TODO comment in the source already
|
||||
flagged this: "re-examine dep loading to see if we are somehow
|
||||
improperly adding the same dep too many times."
|
||||
|
||||
Defect-Id: ANS-001
|
||||
Severity: MEDIUM
|
||||
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
||||
---
|
||||
lib/ansible/playbook/role/__init__.py | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py
|
||||
index xxxxxxx..yyyyyyy 100644
|
||||
--- a/lib/ansible/playbook/role/__init__.py
|
||||
+++ b/lib/ansible/playbook/role/__init__.py
|
||||
@@ -536,11 +536,11 @@ class Role(Base, Become, Conditional, Taggable, Delegatable):
|
||||
# get exported variables from meta/dependencies
|
||||
- seen = []
|
||||
+ seen_ids = set() # CWE-407 fix: O(1) identity set
|
||||
for dep in self.get_all_dependencies():
|
||||
# Avoid rerunning dupe deps since they can have vars from previous invocations and they accumulate in deps
|
||||
# TODO: re-examine dep loading to see if we are somehow improperly adding the same dep too many times
|
||||
- if dep not in seen:
|
||||
+ if id(dep) not in seen_ids: # CWE-407 fix: O(1) vs O(D)
|
||||
# only take 'exportable' vars from deps
|
||||
all_vars = combine_vars(all_vars, dep.get_vars(include_params=False, only_exports=True))
|
||||
- seen.append(dep)
|
||||
+ seen_ids.add(id(dep)) # CWE-407 fix: O(1)
|
||||
62
defects/ansible/patch/ans-0002-role-collections-set.patch
Normal file
62
defects/ansible/patch/ans-0002-role-collections-set.patch
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
From: agent-blackops <blackops@unturf.com>
|
||||
Date: Thu, 26 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] playbook/role: maintain parallel _collections_set for O(1) membership in _load_role_data()
|
||||
|
||||
CWE-407: Algorithmic complexity via O(C) list membership tests in
|
||||
_load_role_data(). self.collections is a list; the generator expression
|
||||
`c not in self.collections` performs an O(C) linear scan for each
|
||||
candidate collection, and the two subsequent `not in self.collections`
|
||||
guards for 'ansible.builtin' and 'ansible.legacy' add two more O(C)
|
||||
scans — O(C) total per call where C = current collections length.
|
||||
|
||||
Fix: maintain a parallel _collections_set (Python set) as a shadow of
|
||||
self.collections. All membership tests become O(1). The list is
|
||||
retained unchanged so that ordering semantics (insert(0, ...), append)
|
||||
are preserved; _collections_set is kept in sync at every mutation site.
|
||||
|
||||
Defect-Id: ANS-002
|
||||
Severity: LOW
|
||||
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
||||
---
|
||||
lib/ansible/playbook/role/__init__.py | 20 ++++++++++++--------
|
||||
1 file changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py
|
||||
index xxxxxxx..yyyyyyy 100644
|
||||
--- a/lib/ansible/playbook/role/__init__.py
|
||||
+++ b/lib/ansible/playbook/role/__init__.py
|
||||
@@ -268,7 +268,9 @@ class Role(Base, Become, Conditional, Taggable, Delegatable):
|
||||
# reset collections list; roles do not inherit collections from parents, just use the defaults
|
||||
# FUTURE: use a private config default for this so we can allow it to be overridden later
|
||||
self.collections = []
|
||||
+ self._collections_set = set() # CWE-407 fix: shadow set for O(1) membership
|
||||
|
||||
@@ -274,7 +276,8 @@ class Role(Base, Become, Conditional, Taggable, Delegatable):
|
||||
if self._role_collection: # this is a collection-hosted role
|
||||
self.collections.insert(0, self._role_collection)
|
||||
+ self._collections_set.add(self._role_collection) # CWE-407 fix: keep in sync
|
||||
else: # this is a legacy role, but set the default collection if there is one
|
||||
default_collection = AnsibleCollectionConfig.default_collection
|
||||
if default_collection:
|
||||
self.collections.insert(0, default_collection)
|
||||
+ self._collections_set.add(default_collection) # CWE-407 fix: keep in sync
|
||||
# legacy role, ensure all plugin dirs under the role are added to plugin search path
|
||||
add_all_plugin_dirs(self._role_path)
|
||||
|
||||
@@ -285,14 +289,14 @@ class Role(Base, Become, Conditional, Taggable, Delegatable):
|
||||
# collections can be specified in metadata for legacy or collection-hosted roles
|
||||
if self._metadata.collections:
|
||||
- self.collections.extend((c for c in self._metadata.collections if c not in self.collections))
|
||||
+ for c in self._metadata.collections: # CWE-407 fix
|
||||
+ if c not in self._collections_set: # CWE-407 fix: O(1) vs O(C)
|
||||
+ self.collections.append(c)
|
||||
+ self._collections_set.add(c) # CWE-407 fix: keep in sync
|
||||
|
||||
# if any collections were specified, ensure that core or legacy synthetic collections are always included
|
||||
if self.collections:
|
||||
# default append collection is core for collection-hosted roles, legacy for others
|
||||
default_append_collection = 'ansible.builtin' if self._role_collection else 'ansible.legacy'
|
||||
- if 'ansible.builtin' not in self.collections and 'ansible.legacy' not in self.collections:
|
||||
+ if 'ansible.builtin' not in self._collections_set and 'ansible.legacy' not in self._collections_set: # CWE-407 fix: O(1)
|
||||
self.collections.append(default_append_collection)
|
||||
+ self._collections_set.add(default_append_collection) # CWE-407 fix: keep in sync
|
||||
Loading…
Add table
Add a link
Reference in a new issue